Skip to content

Container Communication & Configuration Analysis

Date: 2025-10-22
Status: ⚠️ ISSUES FOUND - NEEDS FIXES


🔍 Analysis Summary

✅ What's Working:

  1. Bicep Passes AI Endpoints to API Container
  2. AZURE_AI_ENDPOINT
  3. AZURE_AI_PROJECT_ENDPOINT
  4. AZURE_AI_MODEL_DEPLOYMENT_NAME
  5. Configured in layer4-apps.bicep and passed to container-app-api.bicep

  6. Managed Identity Assigned

  7. API container has user-assigned managed identity ✅
  8. Identity is configured for ACR pull ✅
  9. Code uses DefaultAzureCredential ✅ (from logs)

  10. MCP URLs Passed to API

  11. Internal URLs constructed correctly ✅
  12. Uses Container Apps Environment default domain ✅

  13. UI Gets API URL

  14. VITE_API_URL set to API internal URL ✅

  15. CORS Configured in Code

  16. FastAPI has CORSMiddleware
  17. Config loaded from settings.get_cors_config()

❌ Issues Found:

Issue 1: CORS Origins Hardcoded to Localhost

Problem:

# apps/api/loan_defenders/api/config.py
cors_origins: list[str] | str = [
    "http://localhost:5173",  # Vite dev servers
    "http://localhost:5174",
    # ... more localhost ports
    "http://localhost:3000",
]

Impact: - UI deployed to Azure (ldfdevnew-ui-dev.*.azurecontainerapps.io) will be BLOCKED by CORS - API will reject all requests from the actual UI domain

Expected: - CORS should allow the actual UI Container App URL - Should be configured via environment variable


Issue 2: CORS Origins Not Passed as Environment Variable

Location: infrastructure/bicep/modules/container-app-api.bicep

Current: NO CORS_ORIGINS or APP_CORS_ORIGINS environment variable passed

Should Have:

{
  name: 'APP_CORS_ORIGINS'
  value: uiContainerAppUrl  // UI's actual URL
}


Issue 3: UI Container App URL Not Available at API Deployment

Problem: Chicken-and-egg situation

Current Flow: 1. RBAC module deploys first 2. UI module deploys 3. API module deploys (doesn't know UI URL yet) 4. MCP modules deploy

What Happens: - API is deployed before we know UI's URL - Can't pass UI URL to API as CORS origin

Potential Solutions: 1. Option A: Use wildcard CORS for Container Apps Environment domain

https://*.{containerAppsEnvDefaultDomain}

  1. Option B: Deploy API, then update with UI URL after UI deploys
  2. Requires 2-phase deployment
  3. Not ideal for idempotency

  4. Option C: Use known predictable UI URL

  5. Construct URL same way as MCP URLs
    https://${deploymentPrefix}-ui-${environment}.${containerAppsEnvDefaultDomain}
    

Issue 4: API URL Passed to UI May Be Wrong

Current:

var apiBackendUrl = deployAPI ? 'https://${apiContainerAppName}.${containerAppsEnvDefaultDomain}' : ''

Concern: - apiContainerAppName might not match actual Container App resource name - Need to verify naming consistency


📋 Required Fixes

Fix 1: Add CORS Environment Variable to API

File: infrastructure/bicep/modules/container-app-api.bicep

Add after existing env vars:

{
  name: 'APP_CORS_ORIGINS'
  value: corsOrigins  // New parameter
}

Add parameter:

@description('CORS allowed origins (comma-separated)')
param corsOrigins string


Fix 2: Construct UI URL in Layer 4 Orchestrator

File: infrastructure/bicep/layer4-apps.bicep

Add after line ~195:

// Construct UI URL for CORS (predictable, doesn't depend on deployment order)
var uiContainerAppUrl = deployUI ? 'https://${deploymentPrefix}-ui-${environment}.${containerAppsEnvDefaultDomain}' : ''

// CORS origins for API (allow UI + localhost for development)
var apiCorsOrigins = deployUI ? '${uiContainerAppUrl},http://localhost:5173,http://localhost:3000' : 'http://localhost:5173,http://localhost:3000'


Fix 3: Pass CORS to API Module

File: infrastructure/bicep/layer4-apps.bicep

Update API module call (around line 256):

module apiContainerApp 'modules/container-app-api.bicep' = if (deployAPI) {
  name: 'api-container-app-deployment'
  params: {
    // ... existing params
    corsOrigins: apiCorsOrigins  // ADD THIS
  }
}


Fix 4: Verify Container App Naming

Check that these match:

Bicep Name Construction:

var uiContainerAppName = '${deploymentPrefix}-ui-${environment}'
var apiContainerAppName = '${deploymentPrefix}-api-${environment}'

Container Apps Module:

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  name: containerAppName  // Passed from orchestrator
}

