Usar o provedor Azure Key Vault para o Secrets Store CSI Driver num cluster do Azure Kubernetes Service (AKS)

O fornecedor Azure Key Vault para o driver Secrets Store Container Storage Interface (CSI) permite a integração de um Azure Key Vault como um armazenamento secreto com um cluster Azure Kubernetes Service (AKS) através de um volume CSI.

Funcionalidades

  • Monta segredos, chaves e certificados em um pod usando um volume CSI.
  • Suporta os volumes em linha do CSI.
  • Suporta a montagem de vários objetos de armazenamento de segredos como um único volume.
  • Suporta portabilidade de pods com a SecretProviderClass Definição de Recursos Personalizados (CRD).
  • Suporta contêineres do Windows.
  • Sincroniza com segredos do Kubernetes.
  • Suporta autorotação de conteúdos montados e segredos sincronizados do Kubernetes.

Limitações

  • Um contentor que usa um ConfigMap ou Secret como subPath suporte de volume não recebe atualizações automáticas quando o segredo é rodado, 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, consulte Limitações conhecidas do driver CSI do Secrets Store.
  • O add-on cria uma identidade gerida nomeada azurekeyvaultsecretsprovider-xxxxx no grupo de recursos de nós (MC_) e atribui-a automaticamente ao Virtual Machine Scale Set. Você pode usar essa identidade gerenciada ou sua própria identidade gerenciada para acessar o cofre de chaves. Não é possível impedir a criação da identidade.

Pré-requisitos

  • Se não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar.
  • Verifique se a sua versão da CLI do Azure é 2.30.0 ou posterior. Se for uma versão anterior, instale a versão mais recente.
  • Se não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar.

  • Terraform na versão 1.6 ou superior.

  • CLI do Azure instalado e início de sessão efetuado. instale a versão mais recente.

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

  • Defina a sua subscrição do Azure na CLI do Azure com o seguinte comando. Substitua <subscriptionId> pelo seu ID de subscrição.

    az account set --subscription <subscriptionId>
    

Rede

Funções

Criar um cluster do AKS

Crie um cluster AKS com o fornecedor Azure Key Vault para suporte ao driver CSI da Secrets Store.

  1. Crie variáveis que sejam usadas nos comandos para criar um cluster AKS e 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 únicos, alfanuméricos incluindo hífens e 3-24 caracteres. O nome do cofre de chave concatena o KEYVAULT_NAME valor da myKeyVault variável com a RANDOM_STRING cadeia de 10 caracteres da variável.

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

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

    O --enable-addons parâmetro cria uma identidade gerida atribuída pelo utilizador chamada azurekeyvaultsecretsprovider-xxxx que podes usar para autenticar no teu cofre de chaves. A identidade gerida é armazenada no grupo de recursos de nós (MC_) e é automaticamente atribuída ao Virtual Machine Scale Set. Você pode usar essa identidade gerenciada ou sua própria identidade gerenciada para acessar o cofre de chaves. Não é possível 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
    

    Sugestão

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

Criar um cluster do AKS

Crie um main.tf ficheiro e copie para ele a seguinte configuração de exemplo testada. O repositório Azure Terraform GitHub 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. Implementa a configuração. A partir de uma sessão Bash, execute os seguintes comandos para implementar os recursos:

    terraform init
    terraform validate
    terraform plan
    terraform apply
    
  2. Defina as variáveis usadas nos comandos restantes dos resultados 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 AKS existente

Atualize um cluster AKS existente com o fornecedor Azure Key Vault para suporte ao driver CSI da Secrets Store.

  1. Cria variáveis que são usadas nos comandos. Substitua os valores conforme necessário para atualizar o seu cluster AKS existente ou Key Vault.

    Por exemplo, se estiveres a usar um cofre de chaves existente, substitui o KEYVAULT_NAME valor da variável sem usar a RANDOM_STRING variável.

    Se não tiveres um cofre de chaves, os nomes dos cofres de chaves do Azure devem ser globalmente únicos, alfanuméricos incluindo hífens, e ter entre 3 a 24 caracteres. O nome do cofre de chave concatena o KEYVAULT_NAME valor da myKeyVault variável com a RANDOM_STRING cadeia de 10 caracteres da variável. 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 AKS existente com o fornecedor Azure Key Vault para a capacidade Secrets Store CSI Driver usando o az aks enable-addons comando e ative o azure-keyvault-secrets-provider complemento. O complemento cria uma identidade gerenciada atribuída pelo usuário que você pode usar para autenticar no cofre de chaves.

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

    Depois de ativares o fornecedor de segredos Azure Key Vault, o AKS cria uma identidade gerida chamada azurekeyvaultsecretsprovider-xxxx que podes usar para autenticar no teu cofre de chaves. A identidade gerida é armazenada no grupo de recursos de nós (MC_) e é automaticamente atribuída ao Virtual Machine Scale Set. Você pode usar essa identidade gerenciada ou sua própria identidade gerenciada para acessar o cofre de chaves. Não é possível impedir a criação da identidade.

