Conectar seu provedor de identidade do Azure ao Driver da CSI do Repositório de Segredos do Azure Key Vault no AKS (Serviço de Kubernetes do Azure)

O Driver da CSI (Interface de Armazenamento de Contêiner) do Repositório de Segredos no AKS (Serviço de Kubernetes do Azure) fornece vários métodos de acesso baseado em identidade ao seu Azure Key Vault. Este artigo descreve esses métodos e melhores práticas para quando usar os modelos de segurança do RBAC (controle de acesso baseado em função) ou do OIDC (OpenID Connect) para acessar o cofre de chaves e o cluster do AKS.

Você pode usar um dos seguintes métodos de acesso:

Pré-requisitos do Driver da CSI

Acesso com uma ID de carga de trabalho do Microsoft Entra

Uma ID de Carga de Trabalho do Microsoft Entra é uma identidade que um aplicativo em execução em um pod usa para se autenticar em outros serviços do Azure, como cargas de trabalho no software. O Driver da CSI do Repositório de Segredos se integra aos recursos nativos do Kubernetes para federar com provedores de identidade externos.

Nesse modelo de segurança, o cluster do AKS atua como emissor de token. Em seguida, o Microsoft Entra ID usa o OIDC para descobrir as chaves de assinatura públicas e verificar a autenticidade do token da conta de serviço antes de trocá-lo por um token do Microsoft Entra. Para sua carga de trabalho trocar um token de conta de serviço projetado para o seu volume por um token do Microsoft Entra, você precisa da biblioteca de clientes do Azure Identity no SDK do Azure ou da MSAL (Biblioteca de Autenticação da Microsoft)

Observação

  • Esse método de autenticação substitui a identidade gerenciada por pod do Microsoft Entra (versão prévia). A identidade gerenciada por pod do Microsoft Entra de software livre (versão prévia) no Serviço de Kubernetes do Azure foi preterida a partir de 24/10/2022.
  • A ID de Carga de Trabalho do Microsoft Entra dá suporte a clusters do Windows e do Linux.

Configurar identidade de carga de trabalho

  1. Defina a assinatura usando o comando az account set.

    export SUBSCRIPTION_ID=<subscription id>
    export RESOURCE_GROUP=<resource group name>
    export UAMI=<name for user assigned identity>
    export KEYVAULT_NAME=<existing keyvault name>
    export CLUSTER_NAME=<aks cluster name>
    
    az account set --subscription $SUBSCRIPTION_ID
    
  2. Crie uma identidade gerenciada usando o comando az identity create.

    az identity create --name $UAMI --resource-group $RESOURCE_GROUP
    
    export USER_ASSIGNED_CLIENT_ID="$(az identity show -g $RESOURCE_GROUP --name $UAMI --query 'clientId' -o tsv)"
    export IDENTITY_TENANT=$(az aks show --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --query identity.tenantId -o tsv)
    
  3. Crie uma atribuição de função que conceda à identidade da carga de trabalho permissão para acessar os segredos do cofre de chaves, as chaves de acesso e os certificados, utilizando o comando az role assignment create.

    export KEYVAULT_SCOPE=$(az keyvault show --name $KEYVAULT_NAME --query id -o tsv)
    
    az role assignment create --role "Key Vault Administrator" --assignee $USER_ASSIGNED_CLIENT_ID --scope $KEYVAULT_SCOPE
    
  4. Obtenha a URL do Emissor OIDC do cluster do AKS usando o comando az aks show.

    Observação

    Esta etapa pressupõe que você tenha um cluster AKS existente com a URL do Emissor OIDC habilitada. Se você não o tiver habilitado, consulte Atualizar um cluster do AKS com o Emissor OIDC para habilitá-lo.

    export AKS_OIDC_ISSUER="$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "oidcIssuerProfile.issuerUrl" -o tsv)"
    echo $AKS_OIDC_ISSUER
    
  5. Estabeleça uma credencial de identidade federada entre o aplicativo do Microsoft Entra, o emissor da conta de serviço e o assunto. Obtenha a ID de objeto de aplicativo do Microsoft Entra usando os comandos a seguir. Atualize os valores de serviceAccountName e serviceAccountNamespace com o nome e o namespace da conta de serviço do Kubernetes.

    export SERVICE_ACCOUNT_NAME="workload-identity-sa"  # sample name; can be changed
    export SERVICE_ACCOUNT_NAMESPACE="default" # can be changed to namespace of your workload
    
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        azure.workload.identity/client-id: ${USER_ASSIGNED_CLIENT_ID}
      name: ${SERVICE_ACCOUNT_NAME}
      namespace: ${SERVICE_ACCOUNT_NAMESPACE}
    EOF
    
  6. Crie a credencial de identidade federada entre a identidade gerenciada, o emissor da conta de serviço e o assunto usando o comando az identity federated-credential create.

    export FEDERATED_IDENTITY_NAME="aksfederatedidentity" # can be changed as needed
    
    az identity federated-credential create --name $FEDERATED_IDENTITY_NAME --identity-name $UAMI --resource-group $RESOURCE_GROUP --issuer ${AKS_OIDC_ISSUER} --subject system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}
    
  7. Implante um SecretProviderClass usando o comando kubectl apply e o script YAML a seguir.

    cat <<EOF | kubectl apply -f -
    # This is a SecretProviderClass example using workload identity to access your key vault
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: azure-kvname-wi # needs to be unique per namespace
    spec:
      provider: azure
      parameters:
        usePodIdentity: "false"
        clientID: "${USER_ASSIGNED_CLIENT_ID}" # Setting this to use workload identity
        keyvaultName: ${KEYVAULT_NAME}       # Set to the name of your key vault
        cloudName: ""                         # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud
        objects:  |
          array:
            - |
              objectName: secret1             # Set to the name of your secret
              objectType: secret              # object types: secret, key, or cert
              objectVersion: ""               # [OPTIONAL] object versions, default to latest if empty
            - |
              objectName: key1                # Set to the name of your key
              objectType: key
              objectVersion: ""
        tenantId: "${IDENTITY_TENANT}"        # The tenant ID of the key vault
    EOF
    

    Observação

    Se você usar objectAlias em vez de objectName, atualize o script do YAML para considerá-lo.

    Observação

    Para que o SecretProviderClass funcione corretamente, preencha seu Azure Key Vault com segredos, chaves ou certificados antes de referenciá-los na seção objects.

  8. Implante um pod de exemplo usando o comando kubectl apply e o script YAML a seguir.

    cat <<EOF | kubectl apply -f -
    # This is a sample pod definition for using SecretProviderClass and workload identity to access your key vault
    kind: Pod
    apiVersion: v1
    metadata:
      name: busybox-secrets-store-inline-wi
      labels:
        azure.workload.identity/use: "true"
    spec:
      serviceAccountName: "workload-identity-sa"
      containers:
        - name: busybox
          image: registry.k8s.io/e2e-test-images/busybox:1.29-4
          command:
            - "/bin/sleep"
            - "10000"
          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: "azure-kvname-wi"
    EOF
    

