Web application firewall di Azure nel gateway applicazione per contenitori con l'API gateway

Questo articolo illustra come configurare un'applicazione di esempio che usa risorse dall'API gateway. L'articolo illustra i passaggi per:

  • Creare una risorsa Gateway con un listener HTTPS.
  • Creare una risorsa HTTPRoute che fa riferimento a un servizio back-end.
  • Creare una risorsa WebApplicationFirewallPolicy che fa riferimento a una risorsa HTTPRoute.

Background

Il gateway applicazione per contenitori usa Web application firewall di Azure per impedire che una richiesta dannosa venga inviata tramite proxy alla destinazione back-end. Il diagramma seguente mostra uno scenario di esempio.

Diagramma che mostra una richiesta dannosa bloccata dal gateway applicazione per contenitori con Web application firewall di Azure abilitato in modalità di prevenzione.

Prerequisiti

  • Se si segue la strategia di distribuzione bring your own (BYO), assicurarsi di configurare le risorse del gateway applicazioni per contenitori e il controller ALB (Componente aggiuntivo o Helm).

  • Se si segue la strategia di distribuzione gestita da Application Load Balancer (ALB), assicurarsi di:

  • Applicare il file deployment.yaml seguente nel cluster per creare un'applicazione Web di esempio che illustra la riscrittura dell'intestazione:

    kubectl apply -f https://raw.githubusercontent.com/MicrosoftDocs/azure-docs/refs/heads/main/articles/application-gateway/for-containers/examples/traffic-split-scenario/deployment.yaml
    

    Questo comando crea gli elementi seguenti nel cluster:

    • Uno spazio dei nomi denominato test-infra
    • Due servizi denominati backend-v1 e backend-v2 nello spazio dei nomi test-infra
    • Due distribuzioni denominate backend-v1 e backend-v2 nello spazio dei nomi test-infra

Distribuire le risorse necessarie per l'API gateway

Creare una risorsa Gateway:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway-01
  namespace: test-infra
  annotations:
    alb.networking.azure.io/alb-namespace: alb-test-infra
    alb.networking.azure.io/alb-name: alb-test
spec:
  gatewayClassName: azure-alb-external
  listeners:
  - name: http-listener
    port: 80
    protocol: HTTP
    allowedRoutes:
      namespaces:
        from: Same
EOF

Annotazioni

Quando il controller ALB crea le risorse del gateway applicazione per contenitori in Azure Resource Manager, usa la convenzione di denominazione seguente per una risorsa front-end: fe-<eight randomly generated characters>.

Per modificare il nome della risorsa front-end creata in Azure, valutare la possibilità di seguire la strategia di distribuzione BYO.

Dopo aver creato la risorsa Gateway, assicurarsi che lo stato sia valido, che il listener presenti lo stato Programmed e che al listener sia assegnato un indirizzo:

kubectl get gateway gateway-01 -n test-infra -o yaml

Ecco l'output di esempio per la corretta creazione di una risorsa Gateway:

status:
  addresses:
  - type: IPAddress
    value: xxxx.yyyy.alb.azure.com
  conditions:
  - lastTransitionTime: "2023-06-19T21:04:55Z"
    message: Valid Gateway
    observedGeneration: 1
    reason: Accepted
    status: "True"
    type: Accepted
  - lastTransitionTime: "2023-06-19T21:04:55Z"
    message: Application Gateway For Containers resource has been successfully updated.
    observedGeneration: 1
    reason: Programmed
    status: "True"
    type: Programmed
  listeners:
  - attachedRoutes: 0
    conditions:
    - lastTransitionTime: "2023-06-19T21:04:55Z"
      message: ""
      observedGeneration: 1
      reason: ResolvedRefs
      status: "True"
      type: ResolvedRefs
    - lastTransitionTime: "2023-06-19T21:04:55Z"
      message: Listener is accepted
      observedGeneration: 1
      reason: Accepted
      status: "True"
      type: Accepted
    - lastTransitionTime: "2023-06-19T21:04:55Z"
      message: Application Gateway For Containers resource has been successfully updated.
      observedGeneration: 1
      reason: Programmed
      status: "True"
      type: Programmed
    name: https-listener
    supportedKinds:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute

Creare una risorsa HTTPRoute che ascolti il nome host contoso.com:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: contoso-waf-route
  namespace: test-infra
spec:
  parentRefs:
    - name: gateway-01
      namespace: test-infra
  hostnames:
  - "contoso.com"
  rules:
  - backendRefs:
    - name: backend-v1
      port: 8080
EOF