Verifique a instalação do fornecedor da identidade gerida e do cofre de chaves.

Os comandos seguintes usam as variáveis $CLUSTER_NAME e $RESOURCE_GROUP. Os fluxos de trabalho do CLI do Azure definem estas variáveis mais cedo, e o fluxo de trabalho do Terraform define-as a partir dos resultados após a implementação.

Verificar a identidade gerida

Use os seguintes passos para verificar se a identidade gerida foi criada e atribuída ao Virtual Machine Scale Set do cluster.

  1. Verifique se a identidade gerida 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"
        }
      }
    }
    

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

  2. Verifique se a identidade gerida está atribuída ao Virtual Machine Scale Set do grupo de recursos de nós.

    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 de recurso dos Conjuntos de Escalamento de Máquinas Virtuais Microsoft.Compute/virtualMachineScaleSets e a propriedade userAssignedIdentities com um ID de recurso para azurekeyvaultsecretsprovider-myakscluster que confirma que a identidade está atribuída aos Conjuntos de Escalamento de Máquinas Virtuais.

Verifique o provedor do Azure Key Vault para a instalação do Driver CSI do Secrets Store

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

    az aks get-credentials \
      --name $CLUSTER_NAME \
      --resource-group $RESOURCE_GROUP
    
  2. Verifique se a instalação está concluída usando o comando kubectl get pods, que lista todos os pods com as etiquetas 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
    

    A -o wide flag inclui o nó em que cada pod está a funcionar na saída.

    Sua saída deve ser semelhante à saída de exemplo a seguir:

    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 novo cofre de chaves

Executa o az keyvault create comando para criar um novo cofre de chaves com o Azure RBAC ativado.

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

O Azure RBAC está ativado por defeito quando crias um novo cofre de chaves, mesmo que não incluas o --enable-rbac-authorization parâmetro.

Para mais informações sobre modelos de permissões do Key Vault e Azure RBAC, consulte Fornecer acesso a chaves, certificados e segredos do Key Vault com controlo de acesso baseado em funções do Azure.

Atualizar o cofre de chaves existente

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

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

Para mais informações sobre modelos de permissões de cofres de chaves e Azure RBAC, consulte Fornecer acesso a chaves, certificados e segredos do Cofre de Chaves com controlo de acesso baseado em funções no Azure

Adicionar atribuição de função e chave secreta ao cofre de chaves

  1. Executa o az keyvault show comando para verificar se o cofre de chaves tem o Azure RBAC ativado.

    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ções para a sua conta de utilizador ao escopo do cofre de chaves usando o az role assignment create comando, para que possa adicionar um segredo do cofre de chaves no próximo passo.

    O papel de Oficial de Segredos do Cofre de Chaves com identificador b86a8fe4-44ce-4948-aee5-eccb2c155cd7 único foi adicionado e pode utilizar o nome ou o identificador único. Usar o identificador único da função é uma boa prática para evitar problemas caso o nome da função mude.

    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 demorar vários minutos até que a atribuição de funções faça efeito. Pode verificar se a atribuição de funções 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 em texto simples 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 único 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 novo cofre de chaves

O exemplo do Terraform incluído anteriormente cria um novo Key Vault com o Azure RBAC ativado, atribui as funções necessárias e cria ExampleSecret. Não é necessária uma atualização de configuração separada.

  1. Obtém o nome do cofre de chaves na saída do Terraform.

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

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

Limpeza de recursos

Se for para o próximo artigo e precisar destes recursos, ignore os passos seguintes. Caso contrário, se já terminou e não planeia continuar para o próximo artigo, deve eliminar os recursos criados neste artigo para evitar custos desnecessários.

  1. Remova as credenciais do seu cluster do seu ficheiro .kube/config local.

    KUBE_CONTEXT=$(kubectl config current-context)
    kubectl config delete-context $KUBE_CONTEXT
    
  2. Apague o grupo de recursos e todos os recursos dentro dele, incluindo os recursos no grupo de recursos de nós (MC_), utilizando 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 atual do Terraform e no ficheiro de estado. Execute este comando apenas a partir do diretório de trabalho utilizado neste artigo.

Advertência

Se estiver a trabalhar com recursos existentes ou de produção, reveja cuidadosamente o plano de execução antes de executar:

terraform plan -destroy

Evita executar terraform destroy em infraestruturas partilhadas ou importadas, a menos que tenha a certeza de que é seguro removê-las. Para mais informações, consulte a documentação do Terraform para o comando terraform destroy.

  1. Remova as credenciais do seu cluster do seu ficheiro .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óximos passos

Neste artigo, você aprendeu como usar o provedor do Cofre de Chaves do Azure para o Driver CSI do Repositório de Segredos em um cluster AKS. A amostra Terraform concede à identidade adicional acesso a segredos no cofre de chaves. Para configurar um SecretProviderClass ou utilizar uma identidade diferente, avance para o artigo seguinte.