Configurar a federação de identidade da carga de trabalho com o Kubernetes

Neste guia, descrevemos como usar a federação de identidade da carga de trabalho para permitir que as cargas de trabalho executadas no Serviço do Azure Kubernetes (AKS), no Amazon Elastic Kubernetes Service ou em um cluster auto-hospedado do Kubernetes sejam autenticadas no Google Cloud.

O Kubernetes permite configurar um cluster para que as cargas de trabalho recebam tokens da conta de serviço do Kubernetes de um volume projetado. Ao configurar a federação de identidade da carga de trabalho, é possível permitir que elas usem esses tokens de conta de serviço do Kubernetes para se autenticar no Google Cloud.

Se você estiver usando o GKE, use a Identidade da carga de trabalho em vez de configurar a federação de identidade da carga de trabalho.

Antes de começar

Antes de configurar a federação de identidade da carga de trabalho, verifique se o cluster do Kubernetes atende aos seguintes critérios:

AKS

O cluster precisa atender aos seguintes requisitos:

  • Você ativou o recurso emissor do OIDC (em inglês).

    Ative esse recurso para que a federação de identidade da carga de trabalho possa acessar os metadados do OpenID Connect e o conjunto de chaves da Web JSON (JWKS, na sigla em inglês) do cluster.

EKS

Não é necessário fazer mudanças na configuração do EKS.

Kubernetes

O cluster precisa atender aos seguintes requisitos:

O cluster não precisa ser acessível pela Internet.

Configurar a federação de identidade da força de trabalho

Você só precisa realizar essas etapas uma vez para cada cluster do Kubernetes. Depois disso, será possível usar o mesmo pool de identidade da carga de trabalho e servidor em várias cargas de trabalho e em vários projetos do Google Cloud.

Para começar a configurar a federação de identidade da carga de trabalho, faça o seguinte:

  1. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  2. Recomendamos que você use um projeto dedicado para gerenciar pools de identidade da carga de trabalho e de transporte público.
  3. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  4. Ative as APIs IAM, Resource Manager, Service Account Credentials, and Security Token Service.

    Ative as APIs

Definir um mapeamento e uma condição de atributo

Os tokens de conta de serviço do Kubernetes contêm várias declarações, incluindo:

  • sub: contém o namespace e o nome da conta de serviço, por exemplo, system:serviceaccount:NAMESPACE:KSA_NAME, em que NAMESPACE é o namespace da conta de serviço e KSA_NAME é o nome da conta de serviço.
  • "kubernetes.io".namespace: contém o namespace da conta de serviço.
  • "kubernetes.io".serviceaccount.name: contém o nome da conta de serviço.
  • "kubernetes.io".pod.name: contém o nome do pod.

Para usar sub como identificador de assunto (google.subject) no Google Cloud, use o seguinte mapeamento:

google.subject=assertion.sub

Também é possível mapear outros atributos. Consulte esses atributos ao conceder acesso aos recursos. Exemplo:

google.subject=assertion.sub,
attribute.namespace=assertion['kubernetes.io']['namespace'],
attribute.service_account_name=assertion['kubernetes.io']['serviceaccount']['name'],
attribute.pod=assertion['kubernetes.io']['pod']['name']

Também é possível definir uma condição de atributo. As condições do atributo são expressões CEL que podem verificar atributos de declaração e atributos de destino. Se a condição do atributo for avaliada como true para uma determinada credencial, a credencial será aceita. Caso contrário, a credencial será rejeitada.

É possível usar uma condição de atributo para restringir quais contas de serviço do Kubernetes podem usar a federação de identidade de carga de trabalho para receber tokens de curta duração do Google Cloud. Por exemplo, a condição a seguir restringe o acesso às contas de serviço do Kubernetes dos namespaces backend e monitoring:

assertion['kubernetes.io']['namespace'] in ['backend', 'monitoring']

Crie um pool de identidades e um provedor de carga de trabalho

Funções exigidas

Para receber as permissões necessárias para configurar a federação de identidade da carga de trabalho, peça ao administrador para conceder a você os seguintes papéis do IAM no projeto:

Para mais informações sobre como conceder papéis, consulte Gerenciar acesso.

Também é possível conseguir as permissões necessárias com papéis personalizados ou outros papéis predefinidos.

Como alternativa, o papel básico de Proprietário do IAM (roles/owner) também inclui permissões para configurar a federação de identidade. Não conceda papéis básicos em um ambiente de produção, recomendamos que você faça isso em um ambiente de desenvolvimento ou teste.

Para criar um pool de identidades e um provedor de carga de trabalho, faça o seguinte:

