Inkomend verkeer beveiligen met de implementatie van de Gateway-API voor toepassingsroutering

Note

In dit artikel wordt beschreven hoe u TLS-beëindiging handmatig configureert op een Gateway-resource door uw eigen SecretProviderClass op te stellen, de Azure Key Vault-provider voor Secrets Store CSI Driver te mounten via een voorbeeldpod en rechtstreeks te verwijzen naar het resulterende Kubernetes Secret in de Gateway-listener certificateRefs. Deze methode is handig als u volledige controle over de werkstroom voor certificaatsynchronisatie nodig hebt of deze resources zelf wilt beheren.

Voor de meeste gebruikers is de aanbevolen aanpak de geautomatiseerde integratie van Azure DNS en Azure Key Vault, aangestuurd door de Application Routing-operator, die op basis van een paar listener-SecretProviderClass de certificateRefs, de gesynchroniseerde Kubernetes Secret en de listener tls.options voor u inricht en afstemt. Als u de geautomatiseerde workflow wilt gebruiken, raadpleegt u Azure DNS en TLS configureren met de Gateway API-implementatie voor toepassingsroutering.

De invoegtoepassing voor toepassingsroutering ondersteunt het synchroniseren van geheimen van Azure Key Vault (AKV) voor het beveiligen van inkomend verkeer van gateway-API met TLS-beëindiging. Volg de onderstaande stappen om certificaten en sleutels te maken om TLS-verkeer bij de gateway te beëindigen.

Vereiste voorwaarden

Vereiste client-/servercertificaten en -sleutels

  1. Maak een basiscertificaat en een persoonlijke sleutel voor het ondertekenen van de certificaten voor voorbeeldservices:
mkdir httpbin_certs
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout httpbin_certs/example.com.key -out httpbin_certs/example.com.crt
  1. Genereer een certificaat en een persoonlijke sleutel voor httpbin.example.com:
openssl req -out httpbin_certs/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin_certs/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
openssl x509 -req -sha256 -days 365 -CA httpbin_certs/example.com.crt -CAkey httpbin_certs/example.com.key -set_serial 0 -in httpbin_certs/httpbin.example.com.csr -out httpbin_certs/httpbin.example.com.crt

Een TLS-ingangsgateway configureren

Azure Key Vault instellen en geheimen synchroniseren met het cluster

  1. Azure Key Vault maken

    U hebt een Azure Key Vault-resource nodig om het certificaat en de sleutelinvoer op te geven aan de invoegtoepassing voor toepassingsroutering.

    export AKV_NAME=<azure-key-vault-resource-name>  
    az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    
  2. Schakel de invoegtoepassing Azure Key Vault-provider in voor Secret Store CSI Driver in uw cluster.

    az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER
    
  3. Als uw Key Vault Gebruikmaakt van Azure RBAC voor het machtigingsmodel, volgt u de instructies hier om een Azure-rol van Key Vault Secrets User toe te wijzen voor de door de gebruiker toegewezen beheerde identiteit van de invoegtoepassing. Als uw sleutelkluis gebruikmaakt van het machtigingsmodel voor kluistoegangsbeleid, kunt u ook de door de gebruiker toegewezen beheerde identiteit van de invoegtoepassing autoriseren voor toegang tot Azure Key Vault-resource met behulp van toegangsbeleid:

    OBJECT_ID=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER --query 'addonProfiles.azureKeyvaultSecretsProvider.identity.objectId' -o tsv | tr -d '\r')
    CLIENT_ID=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER --query 'addonProfiles.azureKeyvaultSecretsProvider.identity.clientId')
    TENANT_ID=$(az keyvault show --resource-group $RESOURCE_GROUP --name $AKV_NAME --query 'properties.tenantId')
    
    az keyvault set-policy --name $AKV_NAME --object-id $OBJECT_ID --secret-permissions get list
    
  4. Kies hoe u het TLS-certificaat wilt opgeven.

    Azure Key Vault ondersteunt verschillende objecttypen. Voor dit scenario kiest u een van de volgende end-to-end-opties en gaat u verder met de algemene validatie- en gatewaystappen.

    Option Gebruik deze optie wanneer Key Vault winkels Kubernetes Secret-resultaat
    Optie 1: het certificaat en de sleutel opslaan als Key Vault geheimen U hebt afzonderlijke PEM-certificaatbestanden (.crt) en persoonlijke sleutelbestanden.key, zoals de bestanden die eerder in dit artikel zijn gegenereerd. Twee Key Vault geheimen. Eén gesynchroniseerd Kubernetes TLS-geheim met de naam httpbin-credential.
    Optie 2: Rechtstreeks verwijzen naar een Key Vault certificaatobject Uw certificaat is al opgeslagen in Key Vault als een certificaatobject, zoals een geïmporteerd.pfx. Eén Key Vault-certificaatobject. Eén gesynchroniseerd Kubernetes TLS-geheim met de naam httpbin-credential.

    Important

    Volg beide opties niet. Als u Optie 1 gebruikt, uploadt u het certificaat en de sleutelbestanden als Key Vault geheimen en past u vervolgens het manifest Optie 1 SecretProviderClass toe. Als u optie 2 gebruikt, slaat u de Key Vault stap voor het uploaden van geheimen over en past u het manifest optie 2 SecretProviderClass toe.