Acesso com identidade gerenciada

Uma ID Gerenciada do Microsoft Entra é uma identidade que um administrador usa para se autenticar em outros serviços do Azure. A identidade gerenciada usa o RBAC para federar com provedores de identidade externos.

Neste modelo de segurança, você pode conceder acesso aos recursos do cluster para locatários ou membros da equipe compartilhando uma função gerenciada. A função é verificada quanto ao escopo para acessar o keyvault e outras credenciais. Quando você habilitou o provedor do Azure Key Vault para o Driver da CSI do Repositório de Segredos no cluster do AKS, ele criou uma identidade de usuário.

Configurar uma identidade gerenciada

  1. Acesse o cofre de chaves usando o comando az aks show e a identidade gerenciada atribuída pelo usuário criada pelo complemento. Você também deve recuperar o clientId da identidade, que você usará em etapas posteriores ao criar SecretProviderClass.

    az aks show -g <resource-group> -n <cluster-name> --query addonProfiles.azureKeyvaultSecretsProvider.identity.objectId -o tsv
    az aks show -g <resource-group> -n <cluster-name> --query addonProfiles.azureKeyvaultSecretsProvider.identity.clientId -o tsv
    

    Como alternativa, você pode criar uma identidade gerenciada e atribuí-la ao conjunto de dimensionamento de VMs (máquinas virtuais) ou a cada instância de VM do conjunto de disponibilidade usando os comandos a seguir.

    az identity create -g <resource-group> -n <identity-name>
    az vmss identity assign -g <resource-group> -n <agent-pool-vmss> --identities <identity-resource-id>
    az vm identity assign -g <resource-group> -n <agent-pool-vm> --identities <identity-resource-id>
    
    az identity show -g <resource-group> --name <identity-name> --query 'clientId' -o tsv
    
  2. Crie uma atribuição de função que conceda permissão à identidade para acessar os segredos do cofre de chaves, as chaves de acesso e os certificados, utilizando o comando az role assignment create.

    export IDENTITY_OBJECT_ID="$(az identity show -g <resource-group> --name <identity-name> --query 'principalId' -o tsv)"
    export KEYVAULT_SCOPE=$(az keyvault show --name <key-vault-name> --query id -o tsv)
    
    az role assignment create --role "Key Vault Administrator" --assignee $IDENTITY_OBJECT_ID --scope $KEYVAULT_SCOPE
    
  3. Crie um SecretProviderClass usando o seguinte YAML. Certifique-se de usar os seus próprios valores de userAssignedIdentityID, keyvaultName e tenantId e os objetos a serem recuperados do cofre de chaves.

    # This is a SecretProviderClass example using user-assigned identity to access your key vault
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: azure-kvname-user-msi
    spec:
      provider: azure
      parameters:
        usePodIdentity: "false"
        useVMManagedIdentity: "true"          # Set to true for using managed identity
        userAssignedIdentityID: <client-id>   # Set the clientID of the user-assigned managed identity to use
        keyvaultName: <key-vault-name>        # Set to the name of your key vault
        cloudName: ""                         # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud
        objects:  |
          array:
            - |
              objectName: secret1
              objectType: secret              # object types: secret, key, or cert
              objectVersion: ""               # [OPTIONAL] object versions, default to latest if empty
            - |
              objectName: key1
              objectType: key
              objectVersion: ""
        tenantId: <tenant-id>                 # The tenant ID of the key vault
    

    Observação

    Se você usar objectAlias em vez de objectName, certifique-se de atualizar o script YAML.

    Observação

    Para que o SecretProviderClass funcione corretamente, preencha seu Azure Key Vault com segredos, chaves ou certificados antes de referenciá-los na seção objects.

  4. Aplique o SecretProviderClass ao seu cluster usando o comando kubectl apply.

    kubectl apply -f secretproviderclass.yaml
    
  5. Crie um pod usando o seguinte YAML.

    # This is a sample pod definition for using SecretProviderClass and the user-assigned identity to access your key vault
    kind: Pod
    apiVersion: v1
    metadata:
      name: busybox-secrets-store-inline-user-msi
    spec:
      containers:
        - name: busybox
          image: registry.k8s.io/e2e-test-images/busybox:1.29-4
          command:
            - "/bin/sleep"
            - "10000"
          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: "azure-kvname-user-msi"
    
  6. Aplique o pod ao cluster usando o comando kubectl apply.

    kubectl apply -f pod.yaml
    

Validar segredos do Key Vault

Depois que o pod é iniciado, o conteúdo montado no caminho do volume especificado no YAML de implantação fica disponível. Use os comandos a seguir para validar seus segredos e imprimir um segredo de teste.

  1. Mostre os segredos mantidos no repositório de segredos usando o comando a seguir.

    kubectl exec busybox-secrets-store-inline-user-msi -- ls /mnt/secrets-store/
    
  2. Exiba um segredo no repositório usando o comando a seguir. Este comando de exemplo mostra o segredo de teste ExampleSecret.

    kubectl exec busybox-secrets-store-inline-user-msi -- cat /mnt/secrets-store/ExampleSecret
    

Obter certificados e chaves

O design do Azure Key Vault faz distinções claras entre chaves, segredos e certificados. Os recursos de certificado do serviço do Key Vault foram feitos para usar recursos de chave e de segredo. Quando você cria um certificado de cofre de chaves, ele cria uma chave endereçável e um segredo com o mesmo nome. Essa chave permite operações de autenticação e o segredo permite a recuperação do valor do certificado como um segredo.

Um certificado de cofre de chaves também contém metadados do certificado x509 público. O cofre de chaves armazena os componentes públicos e privados do certificado em um segredo. Você pode obter cada componente individual especificando o objectType em SecretProviderClass. A seguinte tabela mostra os objetos que são mapeados para os vários recursos associados ao seu certificado:

Objeto Valor retornado Retorna toda a cadeia de certificados
key A chave pública, no formato Privacy Enhanced Mail (PEM). N/D
cert O certificado, no formato PEM. Não
secret A chave privada e o certificado, no formato PEM. Sim

Desabilitar o complemento em clusters existentes

Observação

Antes de desabilitar o complemento, certifique-se de que nenhumSecretProviderClass esteja em uso. Tentar desativar o complemento enquanto um SecretProviderClass existe resulta em um erro.

  • Desabilite a capacidade do provedor do Azure Key Vault para o Driver do CSI do Armazenamento de Segredos em um cluster existente, usando o comando az aks disable-addons com o complemento azure-keyvault-secrets-provider.

    az aks disable-addons --addons azure-keyvault-secrets-provider -g myResourceGroup -n myAKSCluster
    

Observação

Quando você desabilita o complemento, as cargas de trabalho existentes não devem ter problemas ou ver atualizações nos segredos montados. Se o pod for reiniciado ou um pod for criado como parte do evento da escala vertical, o pod não será reiniciado porque o driver não está mais em execução.

Próximas etapas

Neste artigo, você aprendeu a criar e fornecer uma identidade para acessar seu Azure Key Vault. Se você quiser configurar opções de configuração extras ou executar a solução de problemas, prossiga para o próximo artigo.