Dopo aver creato la risorsa HTTPRoute, assicurarsi che lo stato della route sia Accepted e che lo stato della risorsa del gateway applicazione per contenitori sia Programmed:

kubectl get httproute header-rewrite-route -n test-infra -o yaml

Verificare che lo stato della risorsa del gateway applicazione per contenitori sia stato aggiornato correttamente:

status:
  parents:
  - conditions:
    - lastTransitionTime: "2023-06-19T22:18:23Z"
      message: ""
      observedGeneration: 1
      reason: ResolvedRefs
      status: "True"
      type: ResolvedRefs
    - lastTransitionTime: "2023-06-19T22:18:23Z"
      message: Route is Accepted
      observedGeneration: 1
      reason: Accepted
      status: "True"
      type: Accepted
    - lastTransitionTime: "2023-06-19T22:18:23Z"
      message: Application Gateway For Containers resource has been successfully updated.
      observedGeneration: 1
      reason: Programmed
      status: "True"
      type: Programmed
    controllerName: alb.networking.azure.io/alb-controller
    parentRef:
      group: gateway.networking.k8s.io
      kind: Gateway
      name: gateway-01
      namespace: test-infra

Configurare WebApplicationFirewallPolicy

Il gateway applicazione per contenitori usa una risorsa personalizzata denominata WebApplicationFirewallPolicy per definire la protezione di Web application firewall di Azure. In questo esempio, Web application firewall di Azure consente di proteggere una risorsa HTTPRoute specifica:

kubectl apply -f - <<EOF
apiVersion: alb.networking.azure.io/v1
kind: WebApplicationFirewallPolicy
metadata:
  name: sample-waf-policy
  namespace: test-infra
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: contoso-waf-route
    namespace: test-infra
    #sectionNames: ["listenerA"] # defined if you're targeting a specific listener on a gateway resource or path
  webApplicationFirewall:
    id: /subscriptions/.../Microsoft.Network/applicationGatewayWebApplicationFirewallPolicies/waf-policy-0
EOF
kubectl apply -f - <<EOF
apiVersion: alb.networking.azure.io/v1
kind: WebApplicationFirewallPolicy
metadata:
  name: sample-waf-policy
  namespace: test-infra
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: contoso-waf-route
    namespace: test-infra
    #sectionNames: ["listenerA"] # defined if you're targeting a specific listener on a gateway resource or path
  webApplicationFirewall:
    id: /subscriptions/711d99a7-fd79-4ce7-9831-ea1afa18442e/resourceGroups/AGC-RG/providers/Microsoft.Network/applicationGatewayWebApplicationFirewallPolicies/agc-waf
EOF

Testare l'accesso all'applicazione

A questo punto è possibile inviare traffico all'applicazione di esempio tramite il nome di dominio completo (FQDN) assegnato alla risorsa front-end. Usare il comando seguente per ottenere il nome di dominio completo:

fqdn=$(kubectl get gateway gateway-01 -n test-infra -o jsonpath='{.status.addresses[0].value}')

Se si specifica l'indicatore del nome del server usando il comando curl con contoso.com per il nome di dominio completo della risorsa front-end, l'output deve restituire una risposta dal servizio backend-v1:

fqdnIp=$(dig +short $fqdn)
curl -k --resolve contoso.com:80:$fqdnIp http://contoso.com

Tramite la risposta, si dovrebbe visualizzare:

{
 "path": "/",
 "host": "contoso.com",
 "method": "GET",
 "proto": "HTTP/1.1",
 "headers": {
  "Accept": [
   "*/*"
  ],
  "User-Agent": [
   "curl/7.81.0"
  ],
  "X-Forwarded-For": [
   "xxx.xxx.xxx.xxx"
  ],
  "X-Forwarded-Proto": [
   "http"
  ],
  "X-Request-Id": [
   "dcd4bcad-ea43-4fb6-948e-a906380dcd6d"
  ]
 },
 "namespace": "test-infra",
 "ingress": "",
 "service": "",
 "pod": "backend-v1-5b8fd96959-f59mm"
}

Inviare ora una richiesta con una stringa di query dannosa per attivare una risposta 403 forbidden dal gateway applicazione per contenitori.

Ecco un esempio di richiesta:

curl -k --resolve contoso.com:80:$fqdnIp http://contoso.com/?text=/etc/passwd

Ecco un'altra richiesta di esempio:

curl -k --resolve contoso.com:80:$fqdnIp http://contoso.com/?1=1=1

Congratulazioni! È stato installato un controller ALB, è stata distribuita un'applicazione back-end e è stata usata la funzionalità di Web application firewall di Azure per bloccare una richiesta dannosa.