Skip to content

Commit 5e0a205

Browse files
fix: use IP restrictions instead of internal ingress for Container App WAF
Internal Container App Environment ingress causes DNS resolution issues for the frontend App Service proxy. Switch to external ingress with VNet-only IP security restrictions (allow 10.0.0.0/8, deny all else). Also update post-deploy scripts to detect IP restrictions in addition to internal ingress when routing through the frontend proxy. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7e8dd36 commit 5e0a205

6 files changed

Lines changed: 96 additions & 24 deletions

File tree

infra/main.bicep

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,8 +1142,8 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2
11421142
tags: tags
11431143
enableTelemetry: enableTelemetry
11441144
// WAF aligned configuration for Private Networking
1145-
publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled'
1146-
internal: enablePrivateNetworking ? true : false
1145+
publicNetworkAccess: 'Enabled' // Always enabling the publicNetworkAccess for Container App Environment
1146+
internal: false // Must be false when publicNetworkAccess is'Enabled'
11471147
infrastructureSubnetResourceId: enablePrivateNetworking ? virtualNetwork.?outputs.?containerSubnetResourceId : null
11481148
// WAF aligned configuration for Monitoring
11491149
appLogsConfiguration: enableMonitoring
@@ -1191,7 +1191,15 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = {
11911191
environmentResourceId: containerAppEnvironment.outputs.resourceId
11921192
managedIdentities: { userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] }
11931193
ingressTargetPort: 8000
1194-
ingressExternal: enablePrivateNetworking ? false : true
1194+
ingressExternal: true
1195+
ipSecurityRestrictions: enablePrivateNetworking ? [
1196+
{
1197+
name: 'allow-vnet-only'
1198+
action: 'Allow'
1199+
ipAddressRange: '10.0.0.0/8'
1200+
description: 'Allow VNet traffic only'
1201+
}
1202+
] : []
11951203
activeRevisionsMode: 'Single'
11961204
corsPolicy: {
11971205
allowedOrigins: [
@@ -1399,7 +1407,15 @@ module containerAppMcp 'br/public:avm/res/app/container-app:0.18.1' = {
13991407
environmentResourceId: containerAppEnvironment.outputs.resourceId
14001408
managedIdentities: { userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] }
14011409
ingressTargetPort: 9000
1402-
ingressExternal: enablePrivateNetworking ? false : true
1410+
ingressExternal: true
1411+
ipSecurityRestrictions: enablePrivateNetworking ? [
1412+
{
1413+
name: 'allow-vnet-only'
1414+
action: 'Allow'
1415+
ipAddressRange: '10.0.0.0/8'
1416+
description: 'Allow VNet traffic only'
1417+
}
1418+
] : []
14031419
activeRevisionsMode: 'Single'
14041420
corsPolicy: {
14051421
allowedOrigins: [

infra/main.parameters.json

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,35 @@
4848
"value": "${AZURE_ENV_REASONING_MODEL_CAPACITY}"
4949
},
5050
"backendContainerImageTag": {
51-
"value": "${AZURE_ENV_IMAGE_TAG}"
51+
"value": "${AZURE_ENV_IMAGE_TAG=latest_v4}"
5252
},
5353
"frontendContainerImageTag": {
54-
"value": "${AZURE_ENV_IMAGE_TAG}"
54+
"value": "${AZURE_ENV_IMAGE_TAG=latest_v4}"
5555
},
5656
"MCPContainerImageTag": {
57-
"value": "${AZURE_ENV_IMAGE_TAG}"
57+
"value": "${AZURE_ENV_IMAGE_TAG=latest_v4}"
5858
},
5959
"enableTelemetry": {
6060
"value": "${AZURE_ENV_ENABLE_TELEMETRY}"
6161
},
62+
"enableMonitoring": {
63+
"value": true
64+
},
65+
"enablePrivateNetworking": {
66+
"value": true
67+
},
68+
"enableScalability": {
69+
"value": false
70+
},
71+
"virtualMachineAdminUsername": {
72+
"value": "${AZURE_ENV_VM_ADMIN_USERNAME}"
73+
},
74+
"virtualMachineAdminPassword": {
75+
"value": "${AZURE_ENV_VM_ADMIN_PASSWORD}"
76+
},
77+
"virtualMachineSize": {
78+
"value": "${AZURE_ENV_VM_SIZE}"
79+
},
6280
"existingLogAnalyticsWorkspaceId": {
6381
"value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}"
6482
},
@@ -73,6 +91,25 @@
7391
},
7492
"MCPContainerRegistryHostname": {
7593
"value": "${AZURE_ENV_CONTAINER_REGISTRY_ENDPOINT}"
94+
},
95+
"allowedFqdnList": {
96+
"value": [
97+
"mcr.microsoft.com",
98+
"openai.azure.com",
99+
"cognitiveservices.azure.com",
100+
"login.microsoftonline.com",
101+
"management.azure.com",
102+
"aiinfra.azure.com",
103+
"aiinfra.azure.net",
104+
"aiinfra.azureedge.net",
105+
"blob.core.windows.net",
106+
"database.windows.net",
107+
"vault.azure.net",
108+
"monitoring.azure.com",
109+
"dc.services.visualstudio.com",
110+
"azconfig.io",
111+
"azconfig.azure.net"
112+
]
76113
}
77114
}
78115
}

