Skip to content

fix : WAF deployment: private backend ingress and frontend proxy rou…#561

Open
Ashwal-Microsoft wants to merge 2 commits intodevfrom
waf-private-backend-20260423
Open

fix : WAF deployment: private backend ingress and frontend proxy rou…#561
Ashwal-Microsoft wants to merge 2 commits intodevfrom
waf-private-backend-20260423

Conversation

@Ashwal-Microsoft
Copy link
Copy Markdown

…ting

Purpose

When enablePrivateNetworking (WAF mode) is active, the backend Container App URL should not be exposed to the browser. This PR adds an application-layer proxy so the browser only communicates with the frontend App Service.

When deploying these accelerators using the WAF deployment option, the expectation is that the backend APIs hosted on Container Apps are secured behind the WAF and are not directly accessible from the public internet. However, the current implementation leaves the Container App API endpoints publicly exposed, which undermines the security posture of the WAF deployment model.

Expected Behavior
The Web App (frontend) should remain publicly accessible through the WAF/Application Gateway.
All backend Container App API endpoints should be private and only accessible internally (e.g., via Container Apps Environment VNet integration, internal ingress, or Private Endpoints).
External users should not be able to directly call the backend Container App API endpoints from outside the network boundary.

Does this introduce a breaking change?

  • Yes
  • No

Golden Path Validation

  • I have tested the primary workflows (the "golden path") to ensure they function correctly without errors.

Deployment Validation

  • I have validated the deployment process successfully and all services are running as expected with this change.

What to Check

Verify that the following are valid

  • ...

Other Information

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to harden the enablePrivateNetworking=true (“WAF mode”) deployment by preventing browsers from calling the backend Container App endpoint directly, instead routing browser API traffic through the frontend container as an application-layer proxy.

Changes:

  • Add an nginx /api/* reverse proxy in the web container to forward requests to the backend API.
  • Update infra to make the API ingress internal-only in private networking mode and introduce a private DNS zone for the Container Apps Environment domain.
  • Update docs to describe the private networking/WAF traffic flow.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/ContentProcessorWeb/nginx-custom.conf Adds /api/ reverse-proxying from the web container to the backend API URL.
src/ContentProcessorWeb/env.sh Extends APP_* placeholder substitution to /etc/nginx/nginx.conf so nginx can be templated at runtime.
infra/main.bicep Switches CAE to internal + disables public network access in private networking mode; makes API ingress internal-only; adds CAE private DNS zone; updates web env vars for /api base URL.
infra/main_custom.bicep Same as infra/main.bicep for the custom deployment template.
docs/TechnicalArchitecture.md Documents the /api proxy behavior for private networking deployments.
docs/DeploymentGuide.md Documents the expected networking posture and proxying behavior in WAF/private networking deployments.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +21 to +31
# Route browser API calls through the web container so private backend
# endpoints remain internal-only in WAF/private networking deployments.
location /api/ {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass APP_BACKEND_API_URL/;
}
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

location /api/ relies on proxy_pass APP_BACKEND_API_URL/; being substituted at runtime. If APP_BACKEND_API_URL is not set in the container environment, env.sh will not replace the placeholder and nginx will fail to start due to an invalid proxy_pass URL. Ensure all deployment paths that run this image always set APP_BACKEND_API_URL (even when the app is not using the /api proxy), or adjust the nginx config/entrypoint to provide a safe default when the variable is missing.

Copilot uses AI. Check for mistakes.
Comment thread infra/main.bicep
Comment on lines +934 to +935
publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled'
internal: enablePrivateNetworking ? true : false
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the Container Apps Environment to internal: true and publicNetworkAccess: 'Disabled' means the environment (and therefore the web Container App inside it) will be reachable only within the VNet. This conflicts with the template still configuring the web Container App ingress as external (ingressExternal: true later in this file). Either keep the environment external and make only the API app's ingress internal, or also make the web app ingress/internal routing consistent with an internal environment (and document the required WAF/App Gateway in front).

Suggested change
publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled'
internal: enablePrivateNetworking ? true : false
publicNetworkAccess: 'Enabled'
internal: false

Copilot uses AI. Check for mistakes.
Comment thread infra/main.bicep
]
}
ingressExternal: true
ingressExternal: enablePrivateNetworking ? false : true
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With ingressExternal set to false in private networking mode, the API Container App FQDN will no longer be reachable from outside the VNet. The repo's post-deployment scripts currently use CONTAINER_API_APP_FQDN to wait for readiness and register schemas from the deployer's machine; that flow will fail for enablePrivateNetworking=true. Consider updating the post-deployment workflow to call the API through the web app's new /api proxy (using CONTAINER_WEB_APP_FQDN) or to execute the registration from within the VNet (e.g., via the jumpbox).

Suggested change
ingressExternal: enablePrivateNetworking ? false : true
ingressExternal: true

Copilot uses AI. Check for mistakes.
Comment thread infra/main_custom.bicep
Comment on lines +937 to +938
publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled'
internal: enablePrivateNetworking ? true : false
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the Container Apps Environment to internal: true and publicNetworkAccess: 'Disabled' means the environment (and therefore the web Container App inside it) will be reachable only within the VNet. This conflicts with the template still configuring the web Container App ingress as external (ingressExternal: true later in this file). Either keep the environment external and make only the API app's ingress internal, or also make the web app ingress/internal routing consistent with an internal environment (and document the required WAF/App Gateway in front).

Suggested change
publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled'
internal: enablePrivateNetworking ? true : false
publicNetworkAccess: 'Enabled'
internal: false

Copilot uses AI. Check for mistakes.
Comment thread infra/main_custom.bicep
]
}
ingressExternal: true
ingressExternal: enablePrivateNetworking ? false : true
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With ingressExternal set to false in private networking mode, the API Container App FQDN will no longer be reachable from outside the VNet. The repo's post-deployment scripts currently use CONTAINER_API_APP_FQDN to wait for readiness and register schemas from the deployer's machine; that flow will fail for enablePrivateNetworking=true. Consider updating the post-deployment workflow to call the API through the web app's new /api proxy (using CONTAINER_WEB_APP_FQDN) or to execute the registration from within the VNet (e.g., via the jumpbox).

Suggested change
ingressExternal: enablePrivateNetworking ? false : true
ingressExternal: true

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants