Usar o provedor do Azure Key Vault para o Driver CSI do Armazenamento de Segredos em um cluster do Serviço de Kubernetes do Azure (AKS)

O provedor do Azure Key Vault para o Driver CSI (Interface de Armazenamento de Contêiner) do repositório de segredos permite a integração de um Azure Key Vault como um repositório de segredos a um cluster do AKS (Serviço de Kubernetes do Azure) por meio de um volume de CSI.

Recursos

  • Monta segredos, chaves e certificados em um pod usando um volume de CSI.
  • Dá suporte a volumes em linha de CSI.
  • Dá suporte à montagem de vários objetos de armazenamento de segredos como um único volume.
  • É compatível com a portabilidade de pods com a SecretProviderClassCRD (Definição de Recurso Personalizado).
  • Dá suporte a contêineres do Windows.
  • Sincroniza com segredos do Kubernetes.
  • Dá suporte à rotação automática de conteúdo montado e segredos do Kubernetes sincronizados

Limitações

  • Um contêiner usando um ConfigMap ou um Secret como um ponto de montagem de volume subPath não recebe atualizações automáticas quando o segredo é rotacionado, o que é uma limitação do Kubernetes. Para que as alterações entrem em vigor, o aplicativo precisa recarregar o arquivo alterado observando as alterações no sistema de arquivos ou reiniciando o pod. Para obter mais informações, confira Limitações conhecidas do Driver CSI do Repositório de Segredos.
  • O complemento cria uma identidade gerenciada chamada azurekeyvaultsecretsprovider-xxxxx no grupo de recursos do nó (MC_) e a atribui automaticamente ao Conjunto de Dimensionamento de Máquinas Virtuais. Você pode usar essa identidade gerenciada ou sua própria identidade gerenciada para acessar o cofre de chaves. Não há suporte para impedir a criação da identidade.

Pré-requisitos

  • Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.
  • Verifique se sua versão da CLI do Azure é 2.30.0 ou posterior. Se ela for uma versão anterior, instale a última versão.
  • Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.

  • Terraform versão 1.6 ou posterior.

  • CLI do Azure instalado e conectado. instale a versão mais recente.

  • Permissões para criar os recursos AKS e Key Vault.

  • Defina sua assinatura Azure no CLI do Azure com o comando a seguir. Substitua <subscriptionId> por sua ID da assinatura.

    az account set --subscription <subscriptionId>
    

Rede

Funções

Criar um cluster do AKS

Crie um cluster AKS com o provedor Azure Key Vault para suporte ao Secrets Store CSI Driver.

  1. Crie variáveis usadas nos comandos para criar um cluster do AKS e o Key Vault.

    export RANDOM_STRING=$(printf '%05d%05d' "$RANDOM" "$RANDOM")
    export KEYVAULT_NAME=myKeyVault${RANDOM_STRING}
    export RESOURCE_GROUP=myResourceGroup
    export CLUSTER_NAME=myAKSCluster
    export LOCATION=eastus2
    

    Os nomes do Azure Key Vault devem ser globalmente exclusivos, alfanuméricos, incluindo hifens e 3 a 24 caracteres. O nome do cofre de chaves concatena o valor da variável KEYVAULT_NAMEmyKeyVault com o valor RANDOM_STRING e a string de 10 caracteres da variável.

  2. Crie um grupo de recursos do Azure usando o comando az group create.

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. Crie um cluster AKS com o fornecedor Azure Key Vault para a capacidade do Secrets Store CSI Driver utilizando o az aks create comando com o --enable-addons azure-keyvault-secrets-provider parâmetro.

    O --enable-addons parâmetro cria uma identidade gerenciada atribuída pelo usuário chamada azurekeyvaultsecretsprovider-xxxx que você pode usar para autenticar-se no cofre de chaves. A identidade gerenciada é armazenada no grupo de recursos do nó (MC_) e atribuída automaticamente ao Conjunto de Dimensionamento de Máquinas Virtuais. Você pode usar essa identidade gerenciada ou sua própria identidade gerenciada para acessar o cofre de chaves. Não há suporte para impedir a criação da identidade.

    az aks create \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP \
      --enable-addons azure-keyvault-secrets-provider \
      --generate-ssh-keys
    

    Dica

    Se você quiser usar a ID da Carga de Trabalho do Microsoft Entra, o comando az aks create deverá incluir os parâmetros --enable-oidc-issuer e --enable-workload-identity.

