Konfigurera CSI-drivrutin för Secrets Store för att aktivera NGINX-ingresskontrollant med TLS

Den här artikeln beskriver hur du skyddar en NGINX-ingresskontrollant med TLS med ett Azure Kubernetes Service-kluster (AKS) och en Azure Key Vault-instans (AKV). Mer information finns i TLS i Kubernetes.

Du kan importera det inkommande TLS-certifikatet till klustret med någon av följande metoder:

  • Program: Programdistributionsmanifestet deklarerar och monterar providervolymen. Endast när du distribuerar programmet görs certifikatet tillgängligt i klustret. När du tar bort programmet tas även hemligheten bort. Det här scenariot passar utvecklingsteam som ansvarar för programmets säkerhetsinfrastruktur och dess integrering med klustret.
  • Ingresskontrollant: Ingressdistributionen ändras för att deklarera och montera providervolymen. Hemligheten importeras när inkommande poddar skapas. Programmets poddar har ingen åtkomst till TLS-certifikatet. Det här scenariot passar scenarier där ett team (till exempel IT) hanterar och skapar infrastruktur- och nätverkskomponenter (inklusive HTTPS TLS-certifikat) och andra team hanterar programmets livscykel.

Förutsättningar

Generera ett TLS-certifikat

  • Generera ett TLS-certifikat med hjälp av följande kommando.

    export CERT_NAME=aks-ingress-cert
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
        -out aks-ingress-tls.crt \
        -keyout aks-ingress-tls.key \
        -subj "/CN=demo.azure.com/O=aks-ingress-tls"
    

Importera certifikatet till AKV

  1. Exportera certifikatet till en PFX-fil med hjälp av följande kommando.

    export AKV_NAME="[YOUR AKV NAME]"
    openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key  -out $CERT_NAME.pfx
    # skip Password prompt
    
  2. Importera certifikatet med kommandot az keyvault certificate import .

    az keyvault certificate import --vault-name $AKV_NAME -n $CERT_NAME -f $CERT_NAME.pfx
    

Distribuera en SecretProviderClass

  1. Exportera ett nytt namnområde med hjälp av följande kommando.

    export NAMESPACE=ingress-basic
    
  2. Skapa namnområdet med kommandot kubectl create namespace .

    kubectl create namespace $NAMESPACE
    
  3. Välj en metod för att tillhandahålla en åtkomstidentitet och konfigurera din SecretProviderClass YAML i enlighet med detta.

    • Se till att använda objectType=secret, vilket är det enda sättet att hämta den privata nyckeln och certifikatet från AKV.
    • Ange kubernetes.io/tls som type i avsnittet secretObjects .

    Se följande exempel på hur Din SecretProviderClass kan se ut:

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: azure-tls
    spec:
      provider: azure
      secretObjects:                            # secretObjects defines the desired state of synced K8s secret objects
        - secretName: ingress-tls-csi
          type: kubernetes.io/tls
          data: 
            - objectName: $CERT_NAME
              key: tls.key
            - objectName: $CERT_NAME
              key: tls.crt
      parameters:
        usePodIdentity: "false"
        useVMManagedIdentity: "true"
        userAssignedIdentityID: <client id>
        keyvaultName: $AKV_NAME                 # the name of the AKV instance
        objects: |
          array:
            - |
              objectName: $CERT_NAME
              objectType: secret
        tenantId: $TENANT_ID                    # the tenant ID of the AKV instance
    
  4. Använd SecretProviderClass på ditt Kubernetes-kluster med kommandot kubectl apply .

    kubectl apply -f secretProviderClass.yaml -n $NAMESPACE
    

Distribuera ingresskontrollanten

Lägg till den officiella lagringsplatsen för inkommande diagram

  • Lägg till den officiella lagringsplatsen för inkommande diagram med hjälp av följande helm kommandon.

    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    

Konfigurera och distribuera NGINX-ingressen