Optie 1: het certificaat en de sleutel opslaan als Key Vault geheimen

Gebruik deze optie als u afzonderlijke PEM-certificaatbestanden (.crt) en persoonlijke sleutelbestanden.key hebt, zoals de bestanden die eerder in dit artikel zijn gegenereerd.

  1. Upload het certificaat en de sleutelbestanden als Key Vault geheimen:

    az keyvault secret set --vault-name $AKV_NAME --name test-httpbin-key --file httpbin_certs/httpbin.example.com.key
    az keyvault secret set --vault-name $AKV_NAME --name test-httpbin-crt --file httpbin_certs/httpbin.example.com.crt
    

    Note

    Telkens wanneer u het certificaat of de sleutel roteert (wijzigt), voert u deze stap opnieuw uit om de nieuwe versies als geheimen te uploaden. Als u de bijgewerkte waarden automatisch wilt synchroniseren naar het cluster, schakelt u automatischerotatie in op de Azure Key Vault-provider voor het stuurprogramma Secrets Store CSI. Zie het overzicht van automatischerotatie en geheimsynchronisatie voor meer informatie. Als u liever Key Vault de levenscyclus van het certificaat wilt beheren, gebruikt u in plaats daarvan Optie 2.

  2. Maak de SecretProviderClass sleutel die verwijst naar de twee geheimen die u hebt gemaakt in Key Vault:

    cat <<EOF | kubectl apply -f -
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: httpbin-credential-spc
    spec:
      provider: azure
      secretObjects:
      - secretName: httpbin-credential
        type: kubernetes.io/tls
        data:
        - objectName: test-httpbin-key
          key: tls.key
        - objectName: test-httpbin-crt
          key: tls.crt
      parameters:
        useVMManagedIdentity: "true"
        userAssignedIdentityID: $CLIENT_ID 
        keyvaultName: $AKV_NAME
        cloudName: ""
        objects:  |
          array:
            - |
              objectName: test-httpbin-key
              objectType: secret
              objectAlias: "test-httpbin-key"
            - |
              objectName: test-httpbin-crt
              objectType: secret
              objectAlias: "test-httpbin-crt"
        tenantId: $TENANT_ID
    EOF
    

Optie 2: Rechtstreeks naar een Key Vault certificaatobject verwijzen

Gebruik deze optie wanneer het certificaat al is opgeslagen in Azure Key Vault als certificaatobject. U hoeft de bestanden .crt en .key niet als aparte Key Vault-geheimen te uploaden.

