Proteja o tráfego de entrada com a implementação da API Gateway de encaminhamento de aplicações

Note

Este artigo descreve como configurar manualmente a terminação TLS num Gateway recurso, criando o seu próprio SecretProviderClass, montando o provedor Azure Key Vault para o Secrets Store CSI Driver através de um sample pod, e referenciando o Kubernetes Secret resultante diretamente no Gateway arquivo do certificateRefsouvinte. Esta abordagem é útil se precisar de controlo total sobre o fluxo de trabalho de sincronização de certificados ou se preferir gerir estes recursos por si próprio.

Para a maioria dos utilizadores, o caminho recomendado é a integração automatizada do DNS do Azure e do Azure Key Vault, alimentada pelo operador Application Routeing, que fornece e reconcilia o SecretProviderClass, o Kubernetes Secret sincronizado e o ouvinte certificateRefs para si, com base num par de ouvintes tls.options. Para usar o fluxo de trabalho automatizado, consulte Configurar DNS do Azure e TLS com a implementação da API do Gateway de encaminhamento de aplicações.

O complemento de encaminhamento de aplicações suporta a sincronização de segredos do Azure Key Vault (AKV) para proteger o tráfego de entrada da API do Gateway com terminação TLS. Siga os passos abaixo para criar certificados e chaves para terminar o tráfego TLS no Gateway.

Pré-requisitos

Certificados e chaves cliente/servidor necessários

  1. Crie um certificado raiz e uma chave privada para assinar os certificados para serviços de exemplo:
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. Gerar um certificado e uma chave privada para 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

Configurar um gateway de entrada TLS

Configurar o Azure Key Vault e sincronizar segredos com o cluster

  1. Criar Azure Key Vault

    Precisas de um recurso Azure Key Vault para fornecer o certificado e as entradas de chave ao complemento de encaminhamento da aplicação.

    export AKV_NAME=<azure-key-vault-resource-name>  
    az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    
  2. Habilite o provedor do Azure Key Vault para o add-on Secret Store CSI Driver no seu cluster.

    az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER
    
  3. Se o seu Key Vault estiver a usar Azure RBAC para o modelo de permissões, siga as instruções aqui para atribuir um papel Azure de Key Vault Secrets User para a identidade gerida atribuída pelo utilizador do add-on. Alternativamente, se o seu cofre de chaves estiver a usar o modelo de permissões da política de acesso ao cofre, autorize a identidade gerida atribuída pelo utilizador ao add-on para aceder ao recurso do Azure Key Vault usando a política de acesso.

    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. Escolha como fornecer o certificado TLS.

    Azure Key Vault suporta diferentes tipos de objetos. Para este walkthrough, escolha uma das seguintes opções de ponta a ponta e continue com os passos comuns de validação e Gateway.

    Option Use esta opção quando O Key Vault armazena Resultado de Kubernetes Secret
    Opção 1: Guardar o certificado e a chave como segredos do Key Vault Tem ficheiros PEM de certificados (.crt) e de chave privada (.key) separados, como os ficheiros gerados anteriormente neste artigo. Dois segredos do Key Vault. Um segredo Kubernetes TLS sincronizado chamado httpbin-credential.
    Opção 2: Referenciar diretamente um objeto certificado do Key Vault O seu certificado já está armazenado no Key Vault como um objeto de certificado, como um .pfx importado. Um objeto de certificado do Key Vault. Um segredo Kubernetes TLS sincronizado chamado httpbin-credential.

    Importante

    Não sigas ambas as opções. Se usares a Opção 1, carrega o certificado e os ficheiros de chave como segredos do Key Vault e depois aplica o manifesto da Opção 1SecretProviderClass. Se usares a Opção 2, salta o passo de upload secreto do Key Vault e aplica o manifesto da Opção 2SecretProviderClass.

Opção 1: Guardar o certificado e a chave como segredos do Key Vault

Use esta opção quando tiver ficheiros de certificado PEM (.crt) e chave privada (.key) separados, como os ficheiros gerados anteriormente neste artigo.

  1. Carregue o certificado e os ficheiros de chave como segredos do 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

    Cada vez que alterar o certificado ou a chave, execute novamente este passo para carregar as novas versões como segredos. Para sincronizar automaticamente os valores atualizados no cluster, ative a autorrotação no fornecedor Azure Key Vault para o Secrets Store CSI Driver. Para mais informações, consulte Descrição geral da rotação automática e da sincronização de segredos. Se preferir que o Key Vault gere o ciclo de vida do certificado, use a Opção 2 em vez disso.

  2. Cria o SecretProviderClass que faz referência aos dois segredos que criaste no 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
    

Opção 2: Referenciar diretamente um objeto certificado do Key Vault

Use esta opção quando o certificado já estiver armazenado no Azure Key Vault como objeto certificado. Não precisa de carregar os ficheiros .crt e .key como segredos separados no Key Vault.

Neste exemplo, test-httpbin-cert-pfx é o nome do objeto de certificado no Cofre da Chave do Azure. Para importar um certificado existente no Key Vault como objeto de certificado, consulte Importar um certificado no Key Vault. Para mais informações sobre os parâmetros do objeto, consulte obter certificados e chaves.

  1. Crie o SecretProviderClass que faça referência ao objeto certificado 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
    

Sincronizar o segredo com o cluster

Depois de completares a Opção 1 ou a Opção 2, implementa um pod de amostras para sincronizar o segredo no cluster. O Secrets Store CSI Driver requer que um pod referencie o recurso SecretProviderClass para que os segredos sejam sincronizados do Azure Key Vault para o cluster.

  1. Use o seguinte manifesto para implementar um pod de exemplo:

    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
    
    • Verifique se o httpbin-credential segredo foi criado no default namespace conforme definido no recurso SecretProviderClass.

      kubectl describe secret/httpbin-credential
      

      Exemplo de saída:

      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
      

Implementar o Gateway TLS

  1. Crie um Gateway Kubernetes que faça referência ao segredo httpbin-credential na configuração de 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
    

    Depois, crie um correspondente HTTPRoute para configurar as rotas de tráfego de entrada do gateway:

    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
    

    Obtenha o endereço do gateway e a porta:

    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. Envie um pedido HTTPS para aceder ao httpbin serviço:

    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"
    

    Deves ver o serviço httpbin a devolver o código 418 I'm a Teapot.