AKS

  1. Determine o URL do emissor do cluster do AKS:

    az aks show -n NAME -g RESOURCE_GROUP --query "oidcIssuerProfile.issuerUrl" -otsv
    

    Substitua:

    • NAME: o nome do cluster.
    • RESOURCE_GROUP: o grupo de recursos do cluster.

    O comando gera o URL do emissor. Você precisa do URL do emissor em uma das etapas a seguir.

    Se o comando não retornar um URL do emissor, verifique se você ativou o recurso emissor do OIDC.

  2. Crie um novo pool de identidades de carga de trabalho:

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    Substitua:

    • POOL_ID: o ID exclusivo do pool.
    • DISPLAY_NAME: o nome do pool.
    • DESCRIPTION: uma descrição do pool escolhido. Essa descrição aparece quando você concede acesso às identidades do pool.
  3. Adicione o cluster do AKS como um provedor de pool de Identidade da carga de trabalho:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    Substitua:

    • PROVIDER_ID: um ID de provedor do pool de Identidade da carga de trabalho exclusivo de sua escolha.
    • POOL_ID: o ID do pool de Identidade da carga de trabalho que você criou anteriormente.
    • ISSUER: o URI do emissor que você determinou anteriormente.
    • MAPPINGS: uma lista separada por vírgulas de mapeamentos de atributos criados anteriormente neste guia.
    • CONDITIONS: uma condição de atributo opcional que você criou anteriormente neste guia. Remova o parâmetro se você não tiver uma condição de atributo.

EKS

  1. Determine o URL do emissor do cluster do EKS:

    aws eks describe-cluster --name NAME --query "cluster.identity.oidc.issuer" --output text
    

    Substitua NAME pelo nome do cluster.

    O comando gera o URL do emissor. Você precisa do URL do emissor em uma das etapas a seguir.

  2. Crie um novo pool de identidades de carga de trabalho:

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    Substitua:

    • POOL_ID: o ID exclusivo do pool.
    • DISPLAY_NAME: o nome do pool.
    • DESCRIPTION: uma descrição do pool escolhido. Essa descrição aparece quando você concede acesso às identidades do pool.
  3. Adicione o cluster do EKS como um provedor de pool de Identidade da carga de trabalho:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    Substitua:

    • PROVIDER_ID: um ID de provedor do pool de Identidade da carga de trabalho exclusivo de sua escolha.
    • POOL_ID: o ID do pool de Identidade da carga de trabalho que você criou anteriormente.
    • ISSUER: o URI do emissor que você determinou anteriormente.
    • MAPPINGS: uma lista separada por vírgulas de mapeamentos de atributos criados anteriormente neste guia.
    • CONDITIONS: uma condição de atributo opcional que você criou anteriormente neste guia. Remova o parâmetro se você não tiver uma condição de atributo.

Kubernetes

  1. Conecte-se ao cluster do Kubernetes e use kubectl para determinar o URL do emissor do cluster:

    kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
    

    Você precisa do URL do emissor em uma das etapas a seguir.

  2. Faça o download do conjunto de chaves da Web JSON (JWKS, na sigla em inglês) do cluster:

    kubectl get --raw /openid/v1/jwks > cluster-jwks.json
    

    Em uma das etapas a seguir, faça upload do JWKS para que a federação de identidade da carga de trabalho possa verificar a autenticidade dos tokens da conta de serviço do Kubernetes emitidos pelo cluster.

  3. Crie um novo pool de identidades de carga de trabalho:

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    Substitua:

    • POOL_ID: o ID exclusivo do pool.
    • DISPLAY_NAME: o nome do pool.
    • DESCRIPTION: uma descrição do pool escolhido. Essa descrição aparece quando você concede acesso às identidades do pool.
  4. Adicione o cluster do Kubernetes como provedor de pool de identidades de carga de trabalho e faça upload do JWKS do cluster:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS" \
        --jwk-json-path="cluster-jwks.json"
    

    Substitua:

    • PROVIDER_ID: um ID de provedor do pool de Identidade da carga de trabalho exclusivo de sua escolha.
    • POOL_ID: o ID do pool de Identidade da carga de trabalho que você criou anteriormente.
    • ISSUER: o URI do emissor que você determinou anteriormente.
    • MAPPINGS: uma lista separada por vírgulas de mapeamentos de atributos criados anteriormente neste guia.
    • CONDITIONS: uma condição de atributo opcional que você criou anteriormente neste guia. Remova o parâmetro se você não tiver uma condição de atributo.

Autenticar uma carga de trabalho do Kubernetes

Nesta seção, descrevemos como configurar uma carga de trabalho do Kubernetes para usar a federação de identidade da carga de trabalho.

Execute essas etapas uma vez para cada carga de trabalho do Kubernetes que precise de acesso ao Google Cloud.

Criar um par de contas de serviço