MCP Server Names:

var mcpServerNames = {
  verification: '${deploymentPrefix}-mcp-application-verification-${environment}'
  documents: '${deploymentPrefix}-mcp-document-processing-${environment}'
  financial: '${deploymentPrefix}-mcp-financial-calculations-${environment}'
}


✅ What's Already Correct

1. Managed Identity for AI Authentication

Container Apps Bicep:

identity: useUserAssignedIdentity ? {
  type: 'UserAssigned'
  userAssignedIdentities: {
    '${userAssignedIdentityId}': {}
  }
} : {
  type: 'SystemAssigned'
}

API Code (apps/api):

# Uses DefaultAzureCredential which automatically uses managed identity
from azure.identity.aio import DefaultAzureCredential

Result: ✅ API will authenticate to Azure AI using managed identity


2. AI Endpoint Configuration

Bash Script Discovery:

azure_ai_endpoint=$(get_azure_ai_endpoint "$rg_name" "$prefix" "$ENVIRONMENT")
ai_project_endpoint=$(get_ai_project_endpoint "$rg_name" "$prefix")
ai_model_deployment_name=$(jq -r '.parameters.azureAiModelDeploymentName.value' "$param_file")

Bicep Passes to Container:

{
  name: 'AZURE_AI_ENDPOINT'
  value: azureAiEndpoint
}
{
  name: 'AZURE_AI_PROJECT_ENDPOINT'  
  value: azureAiProjectEndpoint
}
{
  name: 'AZURE_AI_MODEL_DEPLOYMENT_NAME'
  value: azureAiModelDeploymentName
}

Result: ✅ API knows where to call AI models


3. MCP Server URLs

Constructed Correctly:

var mcpVerificationUrl = deployMCP ? 'https://${deploymentPrefix}-mcp-application-verification-${environment}.${containerAppsEnvDefaultDomain}' : ''

Passed to API:

{
  name: 'MCP_APPLICATION_VERIFICATION_URL'
  value: !empty(mcpVerificationUrl) ? '${mcpVerificationUrl}/mcp' : ''
}

Result: ✅ API can call MCP servers


🚀 Implementation Plan

Priority 1: Fix CORS (CRITICAL)

Without this, UI → API communication will fail in Azure.

  1. Add corsOrigins parameter to container-app-api.bicep
  2. Construct uiContainerAppUrl in layer4-apps.bicep
  3. Build apiCorsOrigins string with UI URL + localhost
  4. Pass to API module
  5. API code already reads from environment ✅

Estimated Time: 15 minutes


Priority 2: Verify Naming Consistency

Ensure URL construction matches actual resource names.

Test After Deployment:

# Get actual names
az containerapp list --resource-group ldfdevnew-cicd-rg --query "[].name" -o tsv

# Compare to expected
echo "Expected UI: ldfdevnew-cicd-ui-dev"
echo "Expected API: ldfdevnew-cicd-api-dev"

Estimated Time: 5 minutes


Priority 3: Document Communication Flow

Create diagram showing: - UI → API (CORS) - API → AI Services (Managed Identity) - API → MCP Servers (Internal HTTPS)

Estimated Time: 10 minutes


📊 Communication Matrix

From To Method Auth Status
UI API HTTPS + CORS None (public API) ❌ CORS blocked
API Azure AI HTTPS Managed Identity ✅ Configured
API MCP Verification HTTPS Internal None (internal) ✅ Configured
API MCP Documents HTTPS Internal None (internal) ✅ Configured
API MCP Financial HTTPS Internal None (internal) ✅ Configured

✅ Testing Checklist

After fixes:

  • Deploy Layer 4
  • Get UI URL: az containerapp show --name ... --query properties.configuration.ingress.fqdn
  • Access UI in browser
  • Open browser console
  • Try to make API call
  • Should NOT see CORS error
  • API should respond successfully
  • Check API logs for AI authentication (should use managed identity)
  • Check API logs for MCP server calls (should reach internal URLs)

  • infrastructure/bicep/layer4-apps.bicep - Orchestrator
  • infrastructure/bicep/modules/container-app-api.bicep - API module
  • infrastructure/bicep/modules/container-app-ui.bicep - UI module
  • apps/api/loan_defenders/api/config.py - CORS config
  • apps/api/loan_defenders/api/app.py - CORS middleware
  • infrastructure/scripts/deploy-layer4.sh - Deployment script

Next Action: Apply CORS fixes before testing deployment