Lab 09 - Application Gateway for Containers (AGC) with WAF¶
| Field | Detail |
|---|---|
| Duration | 45–60 minutes |
| Level | Intermediate – Advanced |
| Prerequisites | Lab 01 environment deployed; basic Kubernetes knowledge; kubectl configured (optional) |
Objectives¶
By the end of this lab you will be able to:
- Explain what Application Gateway for Containers (AGC) is and how it differs from the traditional Application Gateway.
- Navigate AGC resources in the Azure portal.
- Understand how the ALB Controller in AKS manages AGC.
- Define WAF policies as Kubernetes Custom Resource Definitions (CRDs).
- Deploy a sample application on AKS and protect it with a WAF policy through AGC.
- Compare AGC with the traditional Application Gateway and Azure Front Door.
Section 1 – Introduction to Application Gateway for Containers¶
Application Gateway for Containers (AGC) is Microsoft's next-generation application load-balancing solution designed specifically for Kubernetes workloads running on Azure Kubernetes Service (AKS). It supersedes the Application Gateway Ingress Controller (AGIC) add-on model by providing:
| Capability | Traditional AGIC | AGC |
|---|---|---|
| API model | Kubernetes Ingress | Kubernetes Gateway API |
| Provisioning | Pre-created App Gateway | Fully managed by ALB Controller |
| Configuration latency | Minutes | Seconds |
| WAF integration | WAF v2 SKU on App Gateway | WAF policy via CRD reference |
| Traffic splitting | Limited | Native weighted back-end support |
| TLS policy control | App Gateway TLS settings | Gateway API TLSRoute / policy |
| Scalability | Tied to App Gateway SKU | Elastic, Azure-managed data plane |
How AGC Works¶
- The ALB Controller is deployed as a pod inside AKS.
- It watches for Gateway API resources (
Gateway,HTTPRoute,GRPCRoute). - When a
Gatewayresource is created, the ALB Controller provisions or updates the AGC frontend in Azure. - When an
HTTPRouteis created, the ALB Controller programs routing rules and back-end targets on the AGC data plane. - WAF policies can be referenced in the
Gatewayresource so that all traffic passing through that frontend is inspected.
Section 2 – Explore AGC Resources in the Portal¶
-
Sign in to the Azure portal.
-
In the portal search bar, type Application Gateways for Containers and select the service.
-
Click the AGC resource in your resource group (e.g.,
waf-workshop-agc). -
Examine the following blades:
| Blade | What to Look For |
|---|---|
| Overview | Provisioning state, location, associated AKS cluster |
| Frontends | Public or private frontends, FQDN assigned |
| Associations | AKS subnet associations that allow the ALB Controller to program the data plane |
| WAF Policy | Linked WAF policy (if any) |
-
Click Frontends → select the frontend → note the FQDN (e.g.,
fe-xxxxxxxx.<region>.fga.alb.azure.com). You will use this later to test traffic. -
Navigate back to the resource group and confirm the following companion resources exist:
-
Managed identity used by the ALB Controller.
- WAF policy linked to the AGC frontend (if pre-deployed).
Section 3 – AGC Architecture Overview¶