Para permitir que uma carga de trabalho do Kubernetes seja autenticada no Google Cloud, você precisa de um par de contas de serviço:

  • Uma conta de serviço do Kubernetes que você anexa ao pod do Kubernetes.
  • Uma conta de serviço do IAM que a carga de trabalho do Kubernetes pode representar usando a conta de serviço do Kubernetes anexada.

Para criar as contas de serviço, faça o seguinte:

  1. Crie uma conta de serviço do IAM que represente a carga de trabalho.

    A conta de serviço não precisa estar no mesmo projeto que o pool de identidades da carga de trabalho.

    gcloud iam service-accounts create SA_NAME
    

    Substitua:

    • SA_NAME: o nome da conta de serviço.
  2. Crie uma conta de serviço do Kubernetes:

    kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
    

    Substitua:

    • KSA_NAME: o nome da conta de serviço.
    • NAMESPACE: o namespace em que a conta de serviço será criada.
  3. Conceda à conta de serviço do IAM acesso aos recursos que você quer que a carga de trabalho do Kubernetes acesse.

  4. Conceda o papel de Usuário da Identidade da carga de trabalho (roles/iam.workloadIdentityUser) à identidade externa da conta de serviço do Kubernetes:

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/iam.workloadIdentityUser \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT"
    

    Substitua:

    • SERVICE_ACCOUNT_EMAIL: o endereço de e-mail da conta de serviço.
    • PROJECT_NUMBER: o número do projeto que contém o pool de identidade da carga de trabalho
    • POOL_ID: o ID do pool de identidade da carga de trabalho
    • SUBJECT: o valor esperado para o atributo que você mapeou para google.subject, por exemplo, system:serviceaccount:NAMESPACE:KSA_NAME.

Implantar a carga de trabalho do Kubernetes

