Geheimenarchief CSI-stuurprogramma instellen om NGINX-ingangscontroller in te schakelen met TLS

In dit artikel wordt u begeleid bij het beveiligen van een NGINX-ingangscontroller met TLS met een AKS-cluster (Azure Kubernetes Service) en een AZURE Key Vault-exemplaar (AKV). Zie TLS in Kubernetes voor meer informatie.

U kunt het TLS-certificaat voor inkomend verkeer importeren in het cluster met behulp van een van de volgende methoden:

  • Toepassing: Het manifest voor toepassingsimplementatie declareert en koppelt het providervolume. Alleen wanneer u de toepassing implementeert, is het certificaat dat beschikbaar is in het cluster. Wanneer u de toepassing verwijdert, wordt het geheim ook verwijderd. Dit scenario past bij ontwikkelteams die verantwoordelijk zijn voor de beveiligingsinfrastructuur van de toepassing en de integratie met het cluster.
  • Ingangscontroller: de implementatie van inkomend verkeer wordt gewijzigd om het providervolume te declareren en te koppelen. Het geheim wordt geïmporteerd wanneer inkomende pods worden gemaakt. De pods van de toepassing hebben geen toegang tot het TLS-certificaat. Dit scenario past bij scenario's waarin één team (bijvoorbeeld IT) infrastructuur- en netwerkonderdelen beheert en maakt (inclusief HTTPS TLS-certificaten) en andere teams de levenscyclus van toepassingen beheren.

Vereisten

Een TLS-certificaat genereren

  • Genereer een TLS-certificaat met behulp van de volgende opdracht.

    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"
    

Het certificaat importeren in AKV

  1. Exporteer het certificaat naar een PFX-bestand met behulp van de volgende opdracht.

    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. Importeer het certificaat met behulp van de az keyvault certificate import opdracht.

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

Een SecretProviderClass implementeren

  1. Exporteer een nieuwe naamruimte met behulp van de volgende opdracht.

    export NAMESPACE=ingress-basic
    
  2. Maak de naamruimte met behulp van de kubectl create namespace opdracht.

    kubectl create namespace $NAMESPACE
    
  3. Selecteer een methode om een toegangsidentiteit op te geven en configureer uw SecretProviderClass YAML dienovereenkomstig.

    • Zorg ervoor dat u objectType=secretgebruikt, wat de enige manier is om de persoonlijke sleutel en het certificaat van AKV te verkrijgen.
    • Stel kubernetes.io/tls deze in secretObjects als de type sectie.

    Bekijk het volgende voorbeeld van hoe uw SecretProviderClass eruit kan zien:

    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. Pas de SecretProviderClass toe op uw Kubernetes-cluster met behulp van de kubectl apply opdracht.

    kubectl apply -f secretProviderClass.yaml -n $NAMESPACE
    

De ingangscontroller implementeren

De officiële opslagplaats voor inkomend verkeer toevoegen

  • Voeg de officiële opslagplaats voor inkomend verkeer toe met behulp van de volgende helm opdrachten.

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

De NGINX-ingang configureren en implementeren

Afhankelijk van uw scenario kunt u ervoor kiezen om het certificaat te binden aan de toepassing of aan de ingangscontroller. Volg de onderstaande instructies op basis van uw selectie:

Certificaat binden aan toepassing

  • Bind het certificaat aan de toepassing met behulp van de helm install opdracht. De implementatie van de toepassing verwijst naar de Azure Key Vault-provider van het Secrets Store CSI-stuurprogramma.

    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
    

Certificaat binden aan toegangsbeheerobjectcontroller

  1. Bind het certificaat aan de ingangscontroller met behulp van de helm install opdracht. De implementatie van de toegangsbeheerobjectcontroller verwijst naar de Azure Key Vault-provider van het Secrets Store CSI-stuurprogramma.

    Notitie

    • Als u geen door Microsoft Entra beheerde identiteit als toegangsmethode gebruikt, verwijdert u de regel met --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME .

    • Daarnaast is het koppelen van de SecretProviderClass aan een pod vereist voor het CSI-stuurprogramma Secrets Store om het te koppelen en het Kubernetes-geheim te genereren. Zie Gekoppelde inhoud synchroniseren met een Kubernetes-geheim .

    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. Controleer of het Kubernetes-geheim is gemaakt met behulp van de kubectl get secret opdracht.

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

De toepassing implementeren

Nogmaals, de instructies veranderen enigszins, afhankelijk van uw scenario. Volg de instructies die overeenkomen met het scenario dat u hebt geselecteerd.

De toepassing implementeren met behulp van een toepassingsreferentie

  1. Maak een bestand met de naam aks-helloworld-one.yaml met de volgende inhoud.

    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. Maak een bestand met de naam aks-helloworld-two.yaml met de volgende inhoud.

    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. Pas de YAML-bestanden toe op uw cluster met behulp van de kubectl apply opdracht.

    kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE
    kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
    
  4. Controleer of het Kubernetes-geheim is gemaakt met behulp van de kubectl get secret opdracht.

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

De toepassing implementeren met behulp van een verwijzing naar een toegangsbeheerobjectcontroller

  1. Maak een bestand met de naam aks-helloworld-one.yaml met de volgende inhoud.

    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. Maak een bestand met de naam aks-helloworld-two.yaml met de volgende inhoud.

    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. Pas de YAML-bestanden toe op uw cluster met behulp van de kubectl apply opdracht.

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

Een toegangsbeheerobjectresource implementeren die verwijst naar het geheim

We kunnen nu een Kubernetes-toegangsbeheerobjectresource implementeren die verwijst naar het geheim.

  1. Maak een bestandsnaam hello-world-ingress.yaml met de volgende inhoud.

    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. Noteer de tls sectie die verwijst naar het geheim dat u eerder hebt gemaakt en pas het bestand toe op uw cluster met behulp van de kubectl apply opdracht.

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

Het externe IP-adres van de ingangscontroller verkrijgen

  • Haal het externe IP-adres voor de ingangscontroller op met behulp van de kubectl get service opdracht.

    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
    

Inkomend verkeer testen dat is beveiligd met TLS

  1. Controleer of uw toegangsbeheerobject correct is geconfigureerd met TLS met behulp van de volgende curl opdracht. Zorg ervoor dat u het externe IP-adres uit de vorige stap gebruikt.

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

    Omdat er geen ander pad bij het adres is opgegeven, wordt de ingangscontroller standaard ingesteld op de / route. De eerste demotoepassing wordt geretourneerd, zoals wordt weergegeven in de volgende verkorte voorbeelduitvoer:

    [...]
    <!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>
    [...]
    

    De parameter -v in de curl opdracht voert uitgebreide informatie uit, inclusief het ONTVANGEN TLS-certificaat. Halverwege de curl-uitvoer kunt u controleren of uw eigen TLS-certificaat is gebruikt. De parameter -k blijft de pagina laden, ook al gebruiken we een zelfondertekend certificaat. In het volgende voorbeeld ziet u de verlener: CN=demo.azure.com; O=aks-ingress-tls-certificaat is gebruikt:

    [...]
     * 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. Voeg /hello-world-two-pad toe aan het adres, zoals https://demo.azure.com/hello-world-twoen controleer of de tweede demotoepassing juist is geconfigureerd.

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

    De tweede demotoepassing met de aangepaste titel wordt geretourneerd, zoals wordt weergegeven in de volgende verkorte voorbeelduitvoer:

    [...]
    <!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>
    [...]