Application Gateway for Containers with WAF: Internet traffic flows through the AGC Frontend where the WAF Policy (DRS 2.1) inspects requests. Clean traffic is routed to Kubernetes Services and Pods. The ALB Controller in the AKS control plane watches Gateway API CRDs and provisions the AGC automatically. WAF logs flow to Log Analytics.
Key Components¶
| Component | Description |
|---|---|
| ALB Controller | A Kubernetes controller deployed via Helm; watches Gateway API resources and translates them into AGC configuration. |
| Gateway | A Kubernetes resource that represents the AGC frontend (listener). |
| HTTPRoute | Defines how HTTP traffic is routed to Kubernetes services. |
| Frontend | The Azure-managed public or private endpoint that receives traffic. |
| Association | Links the AGC data plane to a delegated subnet inside the AKS VNet. |
Section 4 – WAF Policy as a Kubernetes CRD¶
With AGC, WAF policies are referenced directly in the Gateway API resources using annotations or policy references. This enables a GitOps-friendly workflow — security policies live alongside application manifests.
4.1 – Example Gateway Resource with WAF Policy¶
# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: waf-demo-gateway
namespace: waf-demo
annotations:
alb.networking.azure.io/alb-id: /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.ServiceNetworking/trafficControllers/<AGC_NAME>
spec:
gatewayClassName: azure-alb-external
listeners:
- name: http-listener
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
# WAF policy reference via infrastructure annotation
infrastructure:
annotations:
alb.networking.azure.io/alb-frontend-waf-policy: /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies/<WAF_POLICY_NAME>
Key point: The
alb.networking.azure.io/alb-frontend-waf-policyannotation links the Azure WAF policy to the AGC frontend created by this Gateway.
4.2 – Example HTTPRoute Resource¶
# httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: waf-demo-route
namespace: waf-demo
spec:
parentRefs:
- name: waf-demo-gateway
namespace: waf-demo
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: waf-demo-service
port: 80
4.3 – Example WAF Policy (ARM / Bicep Reference)¶
The WAF policy itself is still an Azure resource. Below is a minimal Bicep snippet that creates a WAF policy suitable for AGC:
resource wafPolicy 'Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies@2023-11-01' = {
name: 'agc-waf-policy'
location: resourceGroup().location
properties: {
policySettings: {
requestBodyCheck: true
maxRequestBodySizeInKb: 128
fileUploadLimitInMb: 100
state: 'Enabled'
mode: 'Prevention'
}
managedRules: {
managedRuleSets: [
{
ruleSetType: 'Microsoft_DefaultRuleSet'
ruleSetVersion: '2.1'
}
{
ruleSetType: 'Microsoft_BotManagerRuleSet'
ruleSetVersion: '1.1'
}
]
}
}
}
Section 5 – Deploy a Sample App to AKS with WAF Protection¶
⚠️ OPTIONAL – Requires AKS Cluster
The following steps require a running AKS cluster with the ALB Controller installed. If you do not have an AKS cluster, review the YAML manifests below as reference material and proceed to Section 7.
5.1 – Connect to the AKS Cluster¶
# Set variables
RESOURCE_GROUP="waf-workshop-rg"
AKS_CLUSTER="waf-workshop-aks"
# Get AKS credentials
az aks get-credentials \
--resource-group $RESOURCE_GROUP \
--name $AKS_CLUSTER \
--overwrite-existing
# Verify connectivity
kubectl get nodes
5.2 – Create the Namespace¶
5.3 – Deploy the Sample Application¶
Create a file named waf-demo-app.yaml:
# waf-demo-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: waf-demo-app
namespace: waf-demo
labels:
app: waf-demo
spec:
replicas: 2
selector:
matchLabels:
app: waf-demo
template:
metadata:
labels:
app: waf-demo
spec:
containers:
- name: nginx
image: mcr.microsoft.com/oss/nginx/nginx:1.25.4
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: waf-demo-service
namespace: waf-demo
spec:
type: ClusterIP
selector:
app: waf-demo
ports:
- protocol: TCP
port: 80
targetPort: 80
Apply the manifest:
5.4 – Create the Gateway Resource¶
Create a file named gateway.yaml using the template from Section 4.1. Replace the placeholders:
# Replace placeholders
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
AGC_NAME="waf-workshop-agc"
WAF_POLICY_NAME="agc-waf-policy"
cat <<EOF > gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: waf-demo-gateway
namespace: waf-demo
annotations:
alb.networking.azure.io/alb-id: /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ServiceNetworking/trafficControllers/${AGC_NAME}
spec:
gatewayClassName: azure-alb-external
listeners:
- name: http-listener
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same
infrastructure:
annotations:
alb.networking.azure.io/alb-frontend-waf-policy: /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies/${WAF_POLICY_NAME}
EOF
kubectl apply -f gateway.yaml
5.5 – Create the HTTPRoute¶
5.6 – Verify the Deployment¶
# Check pods are running
kubectl get pods -n waf-demo
# Check gateway status
kubectl get gateway -n waf-demo
# Get the AGC frontend FQDN
AGC_FQDN=$(kubectl get gateway waf-demo-gateway -n waf-demo \
-o jsonpath='{.status.addresses[0].value}')
echo "AGC Frontend: $AGC_FQDN"
# Test connectivity (may take 2-3 minutes for DNS propagation)
curl -s -o /dev/null -w "%{http_code}" http://$AGC_FQDN/
Expected output: 200
Section 6 – Test WAF Protection on AGC¶
⚠️ OPTIONAL – Requires AKS Cluster with AGC deployed (Section 5)
6.1 – Send Legitimate Traffic¶
Expected: 200 OK
6.2 – Send SQL Injection Attack¶
# SQL injection in query string – should be blocked
curl -s -o /dev/null -w "%{http_code}\n" \
"http://$AGC_FQDN/?id=1' OR '1'='1"
Expected: 403 Forbidden
6.3 – Send XSS Attack¶
# Cross-site scripting in query string – should be blocked
curl -s -o /dev/null -w "%{http_code}\n" \
"http://$AGC_FQDN/?q=<script>alert('xss')</script>"
Expected: 403 Forbidden
6.4 – Send Path Traversal Attack¶
# Path traversal – should be blocked
curl -s -o /dev/null -w "%{http_code}\n" \
"http://$AGC_FQDN/../../etc/passwd"
Expected: 403 Forbidden
6.5 – Send Command Injection Attack¶
# Command injection in header – should be blocked
curl -s -o /dev/null -w "%{http_code}\n" \
-H "User-Agent: () { :; }; /bin/bash -c 'cat /etc/passwd'" \
"http://$AGC_FQDN/"
Expected: 403 Forbidden
6.6 – Verify in WAF Logs¶
WAF logs for AGC flow to the same Log Analytics workspace. Query them with:
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.SERVICENETWORKING"
| where Category == "TrafficControllerAccessLog"
| where properties_s contains "Blocked"
| project TimeGenerated, properties_s
| order by TimeGenerated desc
| take 20
Note: Log ingestion may take 5–10 minutes after the requests are sent.
Section 7 – AGC vs Traditional Application Gateway¶
| Feature | Traditional Application Gateway v2 | Application Gateway for Containers (AGC) |
|---|---|---|
| Target workloads | VMs, VMSS, App Services, AKS | Kubernetes workloads on AKS |
| API model | ARM / Bicep / Terraform | Kubernetes Gateway API + ARM |
| K8s integration | AGIC add-on (Ingress API) | ALB Controller (Gateway API) |
| Configuration latency | 3–5 minutes | Seconds |
| WAF support | WAF v2 SKU (GA) | WAF policy via annotation (Preview) |
| Managed rule sets | DRS 2.1, Bot Manager 1.1 | DRS 2.1, Bot Manager 1.1 |
| Custom rules | Yes | Yes |
| TLS termination | Yes | Yes |
| Mutual TLS (mTLS) | Yes | Yes |
| Traffic splitting | Limited | Native weighted back-end |
| Auto-scaling | Capacity units | Fully elastic (Azure-managed) |
| Health probes | Custom probes | Kubernetes readiness probes |
| Private frontend | Yes | Yes |
| Pricing model | Fixed + capacity units | Per SCU (Service Compute Unit) |
| Maturity | GA | GA (WAF in Preview) |
Section 8 – AGC WAF Limitations¶
As of the current preview, AGC WAF has the following limitations:
| Limitation | Details |
|---|---|
| WAF mode | Prevention and Detection modes are supported. |
| Rule sets | Microsoft_DefaultRuleSet 2.1 and Microsoft_BotManagerRuleSet 1.1 are supported. |
| Custom rules | Supported but with a subset of match conditions compared to Application Gateway WAF. |
| Per-site policies | Not yet supported — one WAF policy per AGC frontend. |
| Exclusions | Supported at the policy level. |
| Request body inspection | Supported up to 128 KB. |
| Rate limiting | Not yet available through AGC WAF. |
| Geo-filtering | Supported via custom rules. |
| Log format | Logs use the TrafficControllerAccessLog category — different from App Gateway ApplicationGatewayFirewallLog. |
| Portal WAF dashboard | Limited integration — use Log Analytics for full visibility. |
Tip: Always check the official AGC WAF documentation for the latest supported features.
Section 9 – Key Takeaways¶
When to Use Each Service¶
| Scenario | Recommended Service |
|---|---|
| Kubernetes-native workloads on AKS needing low-latency config | AGC |
| Traditional VM/VMSS workloads needing WAF | Application Gateway v2 |
| Multi-region, global load balancing with WAF | Azure Front Door |
| AKS workloads needing full WAF GA features today | Application Gateway v2 + AGIC (until AGC WAF reaches GA) |
| API Management with WAF protection | Application Gateway v2 or Front Door |
Summary¶
- AGC is the future of application load balancing for Kubernetes on Azure — it provides seconds-level configuration, Gateway API support, and a fully managed data plane.
- WAF integration with AGC allows security policies to be managed as infrastructure-as-code alongside Kubernetes manifests.
- While AGC WAF is in preview, the traditional Application Gateway WAF v2 remains the GA choice for production workloads requiring full WAF feature parity.
- The Gateway API model used by AGC is the Kubernetes community standard, replacing the legacy Ingress API.
Clean Up (Optional)¶
If you deployed the sample app, remove the resources:
Additional Resources¶
- Application Gateway for Containers documentation
- Gateway API specification
- ALB Controller for AKS
- WAF on AGC
End of Lab 09