Agora implante uma carga de trabalho do Kubernetes e permita que ela use o par de contas de serviço:

  1. Crie um arquivo de configuração de credenciais:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --credential-source-file=/var/run/service-account/token \
        --credential-source-type=text \
        --output-file=credential-configuration.json
    

    Substitua:

    • PROJECT_NUMBER: o número do projeto que contém o pool de identidades da carga de trabalho
    • POOL_ID: o ID do pool de identidades da carga de trabalho
    • PROVIDER_ID: o ID do provedor do pool de identidades da carga de trabalho
    • SERVICE_ACCOUNT_EMAIL: endereço de e-mail da conta de serviço

    O arquivo de configuração de credenciais permite que as bibliotecas de cliente do Cloud, a CLI gcloud e o Terraform determinem o seguinte:

    • De onde receber credenciais externas
    • Qual pool de identidades de carga de trabalho e provedor usar
    • Qual conta de serviço representar
  2. Importe o arquivo de configuração de credenciais como um ConfigMap:

    kubectl create configmap CONFIGMAP_NAME \
      --from-file credential-configuration.json \
      --namespace NAMESPACE
    

    Substitua:

    • CONFIGMAP_NAME: o nome do ConfigMap.
    • NAMESPACE: o namespace em que o ConfigMap será criado.
  3. Implante uma carga de trabalho e permita que ela use a conta de serviço do Kubernetes e o ConfigMap.

    Crie um manifesto e configure-o da seguinte maneira:

    • Ative um volume de token projetado para que a carga de trabalho possa receber um token de conta de serviço do Kubernetes de um arquivo local. Configure o volume para que o token da conta de serviço do Kubernetes use o público-alvo esperado pelo provedor do pool de federação de identidade da carga de trabalho.
    • Ative o ConfigMap que contém o arquivo de configuração da credencial para que a carga de trabalho possa acessar a configuração necessária para usar a federação de identidade da carga de trabalho.
    • Adicione uma variável de ambiente GOOGLE_APPLICATION_CREDENTIALS que contenha o caminho do arquivo de configuração da credencial para que as cargas de trabalho possam encontrá-lo.

    Veja a seguir um manifesto de exemplo que usa a conta de serviço do Kubernetes e o ConfigMap para permitir que a Google Cloud CLI seja autenticada no Google Cloud:

    apiVersion: v1
    kind: Pod
    metadata:
      name: example
      namespace: NAMESPACE
    spec:
      containers:
      - name: example
        image: google/cloud-sdk:alpine
        command: ["/bin/sh", "-c", "gcloud auth login --cred-file $GOOGLE_APPLICATION_CREDENTIALS && gcloud auth list && sleep 600"]
        volumeMounts:
        - name: token
          mountPath: "/var/run/service-account"
          readOnly: true
        - name: workload-identity-credential-configuration
          mountPath: "/etc/workload-identity"
          readOnly: true
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: "/etc/workload-identity/credential-configuration.json"
    
      serviceAccountName: KSA_NAME
      volumes:
      - name: token
        projected:
          sources:
          - serviceAccountToken:
              audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
              expirationSeconds: 3600
              path: token
      - name: workload-identity-credential-configuration
        configMap:
          name: CONFIGMAP_NAME
    

    É possível seguir a mesma abordagem para permitir que ferramentas e cargas de trabalho que usam uma das seguintes bibliotecas de cliente encontrem credenciais automaticamente:

    C++

    As bibliotecas de cliente do Google Cloud para C++ são compatíveis com a federação de identidade da carga de trabalho desde a versão v2.6.0. Para usar a federação de identidade da carga de trabalho, crie as bibliotecas de cliente com a versão 1.36.0 ou mais recente do gRPC.

    Go

    As bibliotecas de cliente do Go são compatíveis com a federação de identidade se usarem a versão v0.0.0-20210218202405-ba52d332ba99 ou posteriores do módulo golang.org/x/oauth2.

    Para verificar qual versão deste módulo sua biblioteca de cliente usa, execute os seguintes comandos:

    cd $GOPATH/src/cloud.google.com/go
    go list -m golang.org/x/oauth2
    

    Java

    As bibliotecas de cliente do Java aceitam federação de identidade se usarem a versão 0.24.0 ou posteriores do artefato com.google.auth:google-auth-library-oauth2-http.

    Para verificar qual versão desse artefato a biblioteca de cliente usa, execute o seguinte comando do Maven no diretório do aplicativo:

    mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http
    

    Node.js

    As bibliotecas de cliente do Node.js são compatíveis com a federação de identidade de carga de trabalho se usarem a versão 7.0.2 ou posteriores do pacote google-auth-library.

    Para verificar qual versão desse pacote sua biblioteca de cliente usa, execute o seguinte comando no diretório do seu aplicativo:

    npm list google-auth-library
    

    Ao criar um objeto GoogleAuth, é possível especificar um ID de projeto ou permitir que GoogleAuth encontre o ID do projeto automaticamente. Para encontrar o ID do projeto automaticamente, a conta de serviço no arquivo de configuração precisa ter o papel de navegador (roles/browser), ou um papel com permissões equivalentes no projeto. Para ver detalhes, consulte o README do pacote google-auth-library.

    Python

    As bibliotecas de cliente do Python são compatíveis com a federação de identidade se usarem a versão 1.27.0 ou posteriores do pacote google-auth.

    Para verificar qual versão desse pacote sua biblioteca de cliente usa, execute o seguinte comando no ambiente em que o pacote está instalado:

    pip show google-auth
    

    Para especificar um ID de projeto para o cliente de autenticação, defina a variável de ambiente GOOGLE_CLOUD_PROJECT ou permita que o cliente encontre o ID do projeto automaticamente. Para encontrar o ID do projeto automaticamente, a conta de serviço no arquivo de configuração precisa ter o papel de Navegador (roles/browser) ou um papel com permissões equivalentes no projeto. Para ver detalhes, consulte o guia do usuário do pacote google-auth.

    gcloud

    Para autenticar usando a federação de identidade da carga de trabalho, use o comando gcloud auth login:

    gcloud auth login --cred-file=FILEPATH.json
    

    Substitua FILEPATH pelo caminho do arquivo de configuração de credencial.

    O suporte para a federação de identidade de carga de trabalho na CLI gcloud está disponível na versão 363.0.0 e posteriores da CLI gcloud.

    Terraform

    O provedor do Google Cloud é compatível com a federação de identidade da carga de trabalho se você usar a versão 3.61.0 ou posterior:

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = "~> 3.61.0"
        }
      }
    }
    

    gsutil

    Para autenticar usando a federação de identidade da carga de trabalho, use um dos seguintes métodos:

    Quando você usar a gsutil com a gcloud, faça login normalmente:

    gcloud auth login --cred-file=FILEPATH.json
    

    Ao usar a gsutil como um aplicativo de linha de comando autônomo, edite o arquivo .boto para incluir a seguinte seção:

    [Credentials]
    gs_external_account_file = FILEPATH
    

    Substitua FILEPATH, em ambos os casos, pelo caminho do arquivo para a configuração da credencial.

    O suporte para a federação de identidade de carga de trabalho na gsutil está disponível na versão 379.0.0 e posteriores da CLI gcloud.

    bq

    Para autenticar usando a federação de identidade de carga de trabalho, use o comando gcloud auth login da seguinte maneira:

    gcloud auth login --cred-file=FILEPATH.json
    

    Substitua FILEPATH pelo caminho do arquivo de configuração de credencial.

    O suporte para a federação de identidade de carga de trabalho no bq está disponível na versão 390.0.0 e posteriores da CLI gcloud.

  4. Se quiser, verifique se a autenticação funciona corretamente executando o seguinte comando:

    kubectl exec example --namespace NAMESPACE -- gcloud auth print-access-token
    

A seguir