From 757f3d79e992baf0aa0888299d2876585b612c69 Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Tue, 31 Mar 2026 19:25:27 +0530 Subject: [PATCH 1/2] fix post deployment script --- infra/scripts/post_deployment.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/infra/scripts/post_deployment.sh b/infra/scripts/post_deployment.sh index 2a3e5d0c..2f9eab9c 100644 --- a/infra/scripts/post_deployment.sh +++ b/infra/scripts/post_deployment.sh @@ -98,8 +98,8 @@ else # Read schema entries from manifest SCHEMA_COUNT=$(cat "$SCHEMA_INFO_FILE" | grep -o '"File"' | wc -l) - REGISTERED_IDS="" - REGISTERED_NAMES="" + REGISTERED_IDS=() + REGISTERED_NAMES=() for idx in $(seq 0 $((SCHEMA_COUNT - 1))); do # Parse entry fields using grep/sed (no python needed) @@ -128,8 +128,8 @@ else if [ -n "$EXISTING_ID" ]; then echo " Schema '$CLASS_NAME' already exists with ID: $EXISTING_ID" - REGISTERED_IDS="$REGISTERED_IDS $EXISTING_ID" - REGISTERED_NAMES="$REGISTERED_NAMES $CLASS_NAME" + REGISTERED_IDS+=("$EXISTING_ID") + REGISTERED_NAMES+=("$CLASS_NAME") continue fi @@ -148,8 +148,8 @@ else if [ "$HTTP_CODE" = "200" ]; then SCHEMA_ID=$(echo "$BODY" | sed 's/.*"Id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/') echo " Successfully registered: $DESCRIPTION's Schema Id - $SCHEMA_ID" - REGISTERED_IDS="$REGISTERED_IDS $SCHEMA_ID" - REGISTERED_NAMES="$REGISTERED_NAMES $CLASS_NAME" + REGISTERED_IDS+=("$SCHEMA_ID") + REGISTERED_NAMES+=("$CLASS_NAME") else echo " Failed to upload '$FILE_NAME'. HTTP Status: $HTTP_CODE" echo " Error Response: $BODY" @@ -205,10 +205,9 @@ else ALREADY_IN_SET=$(curl -s "${SCHEMASETVAULT_URL}${SCHEMASET_ID}/schemas" 2>/dev/null || echo "[]") # Iterate over registered schemas - IDX=0 - for SCHEMA_ID in $REGISTERED_IDS; do - IDX=$((IDX + 1)) - CLASS_NAME=$(echo "$REGISTERED_NAMES" | tr ' ' '\n' | sed -n "${IDX}p") + for i in "${!REGISTERED_IDS[@]}"; do + SCHEMA_ID="${REGISTERED_IDS[$i]}" + CLASS_NAME="${REGISTERED_NAMES[$i]}" if echo "$ALREADY_IN_SET" | grep -q "\"Id\"[[:space:]]*:[[:space:]]*\"$SCHEMA_ID\""; then echo " Schema '$CLASS_NAME' ($SCHEMA_ID) already in schema set - skipped" @@ -236,5 +235,6 @@ else echo "" echo "============================================================" echo "Schema registration process completed." + echo " Schemas registered: ${#REGISTERED_IDS[@]}" echo "============================================================" fi From 774da96e8edbad1087f2e6a87f695f460b8e3f93 Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Fri, 3 Apr 2026 13:33:00 +0530 Subject: [PATCH 2/2] Add troubleshooot for 403 - content understanding --- docs/TroubleShootingSteps.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/TroubleShootingSteps.md b/docs/TroubleShootingSteps.md index 182907fc..6d4d60cd 100644 --- a/docs/TroubleShootingSteps.md +++ b/docs/TroubleShootingSteps.md @@ -27,6 +27,7 @@ Use these as quick reference guides to unblock your deployments. | **InternalSubscriptionIsOverQuotaForSku** | Subscription quota exceeded for the requested SKU | [View Solution](#quota--capacity-limitations) | | **InvalidResourceGroup** | Invalid resource group configuration | [View Solution](#resource-group--deployment-management) | | **RequestDisallowedByPolicy** | Azure Policy blocking the requested operation | [View Solution](#subscription--access-issues) | +| **403 Forbidden - Content Understanding** | Content Understanding returns 403 in WAF/private networking deployment | [View Solution](#network--infrastructure-configuration) | ## 📖 Table of Contents @@ -127,6 +128,7 @@ Use these as quick reference guides to unblock your deployments. | **RouteTableCannotBeAttachedForAzureBastionSubnet** | Route table attached to Azure Bastion subnet | This error occurs because Azure Bastion subnet (`AzureBastionSubnet`) has a platform restriction that prevents route tables from being attached.