Beroende på ditt scenario kan du välja att binda certifikatet till antingen programmet eller till ingresskontrollanten. Följ anvisningarna nedan enligt ditt val:

Binda certifikat till program

  • Binda certifikatet till programmet med hjälp av helm install kommandot . Programmets distribution refererar till CSI-drivrutinens Azure Key Vault-provider i Secrets Store.

    helm install ingress-nginx/ingress-nginx --generate-name \
        --namespace $NAMESPACE \
        --set controller.replicaCount=2 \
        --set controller.nodeSelector."kubernetes\.io/os"=linux \
        --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
        --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux
    

Binda certifikat till ingresskontrollant

  1. Binda certifikatet till ingresskontrollanten med hjälp av helm install kommandot . Ingresskontrollantens distribution refererar till CSI-drivrutinens Azure Key Vault-provider för Secrets Store.

    Kommentar

    • Om du inte använder Microsoft Entra poddhanterad identitet som åtkomstmetod tar du bort raden med --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME .

    • Dessutom krävs bindning av SecretProviderClass till en podd för att CSI-drivrutinen för Secrets Store ska montera den och generera Kubernetes-hemligheten. Se Synkronisera monterat innehåll med en Kubernetes-hemlighet .

    helm install ingress-nginx/ingress-nginx --generate-name \
        --namespace $NAMESPACE \
        --set controller.replicaCount=2 \
        --set controller.nodeSelector."kubernetes\.io/os"=linux \
        --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
        --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
        --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME \
        -f - <<EOF
    controller:
      extraVolumes:
          - name: secrets-store-inline
            csi:
              driver: secrets-store.csi.k8s.io
              readOnly: true
              volumeAttributes:
                secretProviderClass: "azure-tls"
      extraVolumeMounts:
          - name: secrets-store-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
    EOF
    
  2. Kontrollera att Kubernetes-hemligheten kubectl get secret skapades med kommandot .

    kubectl get secret -n $NAMESPACE
    
    NAME                                             TYPE                                  DATA   AGE
    ingress-tls-csi                                  kubernetes.io/tls                     2      1m34s
    

Distribuera programmet

Återigen ändras anvisningarna något beroende på ditt scenario. Följ anvisningarna som motsvarar det scenario som du valde.

Distribuera programmet med hjälp av en programreferens

  1. Skapa en fil med namnet aks-helloworld-one.yaml med följande innehåll.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-one  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-one
      template:
        metadata:
          labels:
            app: aks-helloworld-one
        spec:
          containers:
          - name: aks-helloworld-one
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
            volumeMounts:
            - name: secrets-store-inline
              mountPath: "/mnt/secrets-store"
              readOnly: true
          volumes:
          - name: secrets-store-inline
            csi:
              driver: secrets-store.csi.k8s.io
              readOnly: true
              volumeAttributes:
                secretProviderClass: "azure-tls"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-one  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-one
    
  2. Skapa en fil med namnet aks-helloworld-two.yaml med följande innehåll.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-two  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-two
      template:
        metadata:
          labels:
            app: aks-helloworld-two
        spec:
          containers:
          - name: aks-helloworld-two
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "AKS Ingress Demo"
            volumeMounts:
            - name: secrets-store-inline
              mountPath: "/mnt/secrets-store"
              readOnly: true
          volumes:
          - name: secrets-store-inline
            csi:
              driver: secrets-store.csi.k8s.io
              readOnly: true
              volumeAttributes:
                secretProviderClass: "azure-tls"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-two
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-two
    
  3. Använd YAML-filerna i klustret med hjälp av kubectl apply kommandot .

    kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE
    kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
    
  4. Kontrollera att Kubernetes-hemligheten kubectl get secret skapades med kommandot .

    kubectl get secret -n $NAMESPACE
    
    NAME                                             TYPE                                  DATA   AGE
    ingress-tls-csi                                  kubernetes.io/tls                     2      1m34s
    

