Sécuriser le trafic d’entrée avec l’implémentation de l’API passerelle de routage d’application

Note

Cet article explique comment configurer manuellement la terminaison TLS sur une ressource Gateway en créant votre propre SecretProviderClass, en montant le fournisseur Azure Key Vault pour Secrets Store CSI Driver à l'aide d'un pod d'exemple, puis en faisant directement référence au secret Kubernetes ainsi obtenu dans le Gateway de l'écouteur certificateRefs. Cette approche est utile si vous avez besoin d’un contrôle total sur le flux de travail de synchronisation de certificats ou si vous préférez gérer ces ressources vous-même.

Pour la plupart des utilisateurs, l’approche recommandée est l’intégration automatisée d’Azure DNS et d’Azure Key Vault, assurée par l’opérateur de routage d’application, qui provisionne et réconcilie pour vous le SecretProviderClass, le Secret Kubernetes synchronisé et l’écouteur certificateRefs à partir d’une paire d’écouteurs tls.options. Pour utiliser le flux de travail automatisé, consultez Configurer Azure DNS et TLS avec l’implémentation de l’API passerelle de routage d’application.

Le module complémentaire de routage des applications prend en charge la synchronisation des secrets à partir d’Azure Key Vault (AKV) pour sécuriser le trafic d’entrée de l’API de passerelle avec l’arrêt TLS. Suivez les étapes ci-dessous pour créer des certificats et des clés pour arrêter le trafic TLS sur la passerelle.

Prerequisites

Certificats et clés client/serveur requis

  1. Créez un certificat racine et une clé privée pour signer les certificats pour les exemples de services :
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. Générez un certificat et une clé privée pour 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

Configurer une passerelle d’entrée TLS

Configurer Azure Key Vault et synchroniser les secrets avec le cluster

  1. Créer un Azure Key Vault

    Vous avez besoin d’une ressource Azure Key Vault pour fournir le certificat et les entrées de clé au module complémentaire de routage d’application.

    export AKV_NAME=<azure-key-vault-resource-name>  
    az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    
  2. Activez le module complémentaire Fournisseur Azure Key Vault pour le pilote CSI du magasin de secrets sur votre cluster.

    az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER
    
  3. Si votre coffre de clés utilise Azure RBAC pour le modèle d’autorisations, suivez les instructions ici pour attribuer un rôle Azure de Key Vault Secrets User à l'identité gérée attribuée par l'utilisateur du module complémentaire. Sinon, si votre coffre de clés utilise le modèle d’autorisations de stratégie d’accès au coffre, autorisez l’identité managée affectée par l’utilisateur du module complémentaire à accéder à la ressource Azure Key Vault à l’aide de la stratégie d’accès :

    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. Choisissez comment fournir le certificat TLS.

    Azure Key Vault prend en charge différents types d’objets. Pour cette procédure pas à pas, choisissez l’une des options de bout en bout suivantes, puis passez aux étapes courantes de validation et de passerelle.

    Option Utilisez cette option lorsque magasins Key Vault Résultat du Secret Kubernetes
    Option 1 : Stocker le certificat et la clé en tant que secrets Key Vault Vous disposez de fichiers de certificat PEM (.crt) et de clé.key privée () distincts, tels que les fichiers générés précédemment dans cet article. Deux secrets du coffre de clés Key Vault. Un secret TLS Kubernetes synchronisé nommé httpbin-credential.
    Option 2 : Référencer un objet de certificat Key Vault directement Votre certificat est déjà stocké dans Key Vault en tant qu’objet de certificat, tel qu’un objet importé.pfx. Un objet de certificat Key Vault. Un secret TLS Kubernetes synchronisé nommé httpbin-credential.

    Important

    Ne suivez pas les deux options. Si vous utilisez l’option 1, chargez les fichiers de certificat et de clé en tant que secrets Key Vault, puis appliquez le manifeste d’option 1SecretProviderClass. Si vous utilisez l’option 2, ignorez l’étape de chargement du secret Key Vault et appliquez le manifeste Option 2SecretProviderClass.

Option 1 : Stocker le certificat et la clé en tant que secrets Key Vault

Utilisez cette option lorsque vous avez des fichiers distincts de certificat PEM (.crt) et de clé privée (.key), tels que les fichiers générés précédemment dans cet article.

  1. Téléchargez les fichiers de certificat et de clé comme secrets dans Key Vault :

    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

    Chaque fois que vous faites pivoter (modifier) le certificat ou la clé, réexécutez cette étape pour charger les nouvelles versions en tant que secrets. Pour synchroniser automatiquement les valeurs mises à jour dans le cluster, activez la rotation automatique sur le fournisseur Azure Key Vault pour le pilote Secrets Store CSI. Pour plus d’informations, consultez la vue d’ensemble de l’autorotation et de la synchronisation des secrets. Si vous préférez avoir Key Vault gérer le cycle de vie des certificats, utilisez l’option 2 à la place.

  2. Créez le SecretProviderClass qui fait référence aux deux secrets que vous avez créés dans 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
    

Option 2 : Référencer un objet de certificat Key Vault directement

Utilisez cette option lorsque le certificat est déjà stocké dans Azure Key Vault en tant qu’objet de certificat. Vous n'avez pas besoin de téléverser les fichiers .crt et .key en tant que secrets distincts dans Key Vault.

Dans cet exemple, test-httpbin-cert-pfx est le nom de l’objet de certificat dans Azure Key Vault. Pour importer un certificat existant dans Key Vault en tant qu’objet de certificat, consultez Importer un certificat dans Key Vault. Pour plus d’informations sur les paramètres d’objet, consultez obtenir des certificats et des clés.

  1. Créez le SecretProviderClass qui fait référence à l’objet de certificat 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-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
    

Synchronisez le secret avec le cluster

Une fois l’option 1 ou l’option 2 terminée, déployez un exemple de pod pour synchroniser le secret dans le cluster. Le pilote Secrets Store CSI nécessite qu’un pod fasse référence à la ressource SecretProviderClass afin que les secrets soient synchronisés d’Azure Key Vault vers le cluster.

  1. Utilisez le manifeste suivant pour déployer un exemple de pod :

    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
    
    • Vérifiez que le httpbin-credential secret est créé dans l’espace de noms default tel que défini dans la ressource SecretProviderClass.

      kubectl describe secret/httpbin-credential
      

      Exemple de sortie :

      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
      

Déployer la passerelle TLS

  1. Créez une passerelle Kubernetes qui référence le httpbin-credential secret sous la configuration TLS :

    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
    

    Ensuite, créez un correspondant HTTPRoute pour configurer les itinéraires de trafic d’entrée de la passerelle :

    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
    

    Obtenez l’adresse et le port de la passerelle :

    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. Envoyez une requête HTTPS pour accéder au 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"
    

    Vous devriez voir le service httpbin retourner le code 418 I'm a Teapot.