Securing Azure Container Apps Ingress and Network Isolation

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
Azure Container Apps abstracts the complexity of Kubernetes while providing a managed environment for containerized microservices. The trade-off for that abstraction is that security decisions that would be explicit in a self-managed Kubernetes environment are implicit in Container Apps -- and the implicit defaults favor accessibility over restriction.
By default, a Container App with external ingress enabled is accessible from the internet. There is no IP restriction, no WAF, no authentication requirement at the ingress layer (unless the application itself implements authentication), and no network isolation from other Container Apps environments in the same region. For a development workload, this is acceptable. For a production workload handling sensitive data, it is not.
The networking model for Container Apps has two layers of configuration. The environment level -- whether the Container Apps environment is deployed into a customer-managed virtual network or uses the Microsoft-managed shared network infrastructure -- determines the fundamental network isolation model. The app level -- external vs. internal ingress, IP restriction rules, traffic splitting -- controls how individual apps within the environment are exposed.
This guide covers the environment-level VNet injection pattern that provides private network isolation, the app-level ingress configuration that restricts exposure, the Application Gateway integration that provides WAF and IP restriction upstream of the Container Apps environment, Dapr security configuration for Container Apps that use the Dapr sidecar, and the Azure Policy definitions that enforce these requirements at the organization level.
Default Container Apps Ingress: What Is Exposed and Why
Understanding the default exposure helps scope the hardening work required.
Default environment (consumption plan, no VNet injection). When a Container Apps environment is created without specifying a virtual network, it is deployed into a Microsoft-managed shared network infrastructure. The environment receives a shared outbound IP and a managed ingress IP. Container Apps with external ingress enabled in this configuration are accessible from the internet on the environment's public IP. There is no network isolation between this environment and other tenants' Container Apps environments at the network layer -- isolation relies on the Container Apps platform's logical isolation, not network-level isolation.
External ingress by default. When a Container App is deployed with the Azure CLI using az containerapp create without specifying --ingress internal, it defaults to external ingress if ingress is enabled. The resulting FQDN (e.g., myapp.azurecontainerapps.io) resolves to a public IP and is accessible from any internet source with no restriction.
No IP restriction without explicit configuration. External Container Apps have no default IP restriction. The equivalent of a security group or firewall rule blocking traffic to the ingress does not exist without explicit configuration of either: IP security restrictions in the ingress configuration (available in the environment), or an upstream WAF/Application Gateway.
Authentication not provided by default. Container Apps supports Easy Auth (Azure AD-integrated authentication) but it is not enabled by default. An external Container App that does not implement application-layer authentication and does not have Easy Auth enabled accepts unauthenticated requests from any internet source.
Dapr sidecar API exposed within the environment. If Dapr is enabled for a Container App, the Dapr sidecar HTTP API (port 3500) is accessible to other apps within the same Container Apps environment. By default, there is no per-app Dapr API authentication -- any app in the environment can call the Dapr API of any other app.
Restricting Ingress to Internal Traffic Only
For Container Apps that do not need external internet access, internal ingress is the appropriate configuration. Internal ingress makes the Container App accessible only from within the virtual network.
Setting internal ingress via Azure CLI:
az containerapp ingress update \
--name myapp \
--resource-group myresourcegroup \
--type internal
With internal ingress, the Container App receives a private FQDN in the format myapp.internal.[environment-domain] that resolves to a private IP address within the Container Apps environment's subnet. This FQDN is only resolvable and accessible from within the virtual network.
Setting internal ingress in Bicep:
resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
name: 'myapp'
properties: {
configuration: {
ingress: {
external: false
targetPort: 8080
transport: 'http'
}
}
}
}
The external: false setting is the critical parameter.
VNet injection requirement for internal ingress to be meaningful. Internal ingress restricts accessibility to within the Container Apps environment's network. If the environment is not VNet-injected (not deployed into a customer-managed virtual network), "internal" means accessible from within Microsoft's shared network for that region -- other Container Apps environments in the same region potentially. For meaningful internal ingress isolation, the Container Apps environment must be deployed with VNet injection so that the internal network is your organization's controlled virtual network.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Virtual Network Integration and Private Endpoint Configuration
VNet injection deploys the Container Apps environment into a dedicated subnet within a customer-controlled Azure virtual network. This provides network-level isolation and enables connectivity to other Azure resources, on-premises networks, and private endpoint configuration.
Requirements for VNet-injected environment:
- Dedicated subnet with a minimum /23 CIDR (512 addresses) for Consumption plan environments
- Subnet must be delegated to
Microsoft.App/environments - No other resources in the dedicated subnet
- The subnet must have outbound internet access if the Container Apps need to pull images from public registries or access external services
Creating a VNet-injected environment:
az containerapp env create \
--name myenvironment \
--resource-group myresourcegroup \
--location eastus \
--infrastructure-subnet-resource-id /subscriptions/[subid]/resourceGroups/[rg]/providers/Microsoft.Network/virtualNetworks/[vnet]/subnets/[subnet] \
--internal-only true
The --internal-only true flag makes the environment's load balancer internal-only (no public IP on the environment's ingress), requiring all traffic to enter through the virtual network.
Private endpoint for the Container Apps environment. For environments that need to be accessed from on-premises networks without traversing the public internet, configure a private endpoint for the Container Apps environment in a separate subnet:
az network private-endpoint create \
--name myenv-pe \
--resource-group myresourcegroup \
--vnet-name myvnet \
--subnet pe-subnet \
--private-connection-resource-id [containerapp-env-resource-id] \
--group-id managedEnvironments \
--connection-name myenv-connection
Then create a Private DNS Zone for azurecontainerapps.io linked to the virtual network to ensure DNS resolution of the Container App FQDNs resolves to the private IP.
IP Restriction and WAF Integration via Application Gateway
For Container Apps that must accept external internet traffic, the recommended pattern is to route traffic through Azure Application Gateway with WAF enabled, which provides IP restriction, TLS termination, and OWASP rule-based protection upstream of the Container Apps environment.
Architecture pattern. Deploy the Container Apps environment with internal ingress and VNet injection. Place the Application Gateway in a separate subnet of the same virtual network. Configure Application Gateway to forward requests to the Container App's internal FQDN. External traffic reaches Application Gateway's public IP, traverses the WAF policy, and is forwarded to the internal Container App.
Application Gateway backend pool for Container Apps:
az network application-gateway address-pool create \
--gateway-name my-appgw \
--resource-group myresourcegroup \
--name containerapp-backend \
--servers myapp.internal.[environment-domain]
The backend pool uses the Container App's internal FQDN. Application Gateway resolves this within the VNet and forwards to the Container App's private IP.
WAF policy configuration. Enable the OWASP 3.2 ruleset on the Application Gateway WAF policy:
az network application-gateway waf-policy create \
--name my-waf-policy \
--resource-group myresourcegroup \
--type OWASP \
--version 3.2 \
--state Enabled \
--mode Prevention
Prevention mode blocks requests that match OWASP rules. Detection mode logs but does not block -- start in Detection mode and review logs for false positives before switching to Prevention.
IP restriction via Application Gateway. Configure custom WAF rules to block traffic from IP ranges not in your allowlist:
az network application-gateway waf-policy custom-rule create \
--policy-name my-waf-policy \
--resource-group myresourcegroup \
--name BlockUnknownSources \
--priority 100 \
--rule-type MatchRule \
--action Block \
--match-conditions '[{"matchVariables":[{"variableName":"RemoteAddr"}],"operator":"IPMatch","negationConditon":true,"matchValues":["203.0.113.0/24","198.51.100.0/24"]}]'
This blocks any request not originating from the specified IP ranges. Adjust the IP ranges to your allowlisted sources.
Dapr Component Security in Container Apps
Azure Container Apps integrates Dapr as a sidecar. Dapr components (secret stores, state stores, pub/sub, bindings) in Container Apps require specific security configuration to prevent unauthorized access to secrets and state.
Secret store: use Key Vault with managed identity, not component secret files. The Dapr secret store component should be backed by Azure Key Vault with managed identity authentication:
az containerapp env dapr-component set \
--name myenvironment \
--resource-group myresourcegroup \
--dapr-component-name secretstore \
--yaml - <<EOF
componentType: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: mykeyvault
- name: azureClientId
value: [managed-identity-client-id]
EOF
Using managed identity authentication (azureClientId pointing to the Container App's assigned managed identity) eliminates the need for client secrets in the Dapr component configuration. Managed identities are rotated automatically by Azure.
Scoping Dapr components to specific apps. Restrict Dapr components to only the Container Apps that need them using the scopes field:
scopes:
- myapp-frontend
- myapp-backend
Without scoping, any app in the Container Apps environment with Dapr enabled can access any Dapr component. Scoping limits component access to named apps only.
Dapr API mTLS between apps. Dapr automatically provisions mTLS between sidecars for service-to-service calls within the environment. Verify that mTLS is not disabled in the Dapr configuration -- the mtls.enabled setting should remain true (the default). Disabling mTLS exposes inter-service communication to network sniffing within the Container Apps environment.
Service invocation access control. Configure Dapr access control policies to restrict which apps can invoke which other apps via Dapr service invocation:
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: appconfig
spec:
accessControl:
defaultAction: deny
trustDomain: cluster.local
policies:
- appId: myapp-backend
defaultAction: allow
namespace: default
operations:
- name: /api/data
httpVerb: ['GET']
action: allow
The default action of deny requires explicit allow rules for each service-to-service invocation, enforcing least privilege between Container Apps.
Environment-Level Network Isolation Policies
Azure Policy enforces Container Apps network security requirements at the organization or subscription level, preventing deployments that violate security requirements before they reach production.
Policy: Require VNet injection for Container Apps environments. The built-in Azure Policy Container Apps environments should use virtual network injection can be assigned at the subscription or management group level to audit or deny environments created without VNet injection:
az policy assignment create \
--name require-vnet-injection \
--scope /subscriptions/[subscription-id] \
--policy /providers/Microsoft.Authorization/policyDefinitions/[built-in-policy-id] \
--enforcement-mode Default
Set --enforcement-mode Default (deny mode) to prevent non-compliant environments from being created. Use DoNotEnforce (audit mode) initially to assess the existing environment before enabling enforcement.
Policy: Deny external ingress without WAF. Create a custom policy that denies Container Apps with external ingress enabled if the environment is not fronted by Application Gateway with WAF. This requires a custom policy definition that checks for the presence of an Application Gateway backend pool configuration -- typically implemented as a deny policy on Container Apps with configuration.ingress.external = true without an associated Application Gateway resource tag or parameter.
Network Security Group on the Container Apps subnet. For VNet-injected environments, associate an NSG with the Container Apps subnet that allows:
- Inbound: TCP 443 from Application Gateway subnet (or Azure Front Door service tag)
- Inbound: Required Azure infrastructure ports (Container Apps requires specific inbound rules for platform management -- reference the Azure documentation for current required rules)
- Outbound: TCP 443 to Azure Container Registry (for image pulls), Azure Key Vault, and required Azure services
- Deny all other inbound and outbound traffic
Do not restrict Container Apps subnet traffic more aggressively than documented -- the platform requires specific connectivity for health checks and management operations.
The bottom line
Azure Container Apps defaults expose ingress publicly without IP restriction, WAF protection, or network isolation -- defaults that are appropriate for development but require explicit hardening for production. The two foundational controls are VNet injection (deploying the Container Apps environment into a customer-controlled virtual network rather than the Microsoft-managed shared network) and internal ingress (restricting the Container App to private FQDN accessible only within the VNet). External traffic should route through Azure Application Gateway with WAF enabled, providing OWASP rule-based protection and IP restriction upstream of the Container Apps environment. Dapr components must use managed identity authentication with Azure Key Vault as the secret store backend, component scoping to limit which apps can access which components, and service invocation access control policies with a default-deny posture. Azure Policy assignments at the subscription or management group level enforce these requirements and prevent non-compliant environments from being deployed.
Frequently asked questions
What is the difference between external and internal ingress in Azure Container Apps?
External ingress makes the Container App accessible from the internet via a public FQDN and public IP. Internal ingress makes the Container App accessible only from within the Container Apps environment's virtual network via a private FQDN that resolves to a private IP. External ingress is the default when ingress is enabled. Internal ingress requires either VNet injection for the environment (so the internal network is your organization's VNet) or explicit internal ingress configuration in the app settings.
What is VNet injection for Azure Container Apps and why is it needed?
VNet injection deploys the Container Apps environment into a customer-owned subnet within an Azure virtual network, rather than into Microsoft's managed shared network infrastructure. Without VNet injection, the environment is on shared Microsoft infrastructure and cannot use private endpoints, cannot access private Azure resources via private IP, and internal ingress means accessible from within Microsoft's shared region network rather than your organization's private network. VNet injection is required for meaningful network isolation, private connectivity to other Azure resources, and Private Endpoint configuration for the Container Apps environment.
Can I use Azure Front Door instead of Application Gateway for WAF and IP restriction?
Yes. Azure Front Door Premium provides WAF capabilities, DDoS protection, and global load balancing, and can be positioned in front of Container Apps environments. The architecture differs from Application Gateway: Front Door operates at the edge (global) rather than within the virtual network (regional). For Container Apps with VNet injection and internal ingress, Front Door requires the Private Link integration to reach the internal environment without exposing it publicly. Application Gateway is simpler for regional deployments where VNet adjacency is acceptable; Front Door is preferred for globally distributed deployments or when edge DDoS protection is a requirement.
What ports does Azure Container Apps require for platform management?
The Container Apps platform requires specific inbound connectivity to the environment's subnet for health checks, platform management, and Kubernetes control plane communication. Microsoft documents the required ports in the Container Apps networking documentation. The requirements include inbound from the AzureLoadBalancer and AzureCloud service tags on specific ports. If an NSG on the Container Apps subnet blocks these ports, the environment may enter a failed state or health checks may fail. Always reference the current Microsoft documentation for required NSG rules rather than inferring them, as they can change with platform updates.
How does Dapr mTLS work in Azure Container Apps?
Dapr automatically provisions mutual TLS (mTLS) between sidecars for service-to-service communication within the Container Apps environment. Each Dapr sidecar receives a certificate issued by the Dapr control plane. When App A calls App B via Dapr service invocation, the Dapr sidecars on both apps authenticate each other using these certificates before establishing the connection. The mTLS configuration is managed by the Dapr control plane embedded in the Container Apps environment -- you do not need to provision certificates manually. The critical configuration requirement is to not disable mTLS, which would expose inter-service traffic to network inspection within the environment.
What is Easy Auth in Azure Container Apps and how does it differ from application-layer authentication?
Easy Auth (Azure App Service Authentication) in Container Apps is a platform-managed authentication middleware that validates Azure AD (Entra ID) tokens before requests reach the application container. It handles token validation, session management, and authentication redirect flows without requiring changes to the application code. Application-layer authentication is authentication implemented within the containerized application itself. Easy Auth is appropriate for protecting internal tools and APIs accessed by Azure AD users; application-layer authentication is more flexible and supports custom authentication schemes. Easy Auth does not restrict which Azure AD users can access the app (all valid Azure AD users can authenticate by default unless groups-based authorization is added).
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