Criar um cluster do AKS

Crie um main.tf arquivo e copie a seguinte configuração de exemplo testada nele. O repositório GitHub terraform Azure mantém o exemplo. O exemplo cria o grupo de recursos, o cluster do AKS, o Azure Key Vault, o segredo de exemplo e as atribuições de função necessárias.

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.116"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.6"
    }
  }
}

provider "azurerm" {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
}

data "azurerm_client_config" "current" {}

resource "random_string" "suffix" {
  length  = 6
  upper   = false
  special = false
}

locals {
  location            = "eastus"
  resource_group_name = "rg-aks-kv-csi-demo-${random_string.suffix.result}"
  aks_name            = "aks-kv-csi-demo"
  key_vault_name      = "kvcsidemo${random_string.suffix.result}"
  secret_name         = "ExampleSecret"
}

resource "azurerm_resource_group" "this" {
  name     = local.resource_group_name
  location = local.location
}

resource "azurerm_log_analytics_workspace" "this" {
  name                = "law-aks-kv-csi-demo"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

resource "azurerm_kubernetes_cluster" "this" {
  name                      = local.aks_name
  location                  = azurerm_resource_group.this.location
  resource_group_name       = azurerm_resource_group.this.name
  dns_prefix                = "akskvcsidemo"
  kubernetes_version        = null
  oidc_issuer_enabled       = true
  workload_identity_enabled = true

  default_node_pool {
    name       = "system"
    node_count = 1
    vm_size    = "Standard_D2s_v3"

    upgrade_settings {
      drain_timeout_in_minutes      = 0
      max_surge                     = "10%"
      node_soak_duration_in_minutes = 0
    }
  }

  identity {
    type = "SystemAssigned"
  }

  key_vault_secrets_provider {
    secret_rotation_enabled = false
  }

  oms_agent {
    log_analytics_workspace_id = azurerm_log_analytics_workspace.this.id
  }

  network_profile {
    network_plugin    = "azure"
    load_balancer_sku = "standard"
  }

  tags = {
    scenario = "aks-keyvault-csi"
  }
}

resource "azurerm_key_vault" "this" {
  name                          = local.key_vault_name
  location                      = azurerm_resource_group.this.location
  resource_group_name           = azurerm_resource_group.this.name
  tenant_id                     = data.azurerm_client_config.current.tenant_id
  sku_name                      = "standard"
  purge_protection_enabled      = false
  soft_delete_retention_days    = 7
  enable_rbac_authorization     = true
  public_network_access_enabled = true
}

resource "azurerm_role_assignment" "current_user_kv_admin" {
  scope                = azurerm_key_vault.this.id
  role_definition_name = "Key Vault Administrator"
  principal_id         = data.azurerm_client_config.current.object_id
}

resource "azurerm_key_vault_secret" "example" {
  name         = local.secret_name
  value        = "HelloFromKeyVault"
  key_vault_id = azurerm_key_vault.this.id

  depends_on = [
    azurerm_role_assignment.current_user_kv_admin
  ]
}

resource "azurerm_role_assignment" "aks_csi_secrets_user" {
  scope                = azurerm_key_vault.this.id
  role_definition_name = "Key Vault Secrets User"
  # This is the managed identity automatically created by the AKS Key Vault CSI addon.
  principal_id = azurerm_kubernetes_cluster.this.key_vault_secrets_provider[0].secret_identity[0].object_id
}

output "resource_group_name" {
  value = azurerm_resource_group.this.name
}

output "aks_cluster_name" {
  value = azurerm_kubernetes_cluster.this.name
}

output "key_vault_name" {
  value = azurerm_key_vault.this.name
}

output "key_vault_secret_name" {
  value = azurerm_key_vault_secret.example.name
}

output "tenant_id" {
  value = data.azurerm_client_config.current.tenant_id
}

output "aks_csi_client_id" {
  value = azurerm_kubernetes_cluster.this.key_vault_secrets_provider[0].secret_identity[0].client_id
}

output "aks_csi_object_id" {
  value = azurerm_kubernetes_cluster.this.key_vault_secrets_provider[0].secret_identity[0].object_id
}
  1. Implante a configuração. Em uma sessão do Bash, execute os seguintes comandos para implantar os recursos:

    terraform init
    terraform validate
    terraform plan
    terraform apply
    
  2. Defina as variáveis usadas nos comandos restantes das saídas do Terraform:

    export RESOURCE_GROUP=$(terraform output -raw resource_group_name)
    export CLUSTER_NAME=$(terraform output -raw aks_cluster_name)
    export KEYVAULT_NAME=$(terraform output -raw key_vault_name)
    

Atualizar um cluster de AKS existente

Atualize um cluster do AKS existente com o provedor do Azure Key Vault para dar suporte ao Secrets Store CSI Driver.

  1. Crie variáveis usadas nos comandos. Substitua os valores conforme necessário para atualizar o cluster do AKS existente ou o Key Vault.

    Por exemplo, se você estiver usando um cofre de chaves existente, substitua o valor da variável KEYVAULT_NAME sem usar a variável RANDOM_STRING.

    Se você não tiver um cofre de chaves, os nomes do Azure Key Vault deverão ser globalmente exclusivos, alfanuméricos, incluindo hifens e 3 a 24 caracteres. O nome do cofre de chaves concatena o valor da variável KEYVAULT_NAMEmyKeyVault com o valor RANDOM_STRING e a string de 10 caracteres da variável. Você pode criar o cofre de chaves mais adiante neste artigo.

    export RANDOM_STRING=$(printf '%05d%05d' "$RANDOM" "$RANDOM")
    export KEYVAULT_NAME=myKeyVault${RANDOM_STRING}
    export RESOURCE_GROUP=myResourceGroup
    export CLUSTER_NAME=myAKSCluster
    export LOCATION=eastus2
    
  2. Atualize um cluster do AKS existente com a capacidade do provedor do Azure Key Vault para o Driver CSI do Repositório de Segredos, usando o comando az aks enable-addons com e habilite o complemento azure-keyvault-secrets-provider. O complemento cria uma identidade gerenciada atribuída pelo usuário que você pode usar para se autenticar no seu cofre de chaves.

    az aks enable-addons \
      --addons azure-keyvault-secrets-provider \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP
    

    Depois de habilitar o provedor de segredo do Azure Key Vault, o AKS cria uma identidade gerenciada chamada azurekeyvaultsecretsprovider-xxxx que você pode usar para autenticação no cofre de chaves. A identidade gerenciada é armazenada no grupo de recursos do nó (MC_) e atribuída automaticamente ao Conjunto de Dimensionamento de Máquinas Virtuais. Você pode usar essa identidade gerenciada ou sua própria identidade gerenciada para acessar o cofre de chaves. Não há suporte para impedir a criação da identidade.

Verifique a instalação da identidade gerenciada e do provedor de cofre de chaves

Os comandos a seguir usam as variáveis $RESOURCE_GROUP e $CLUSTER_NAME. Os fluxos de trabalho CLI do Azure definem essas variáveis anteriormente e o fluxo de trabalho do Terraform as define de saídas após a implantação.

Verificar a identidade gerenciada

Siga as etapas seguintes para verificar se a identidade gerenciada foi criada e atribuída ao Conjunto de Escala de Máquinas Virtuais do cluster.

  1. Verifique se a identidade gerenciada foi criada e atribuída ao cluster usando o az aks show comando.

    az aks show \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP \
      --query addonProfiles
    
    {
      "azureKeyvaultSecretsProvider": {
        "config": {
          "enableSecretRotation": "false",
          "rotationPollInterval": "2m"
        },
        "enabled": true,
        "identity": {
          "clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
          "objectId": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
          "resourceId": "/subscriptions/<subscriptionID>/resourcegroups/MC_myResourceGroup_myAKSCluster_eastus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/azurekeyvaultsecretsprovider-myakscluster"
        }
      }
    }
    

    A resourceId propriedade mostra o grupo de recursos e o nome azurekeyvaultsecretsprovider-myakscluster da identidade.

  2. Verifique se a identidade gerenciada está atribuída ao Conjunto de Dimensionamento de Máquinas Virtuais do grupo de recursos do nó.

    NODE_RG=$(az aks show \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP \
      --query nodeResourceGroup --output tsv)
    
    VMSS_NAME=$(az vmss list \
      --resource-group $NODE_RG \
      --query [].name --output tsv)
    
    az vmss show --name $VMSS_NAME --resource-group $NODE_RG --query '[id, identity]'
    

    A saída mostra o ID do recurso dos Conjuntos de Dimensionamento de Máquinas Virtuais Microsoft.Compute/virtualMachineScaleSets e a propriedade userAssignedIdentities com a ID de recurso para azurekeyvaultsecretsprovider-myakscluster que confirma que a identidade está atribuída ao Conjunto de Dimensionamento de Máquinas Virtuais.

Verificar o provedor do Azure Key Vault para a instalação do Driver do CSI do Armazenamento de Segredos

  1. Obtenha as credenciais de cluster do AKS usando o comando az aks get-credentials.

    az aks get-credentials \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP
    
  2. Verifique se a instalação foi concluída usando o comando kubectl get pods, que lista todos os pods com os rótulos secrets-store-csi-driver e secrets-store-provider-azure no namespace kube-system.

    kubectl get pods -n kube-system -l 'app in (secrets-store-csi-driver,secrets-store-provider-azure)' -o wide
    

    O sinalizador -o wide inclui o nó em que cada pod está sendo executado na saída.

    Seu resultado deve ser semelhante ao seguinte exemplo de saída:

    NAME                                     READY   STATUS    RESTARTS   AGE    NODE
    aks-secrets-store-csi-driver-4vpkj       3/3     Running   2          4m25s  aks-nodepool1-12345678-vmss000002
    aks-secrets-store-csi-driver-ctjq6       3/3     Running   2          4m21s  aks-nodepool1-12345678-vmss000001
    aks-secrets-store-csi-driver-tlvlq       3/3     Running   2          4m24s  aks-nodepool1-12345678-vmss000000
    aks-secrets-store-provider-azure-5p4nb   1/1     Running   0          4m21s  aks-nodepool1-12345678-vmss000000
    aks-secrets-store-provider-azure-6pqmv   1/1     Running   0          4m24s  aks-nodepool1-12345678-vmss000001
    aks-secrets-store-provider-azure-f5qlm   1/1     Running   0          4m25s  aks-nodepool1-12345678-vmss000002
    

Criar um novo cofre de chaves

Execute o az keyvault create comando para criar um novo cofre de chaves com o RBAC do Azure habilitado.

az keyvault create \
  --name $KEYVAULT_NAME \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --enable-rbac-authorization

O RBAC do Azure é habilitado por padrão quando você cria um novo cofre de chaves, mesmo que não inclua o --enable-rbac-authorization parâmetro.

Para obter mais informações sobre modelos de permissão do Key Vault e Azure RBAC, consulte Fornecer acesso às chaves, certificados e segredos do Key Vault com um controle de acesso baseado em função do Azure.

Atualizar o cofre de chaves existente

Execute o comando az keyvault update para atualizar um cofre de chaves existente com controle de acesso baseado em função do Azure (Azure RBAC). O parâmetro --enable-rbac-authorization é necessário para ativar o Azure RBAC quando você atualizar um cofre de chaves existente que tem Azure RBAC desabilitado.

az keyvault update \
  --name $KEYVAULT_NAME \
  --resource-group $RESOURCE_GROUP \
  --enable-rbac-authorization

Para obter mais informações sobre modelos de permissão do cofre de chaves e RBAC do Azure, consulte Fornecer acesso a chaves, certificados e segredos do Key Vault com um controle de acesso baseado em função do Azure

Adicionar atribuição de função e segredo ao cofre de chaves

  1. Execute o az keyvault show comando para verificar se o cofre de chaves tem o RBAC do Azure habilitado.

    az keyvault show \
      --name $KEYVAULT_NAME \
      --resource-group $RESOURCE_GROUP \
      --query properties.enableRbacAuthorization
    

    A saída deve ser true.

  2. Adicione uma atribuição de função para sua conta de usuário ao escopo do cofre de chaves usando o az role assignment create comando para que você possa adicionar um segredo do cofre de chaves na próxima etapa.

    A função Responsável pelos Segredos do Key Vault com identificador exclusivo b86a8fe4-44ce-4948-aee5-eccb2c155cd7 é adicionada e você pode usar o nome ou o identificador exclusivo. Usar o identificador exclusivo da função é uma prática recomendada para evitar problemas se o nome das funções for alterado.

    KEYVAULT_ID=$(az keyvault show \
      --name $KEYVAULT_NAME \
      --resource-group $RESOURCE_GROUP \
      --query id -o tsv)
    
    MYID=$(az ad signed-in-user show --query id --output tsv)
    
    az role assignment create \
      --assignee-object-id $MYID \
      --role "b86a8fe4-44ce-4948-aee5-eccb2c155cd7" \
      --scope $KEYVAULT_ID \
      --assignee-principal-type User
    

    Pode levar vários minutos para que a atribuição de função entre em vigor. Você pode verificar se a atribuição de função foi criada com o seguinte comando:

    az role assignment list \
      --assignee-object-id $MYID \
      --scope $KEYVAULT_ID \
      --query '[].{Role:roleDefinitionName, Scope:scope}' \
      --output table
    
  3. Crie um segredo de texto sem formatação nomeado ExampleSecret no cofre de chaves usando o az keyvault secret set comando.

    Seu cofre de chaves pode armazenar chaves, segredos e certificados. O value parâmetro usa a RANDOM_STRING variável para criar um valor exclusivo para o segredo.

    az keyvault secret set \
      --vault-name $KEYVAULT_NAME \
      --name ExampleSecret \
      --value MyAKSExampleSecret${RANDOM_STRING}
    
  4. Verifique se o segredo foi adicionado ao cofre de chaves usando o az keyvault secret show comando.

    az keyvault secret show --vault-name $KEYVAULT_NAME --name ExampleSecret
    

Criar um novo cofre de chaves

O exemplo do Terraform apresentado anteriormente cria um novo cofre de chaves com o Azure RBAC habilitado, atribui as funções necessárias e cria ExampleSecret. Nenhuma atualização de configuração separada é necessária.

  1. Obtenha o nome do cofre de chaves da saída do Terraform.

    KEYVAULT_NAME=$(terraform output -raw key_vault_name)
    
  2. Verifique se ExampleSecret foi adicionado ao cofre de chaves usando o az keyvault secret show comando.

    az keyvault secret show \
     --vault-name $KEYVAULT_NAME \
     --name ExampleSecret
    

Limpar os recursos

Se você estiver indo para o próximo artigo e precisar desses recursos, ignore as etapas a seguir. Caso contrário, se você terminar e não planeja continuar para o próximo artigo, deverá excluir os recursos criados neste artigo para evitar custos desnecessários.

  1. Remova as credenciais do cluster do arquivo .kube/config local.

    KUBE_CONTEXT=$(kubectl config current-context)
    kubectl config delete-context $KUBE_CONTEXT
    
  2. Exclua o grupo de recursos e todos os recursos dentro dele, incluindo recursos no grupo de recursos do nó (MC_) usando o comando az group delete.

    az group delete --name $RESOURCE_GROUP --yes --no-wait
    

O terraform destroy comando remove todos os recursos definidos na configuração do Terraform atual e no arquivo de estado. Execute este comando somente no diretório de trabalho usado para este artigo.

Aviso

Se você estiver trabalhando com recursos existentes ou de produção, examine o plano de execução cuidadosamente antes de executar:

terraform plan -destroy

Evite executar terraform destroy em uma infraestrutura compartilhada ou importada, a menos que tenha certeza de que é seguro remover. Para obter mais informações, consulte a documentação do Terraform para o comando terraform destroy .

  1. Remova as credenciais do cluster do arquivo .kube/config local.

    KUBE_CONTEXT=$(kubectl config current-context)
    kubectl config delete-context $KUBE_CONTEXT
    
  2. Execute o seguinte comando para remover os recursos criados neste artigo:

    terraform destroy
    

Próximas etapas

Neste artigo, você aprendeu a usar o provedor do Azure Key Vault para o Driver do CSI do Armazenamento de Segredos com um cluster do AKS. O exemplo do Terraform concede acesso de identidade complementar a segredos no cofre de chaves. Para configurar ou usar uma SecretProviderClass identidade diferente, prossiga para o próximo artigo.