In dit voorbeeld test-httpbin-cert-pfx is dit de naam van het certificaatobject in Azure Key Vault. Zie Een certificaat importeren in Key Vault om een bestaand certificaat in Key Vault als certificaatobject te importeren. Zie Certificaten en sleutels verkrijgen voor meer informatie over de objectparameters.

  1. Maak de SecretProviderClass die verwijst naar het Key Vault-certificaatobject:

    cat <<EOF | kubectl apply -f -
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: httpbin-credential-spc
    spec:
      provider: azure
      secretObjects:
      - secretName: httpbin-credential
        type: kubernetes.io/tls
        data:
        - objectName: test-httpbin-key
          key: tls.key
        - objectName: test-httpbin-crt
          key: tls.crt
      parameters:
        useVMManagedIdentity: "true"
        userAssignedIdentityID: $CLIENT_ID 
        keyvaultName: $AKV_NAME
        cloudName: ""
        objects:  |
          array:
            - |
              objectName: test-httpbin-cert-pfx  #certificate object name from keyvault
              objectType: secret
              objectAlias: "test-httpbin-key"
            - |
              objectName: test-httpbin-cert-pfx #certificate object name from keyvault
              objectType: cert
              objectAlias: "test-httpbin-crt"
        tenantId: $TENANT_ID
    EOF
    

Het geheim synchroniseren met het cluster

Nadat u optie 1 of optie 2 hebt voltooid, implementeert u een voorbeeldpod om het geheim in het cluster te synchroniseren. Het Secrets Store CSI-stuurprogramma vereist dat een pod verwijst naar de SecretProviderClass-resource, zodat geheimen vanuit Azure Key Vault naar het cluster worden gesynchroniseerd.

  1. Gebruik het volgende manifest om een voorbeeldpod te implementeren:

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: secrets-store-sync-httpbin
    spec:
      containers:
        - name: busybox
          image: mcr.microsoft.com/oss/busybox/busybox:1.33.1
          command:
            - "/bin/sleep"
            - "10"
          volumeMounts:
          - name: secrets-store01-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
      volumes:
        - name: secrets-store01-inline
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "httpbin-credential-spc"
    EOF
    
    • Controleer of het httpbin-credential geheim is gemaakt in de default naamruimte zoals gedefinieerd in de SecretProviderClass-resource.

      kubectl describe secret/httpbin-credential
      

      Voorbeelduitvoer:

      Name:         httpbin-credential
      Namespace:    default
      Labels:       secrets-store.csi.k8s.io/managed=true
      Annotations:  <none>
      
      Type:  kubernetes.io/tls
      
      Data
      ====
      tls.crt:  1180 bytes
      tls.key:  1675 bytes
      

TLS-gateway implementeren

  1. Maak een Kubernetes-gateway die verwijst naar het httpbin-credential geheim onder de TLS-configuratie:

    cat <<EOF | kubectl apply -f -
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-gateway
    spec:
      gatewayClassName: approuting-istio
      listeners:
      - name: https
        hostname: "httpbin.example.com"
        port: 443
        protocol: HTTPS
        tls:
          mode: Terminate
          certificateRefs:
          - name: httpbin-credential
        allowedRoutes:
          namespaces:
            from: Selector
            selector:
              matchLabels:
                kubernetes.io/metadata.name: default
    EOF
    

    Maak vervolgens HTTPRoute een overeenkomstige configuratie om de ingangsverkeerroutes van de gateway te configureren.

    cat <<EOF | kubectl apply -f -
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin
    spec:
      parentRefs:
      - name: httpbin-gateway
      hostnames: ["httpbin.example.com"]
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /status
        - path:
            type: PathPrefix
            value: /delay
        backendRefs:
        - name: httpbin
          port: 8000
    EOF
    

    Haal het gatewayadres en de poort op:

    kubectl wait --for=condition=programmed gateways.gateway.networking.k8s.io httpbin-gateway
    export INGRESS_HOST=$(kubectl get gateways.gateway.networking.k8s.io httpbin-gateway -o jsonpath='{.status.addresses[0].value}')
    export SECURE_INGRESS_PORT=$(kubectl get gateways.gateway.networking.k8s.io httpbin-gateway -o jsonpath='{.spec.listeners[?(@.name=="https")].port}')
    
  2. Een HTTPS-aanvraag verzenden om toegang te krijgen tot de httpbin service:

    curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
    --cacert httpbin_certs/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
    

    U ziet dat de httpbin-service de 418 ik een Teapot-code retourneert.