Distribuera programmet med hjälp av en referens för ingresskontrollant

  1. Skapa en fil med namnet aks-helloworld-one.yaml med följande innehåll.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-one  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-one
      template:
        metadata:
          labels:
            app: aks-helloworld-one
        spec:
          containers:
          - name: aks-helloworld-one
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-one
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-one
    
  2. Skapa en fil med namnet aks-helloworld-two.yaml med följande innehåll.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-two  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-two
      template:
        metadata:
          labels:
            app: aks-helloworld-two
        spec:
          containers:
          - name: aks-helloworld-two
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "AKS Ingress Demo"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-two  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-two
    
  3. Använd YAML-filerna i klustret med hjälp av kubectl apply kommandot .

    kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE
    kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
    

Distribuera en ingressresurs som refererar till hemligheten

Nu kan vi distribuera en Kubernetes-ingressresurs som refererar till hemligheten.

  1. Skapa ett filnamn hello-world-ingress.yaml med följande innehåll.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-tls
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$2
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - demo.azure.com
        secretName: ingress-tls-csi
      rules:
      - host: demo.azure.com
        http:
          paths:
          - path: /hello-world-one(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
          - path: /hello-world-two(/|$)(.*)
            pathType: Prefix      
            backend:
              service:
                name: aks-helloworld-two
                port:
                  number: 80
          - path: /(.*)
            pathType: Prefix      
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
    
  2. Anteckna avsnittet tls som refererar till hemligheten som skapades tidigare och tillämpa filen på klustret med hjälp av kubectl apply kommandot .

    kubectl apply -f hello-world-ingress.yaml -n $NAMESPACE
    

Hämta den externa IP-adressen för ingresskontrollanten

  • Hämta den externa IP-adressen för ingresskontrollanten med hjälp av kubectl get service kommandot .

    kubectl get service --namespace $NAMESPACE --selector app.kubernetes.io/name=ingress-nginx
    
    NAME                                       TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
    nginx-ingress-1588032400-controller        LoadBalancer   10.0.255.157   EXTERNAL_IP      80:31293/TCP,443:31265/TCP   19m
    nginx-ingress-1588032400-default-backend   ClusterIP      10.0.223.214   <none>           80/TCP                       19m
    

Testa ingress som skyddas med TLS

  1. Kontrollera att ingressen är korrekt konfigurerad med TLS med hjälp av följande curl kommando. Kontrollera att du använder den externa IP-adressen från föregående steg.

    curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com
    

    Eftersom en annan sökväg inte har angetts med adressen använder ingresskontrollanten / som standard vägen. Det första demoprogrammet returneras, enligt följande komprimerade exempelutdata:

    [...]
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>Welcome to Azure Kubernetes Service (AKS)</title>
    [...]
    

    Parametern -v i curl kommandot matar ut utförlig information, inklusive TLS-certifikatet som tagits emot. Halvvägs genom curl-utdata kan du kontrollera att ditt eget TLS-certifikat användes. Parametern -k fortsätter att läsa in sidan trots att vi använder ett självsignerat certifikat. I följande exempel visas utfärdaren : CN=demo.azure.com; O=aks-ingress-tls-certifikat användes:

    [...]
     * Server certificate:
     *  subject: CN=demo.azure.com; O=aks-ingress-tls
     *  start date: Oct 22 22:13:54 2021 GMT
     *  expire date: Oct 22 22:13:54 2022 GMT
     *  issuer: CN=demo.azure.com; O=aks-ingress-tls
     *  SSL certificate verify result: self signed certificate (18), continuing anyway.
    [...]
    
  2. Lägg till sökvägen /hello-world-two till adressen, till exempel https://demo.azure.com/hello-world-two, och kontrollera att det andra demoprogrammet är korrekt konfigurerat.

    curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com/hello-world-two
    

    Det andra demoprogrammet med den anpassade rubriken returneras, enligt följande komprimerade exempelutdata:

    [...]
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>AKS Ingress Demo</title>
    [...]