infra/main_custom.bicep

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,8 +1140,8 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2
11401140
tags: tags
11411141
enableTelemetry: enableTelemetry
11421142
// WAF aligned configuration for Private Networking
1143-
publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled'
1144-
internal: enablePrivateNetworking ? true : false
1143+
publicNetworkAccess: 'Enabled' // Always enabling the publicNetworkAccess for Container App Environment
1144+
internal: false // Must be false when publicNetworkAccess is'Enabled'
11451145
infrastructureSubnetResourceId: enablePrivateNetworking ? virtualNetwork.?outputs.?containerSubnetResourceId : null
11461146
// WAF aligned configuration for Monitoring
11471147
appLogsConfiguration: enableMonitoring
@@ -1218,7 +1218,15 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = {
12181218
environmentResourceId: containerAppEnvironment.outputs.resourceId
12191219
managedIdentities: { userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] }
12201220
ingressTargetPort: 8000
1221-
ingressExternal: enablePrivateNetworking ? false : true
1221+
ingressExternal: true
1222+
ipSecurityRestrictions: enablePrivateNetworking ? [
1223+
{
1224+
name: 'allow-vnet-only'
1225+
action: 'Allow'
1226+
ipAddressRange: '10.0.0.0/8'
1227+
description: 'Allow VNet traffic only'
1228+
}
1229+
] : []
12221230
activeRevisionsMode: 'Single'
12231231
corsPolicy: {
12241232
allowedOrigins: [
@@ -1441,7 +1449,15 @@ module containerAppMcp 'br/public:avm/res/app/container-app:0.18.1' = {
14411449
environmentResourceId: containerAppEnvironment.outputs.resourceId
14421450
managedIdentities: { userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] }
14431451
ingressTargetPort: 9000
1444-
ingressExternal: enablePrivateNetworking ? false : true
1452+
ingressExternal: true
1453+
ipSecurityRestrictions: enablePrivateNetworking ? [
1454+
{
1455+
name: 'allow-vnet-only'
1456+
action: 'Allow'
1457+
ipAddressRange: '10.0.0.0/8'
1458+
description: 'Allow VNet traffic only'
1459+
}
1460+
] : []
14451461
activeRevisionsMode: 'Single'
14461462
corsPolicy: {
14471463
allowedOrigins: [

infra/scripts/Selecting-Team-Config-And-Data.ps1

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -445,18 +445,20 @@ do {
445445
}
446446
} while (-not $useCaseValid)
447447

448-
# WAF/Private Networking: If the Container App ingress is internal, the backendUrl
449-
# is not reachable from the developer's machine. Route through the frontend App Service
450-
# proxy instead, which is public and forwards /api/* to the private backend over VNet.
448+
# WAF/Private Networking: If the Container App has IP restrictions or internal ingress,
449+
# the backendUrl is not reachable from the developer's machine. Route through the frontend
450+
# App Service proxy instead, which is public and forwards /api/* to the private backend over VNet.
451451
$solutionSuffix = az group show --name $ResourceGroup --query "tags.SolutionSuffix" -o tsv 2>$null
452452
if ($solutionSuffix) {
453453
$containerAppName = "ca-$solutionSuffix"
454-
$isInternal = az containerapp show --name $containerAppName --resource-group $ResourceGroup `
454+
$isExternal = az containerapp show --name $containerAppName --resource-group $ResourceGroup `
455455
--query "properties.configuration.ingress.external" -o tsv 2>$null
456-
if ($isInternal -eq "false") {
456+
$hasIpRestrictions = az containerapp show --name $containerAppName --resource-group $ResourceGroup `
457+
--query "length(properties.configuration.ingress.ipSecurityRestrictions || ``[]``)" -o tsv 2>$null
458+
if ($isExternal -eq "false" -or [int]$hasIpRestrictions -gt 0) {
457459
$frontendHostname = "app-$solutionSuffix"
458460
$frontendUrl = "https://${frontendHostname}.azurewebsites.net"
459-
Write-Host "Private networking detected: Container App ingress is internal."
461+
Write-Host "Private networking detected: Container App has restricted access."
460462
Write-Host "Routing API calls through frontend App Service: $frontendUrl"
461463
$script:backendUrl = $frontendUrl
462464
}

infra/scripts/selecting_team_config_and_data.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -453,18 +453,20 @@ while [[ "$useCaseValid" != true ]]; do
453453
fi
454454
done
455455

456-
# WAF/Private Networking: If the Container App ingress is internal, the backendUrl
457-
# is not reachable from the developer's machine. Route through the frontend App Service
458-
# proxy instead, which is public and forwards /api/* to the private backend over VNet.
456+
# WAF/Private Networking: If the Container App has IP restrictions or internal ingress,
457+
# the backendUrl is not reachable from the developer's machine. Route through the frontend
458+
# App Service proxy instead, which is public and forwards /api/* to the private backend over VNet.
459459
solutionSuffix=$(az group show --name "$ResourceGroup" --query "tags.SolutionSuffix" -o tsv 2>/dev/null)
460460
if [[ -n "$solutionSuffix" ]]; then
461461
containerAppName="ca-${solutionSuffix}"
462462
isExternal=$(az containerapp show --name "$containerAppName" --resource-group "$ResourceGroup" \
463463
--query "properties.configuration.ingress.external" -o tsv 2>/dev/null)
464-
if [[ "$isExternal" == "false" ]]; then
464+
hasIpRestrictions=$(az containerapp show --name "$containerAppName" --resource-group "$ResourceGroup" \
465+
--query "length(properties.configuration.ingress.ipSecurityRestrictions || \`[]\`)" -o tsv 2>/dev/null)
466+
if [[ "$isExternal" == "false" ]] || [[ "$hasIpRestrictions" -gt 0 ]]; then
465467
frontendHostname="app-${solutionSuffix}"
466468
frontendUrl="https://${frontendHostname}.azurewebsites.net"
467-
echo "Private networking detected: Container App ingress is internal."
469+
echo "Private networking detected: Container App has restricted access."
468470
echo "Routing API calls through frontend App Service: $frontendUrl"
469471
backendUrl="$frontendUrl"
470472
fi

src/frontend/Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ WORKDIR /app
3434
COPY pyproject.toml requirements.txt* uv.lock* ./
3535

3636
# Install Python dependencies using UV
37-
RUN --mount=type=cache,target=/root/.cache/uv \
38-
if [ -f "requirements.txt" ]; then \
37+
RUN if [ -f "requirements.txt" ]; then \
3938
uv pip install --system -r requirements.txt && uv pip install --system "uvicorn[standard]"; \
4039
else \
4140
uv pip install --system pyproject.toml && uv pip install --system "uvicorn[standard]"; \

0 commit comments

Comments
 (0)