**How to reproduce:**

**Resolution:**
| | **VMSizeIsNotPermittedToEnableAcceleratedNetworking** | VM size does not support accelerated networking | This error occurs when you attempt to enable accelerated networking on a VM size that does not support it. This deployment's jumpbox VM **requires** accelerated networking.

**Default VM size:** `Standard_D2s_v5` — supports accelerated networking.

**How this error happens:**

**Resolution:**
| | **NetworkSecurityGroupNotCompliantForAzureBastionSubnet** / **SecurityRuleParameterContainsUnsupportedValue** | NSG rules blocking required Azure Bastion ports | This error occurs when the Network Security Group (NSG) attached to `AzureBastionSubnet` explicitly denies inbound TCP ports 443 and/or 4443, which Azure Bastion requires for management and tunneling.

**How to reproduce:**

**Resolution:**
| +| **403 Forbidden - Content Understanding** | Azure AI Content Understanding returns 403 Forbidden in WAF (private networking) deployment | This error occurs when the **Azure AI Content Understanding** service returns a `403 Forbidden` response during document processing in a **WAF-enabled (private networking)** deployment.

**Why this happens:**
In WAF deployments (`enablePrivateNetworking=true`), the Content Understanding AI Services account (`aicu-`) is configured with `publicNetworkAccess: Disabled`. All traffic must flow through the **private endpoint** (`pep-aicu-`) and resolve via private DNS zones (`privatelink.cognitiveservices.azure.com`, `privatelink.services.ai.azure.com`, `privatelink.contentunderstanding.ai.azure.com`). If any part of this chain is misconfigured, the request either reaches the public endpoint (which is blocked) or fails to route entirely, resulting in a 403.

**Common causes:**
  • Private DNS zones not linked to the VNet — DNS resolution falls back to the public IP, which is blocked
  • Private endpoint connection is not in **Approved** state
  • Content Understanding is deployed in a different region (`contentUnderstandingLocation`, defaults to `WestUS`) than the main deployment — the private endpoint still works cross-region, but DNS misconfiguration is more likely
  • Container Apps are not injected into the VNet or are on a subnet that cannot reach the private endpoint
  • Managed Identity used by the Container App does not have the required **Cognitive Services User** role on the Content Understanding resource

**Resolution:**
  • **Verify private endpoint status:**
    `az network private-endpoint show --name pep-aicu- --resource-group --query "privateLinkServiceConnections[0].privateLinkServiceConnectionState.status"`
    Expected: `Approved`
  • **Verify private DNS zone VNet links:**
    `az network private-dns zone list --resource-group -o table`
    Ensure `privatelink.cognitiveservices.azure.com`, `privatelink.services.ai.azure.com`, and `privatelink.contentunderstanding.ai.azure.com` all have VNet links
  • **Test DNS resolution from the jumpbox VM** (inside the VNet):
    `nslookup aicu-.cognitiveservices.azure.com`
    Should resolve to a private IP (e.g., `10.x.x.x`), NOT a public IP
  • **Verify RBAC role assignments:** Ensure the Container App managed identity has **Cognitive Services User** role on the Content Understanding resource:
    `az role assignment list --scope /subscriptions//resourceGroups//providers/Microsoft.CognitiveServices/accounts/aicu- --query "[?roleDefinitionName=='Cognitive Services User']" -o table`
  • **Check Container App VNet integration:** Confirm the Container App Environment is deployed into the VNet and can reach the backend subnet where the private endpoint resides
  • **Redeploy if needed:**
    `azd up`

**Reference:**
  • [Configure private endpoints for Azure AI Services](https://learn.microsoft.com/en-us/azure/ai-services/cognitive-services-virtual-networks)
  • [Azure Private DNS zones](https://learn.microsoft.com/en-us/azure/dns/private-dns-overview)
| ---------------------------------