Autenticação em APIs do Google Cloud de cargas de trabalho de frota de confiança mista

Nesta página, mostramos como configurar seus aplicativos para autenticação nas APIs doGoogle Cloud , como a API Compute Engine ou a API AI Platform, em frotas que têm um modelo de confiança misto em toda a frota. Se a frota tiver um modelo de confiança compartilhada, consulte Autenticar em APIs Google Cloud de cargas de trabalho de frota de confiança compartilhada.

Esta página é destinada a administradores e operadores de plataforma e engenheiros de segurança que querem autenticar programaticamente cargas de trabalho da frota em APIs do Google Cloud. Para saber mais sobre as funções de usuário e as tarefas de exemplo referenciadas na documentação do Google Cloud, consulte Funções e tarefas comuns do usuário do GKE.

Antes de ler esta página, você deve conhecer os seguintes conceitos:

Sobre a federação de identidade da carga de trabalho da frota para ambientes de confiança mista

Com a federação de identidade da carga de trabalho da frota, é possível conceder papéis do IAM em APIs e recursos doGoogle Cloud a entidades na frota, como cargas de trabalho em um namespace específico. Por padrão, o projeto host da frota usa um pool de identidade da carga de trabalho gerenciado pelo Google para provisionar identidades para entidades em toda a frota. No entanto, em ambientes de confiança mista, como frotas multitenant ou em projetos host de frota que executam clusters autônomos, recomendamos que você configure um pool de identidade da carga de trabalho autogerenciado separado para um subconjunto de suas cargas de trabalho e clusters.

As entidades que usam um pool de identidades de carga de trabalho autogerenciado têm identificadores diferentes nas políticas do IAM do que as entidades que usam o pool de identidades de carga de trabalho gerenciado pelo Google do projeto host da frota. Isso garante que a concessão de acesso a principais em um namespace específico da frota não conceda acesso sem querer a outros principais que correspondam ao identificador.

Os pools de identidade de carga de trabalho autogerenciados exigem o uso de escopos de equipe. Com os escopos de equipe, é possível controlar o acesso a subconjuntos de recursos da frota por equipe. Você vincula escopos de equipe específicos a clusters de membros da frota específicos para permitir que essa equipe implante cargas de trabalho nesses clusters. Em um escopo da equipe, os membros só podem implantar cargas de trabalho em namespaces da frota.

Usar pools de identidade de carga de trabalho autogerenciados para fornecer identidades a cargas de trabalho no escopo da equipe tem benefícios como os seguintes:

  • Verifique se as concessões de acesso a entidades em namespaces da frota não se aplicam sem querer a entidades em outros namespaces ou clusters.
  • Configure um conjunto de clusters da frota para receber identidades do pool autogerenciado vinculando-os a um escopo de equipe e configurando o pool autogerenciado como um provedor de identidade nesses clusters.
  • Configure um subconjunto dos clusters vinculados de um escopo de equipe para receber identidades do pool autogerenciado. Para isso, configure o pool autogerenciado como um provedor de identidade em clusters específicos.

Exemplo de semelhança de identidade em um ambiente de confiança mista

Pense no seguinte cenário:

  • Você tem dois clusters membros da frota: frontend-cluster e finance-cluster.
  • Você não configurou um pool de identidade da carga de trabalho autogerenciado.
  • Você cria um escopo de equipe finance-team e um namespace de frota finance-ns no escopo da equipe.
  • Vincule o cluster finance-cluster ao escopo da equipe finance-team.
  • Você concede um papel do IAM à finance-sa ServiceAccount do Kubernetes no namespace finance-ns da frota.

As cargas de trabalho que atendem aos seguintes critérios compartilham a mesma identidade:

  • Executar no namespace da frota finance-ns.
  • Use a ServiceAccount finance-sa.

No entanto, se alguém no cluster frontend-cluster criar um namespace do Kubernetes finance-ns e uma ServiceAccount finance-sa, essa pessoa terá a mesma identidade das cargas de trabalho no cluster finance-cluster. Isso ocorre porque toda a frota usa o pool de identidades de carga de trabalho gerenciado pelo Google do projeto host da frota e porque o identificador principal não especifica um cluster host.

Considere as seguintes mudanças no cenário anterior:

  • Você configura um pool de identidades de carga de trabalho autogerenciado na sua frota.
  • Você configura o cluster finance-cluster para receber identidades do pool autogerenciado em vez do pool gerenciado pelo Google.
  • Você cria uma concessão de papel do IAM que especifica o pool autogerenciado no identificador principal em vez do pool gerenciado pelo Google.

As cargas de trabalho executadas no namespace da frota finance-ns em finance-cluster agora recebem uma identidade do pool autogerenciado. No entanto, as entidades no namespace finance-ns do Kubernetes no cluster frontend-cluster continuam recebendo identidades do pool de identidades de carga de trabalho gerenciado pelo Google do projeto host da frota.

Essas mudanças resultam nos seguintes benefícios:

  • É possível conceder papéis explicitamente a entidades no namespace da frota finance-ns.
  • As entidades no cluster frontend-cluster não podem ter o mesmo acesso porque as identidades no cluster frontend-cluster vêm do pool de identidades de carga de trabalho gerenciado pelo Google.

Antes de começar

  • Verifique se você tem as seguintes ferramentas de linha de comando instaladas:

    • A versão mais recente da Google Cloud CLI, que inclui gcloud, a ferramenta de linha de comando para interagir com Google Cloud.
    • kubectl

    Se você estiver usando o Cloud Shell como ambiente shell para interagir com Google Cloud, essas ferramentas estarão instaladas.

  • Verifique se você inicializou a CLI gcloud para usar com seu projeto.

Requisitos

Você precisa usar recursos de gerenciamento de equipes da frota, como escopos de equipe e namespaces da frota. As instruções nesta página mostram como configurar um exemplo de escopo de equipe e namespace da frota.

Prepare seus clusters

Antes que os aplicativos da sua frota recebam uma identidade federada, os clusters em que eles são executados precisam ser registrados para sua frota e configurados corretamente para usar a federação de identidade da carga de trabalho da frota. As seções a seguir descrevem como configurar a federação de identidade da carga de trabalho da frota para diferentes tipos de clusters.

GKE

Para clusters do GKE, faça o seguinte:

  1. Ative a federação de identidade da carga de trabalho do GKE no cluster do Google Kubernetes Engine, se ela ainda não estiver ativada.
  2. Registre o cluster na frota.

Também é possível ativar a federação de identidade da carga de trabalho para o GKE durante o processo de criação de cluster e registro de frota.

Clusters fora de Google Cloud

Os seguintes tipos de cluster ativam automaticamente a Federação de identidade da carga de trabalho da frota e são registrados na frota durante a criação do cluster:

  • Google Distributed Cloud (somente software) no VMware
  • Google Distributed Cloud (somente software) em bare metal
  • GKE na AWS
  • GKE no Azure

Clusters anexados

Os clusters anexados do EKS e do AKS registrados usando a GKE Multi-cloud são registrados com a federação de identidade da carga de trabalho da frota ativada por padrão. Os clusters anexados podem ser registrados com a federação de identidade da carga de trabalho da frota ativada se atenderem aos requisitos necessários. Siga as instruções para o tipo de cluster em Como registrar um cluster.

Configurar um pool de identidades da carga de trabalho do IAM

Nesta seção, você vai criar um pool de identidades de carga de trabalho do IAM no projeto host da frota e dar ao agente de serviço da frota acesso ao novo pool.

  1. Crie um pool de identidades da carga de trabalho:

    gcloud iam workload-identity-pools create POOL_NAME \
        --location=global \
        --project=POOL_HOST_PROJECT_ID \
        --mode=TRUST_DOMAIN
    

    Substitua:

    • POOL_NAME: o nome do novo pool de identidade da carga de trabalho.
    • POOL_HOST_PROJECT_ID: o ID do projeto em que você quer criar o pool de identidades da carga de trabalho autogerenciado. Você pode usar qualquer projeto Google Cloud , incluindo o projeto host da frota.
  2. Conceda o papel Administrador de pool de Identidade da carga de trabalho do IAM (roles/iam.workloadIdentityPoolAdmin) no novo pool de identidade da carga de trabalho ao agente de serviço da frota:

    gcloud iam workload-identity-pools add-iam-policy-binding POOL_NAME \
        --project=POOL_HOST_PROJECT_ID \
        --location=global \
        --member=serviceAccount:service-FLEET_HOST_PROJECT_NUMBER@gcp-sa-gkehub.iam.gserviceaccount.com \
        --role=roles/iam.workloadIdentityPoolAdmin \
        --condition=None
    

    Substitua FLEET_HOST_PROJECT_NUMBER pelo número do projeto host da frota.

Adicionar o pool autogerenciado à configuração da frota

Nesta seção, você vai ativar pools autogerenciados com a federação de identidade da carga de trabalho da frota e adicionar o pool criado à configuração da frota. Esta seção também fornece instruções para criar um escopo de equipe e um namespace de frota. Se a frota já tiver escopos de equipe e namespaces de frota configurados, pule essas etapas.

  1. Ative a federação de identidade da carga de trabalho da frota no nível da frota:

    gcloud beta container fleet workload-identity enable \
      --project=FLEET_HOST_PROJECT_ID
    

    Substitua FLEET_HOST_PROJECT_ID pelo ID do projeto host da frota.

  2. Adicione o pool de identidades de carga de trabalho autogerenciado à configuração da frota:

    gcloud beta container fleet workload-identity scope-tenancy-pool set POOL_NAME
    

    Substitua POOL_NAME pelo nome do pool de identidade da carga de trabalho autogerenciado. Esse valor tem a seguinte sintaxe:

    POOL_NAME.global.POOL_HOST_PROJECT_NUMBER.workload.id.goog
    
  3. Crie um escopo de equipe. Se você já tiver um escopo de equipe e um namespace da frota, pule para a seção Verificar a configuração do pool de identidade da carga de trabalho.

    gcloud container fleet scopes create SCOPE_NAME
    

    Substitua SCOPE_NAME pelo nome do novo escopo de equipe.

  4. Crie um namespace de frota no escopo da equipe:

    gcloud container fleet scopes namespaces create NAMESPACE_NAME \
        --scope=SCOPE_NAME
    

    Substitua NAMESPACE_NAME pelo nome do novo namespace da frota.

  5. Vincule um cluster na sua frota ao escopo da equipe:

    gcloud container fleet memberships bindings create BINDING_NAME \
        --membership=FLEET_CLUSTER_NAME \
        --location=global \
        --scope=SCOPE_NAME
    

    Substitua:

    • BINDING_NAME: o nome da nova vinculação de assinatura.
    • FLEET_CLUSTER_NAME: o nome do cluster da frota existente a ser vinculado ao escopo da equipe.

Verificar a configuração do pool de identidades de cargas de trabalho

Nesta seção, você vai garantir que a configuração do pool de identidade da carga de trabalho autogerenciada foi bem-sucedida.

  1. Descreva a configuração de assinatura da frota:

    gcloud container fleet memberships describe FLEET_CLUSTER_NAME \
        --location=global
    

    Substitua FLEET_CLUSTER_NAME pelo nome de um cluster de frota atual vinculado a qualquer escopo de equipe na sua frota.

    O resultado será assim:

    authority:
    ...
      scopeTenancyIdentityProvider: https://gkehub.googleapis.com/projects/FLEET_HOST_PROJECT_ID/locations/global/memberships/FLEET_CLUSTER_NAME
      scopeTenancyWorkloadIdentityPool: POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog
      workloadIdentityPool: FLEET_HOST_PROJECT_ID.svc.id.goog
    ...
    

    Essa saída precisa conter os seguintes campos:

    • scopeTenancyIdentityProvider: o provedor de identidade para cargas de trabalho que são executadas em namespaces da frota nos escopos da equipe. O valor é um identificador de recurso para seu cluster.
    • scopeTenancyWorkloadIdentityPool: o pool de identidade da carga de trabalho de que as cargas de trabalho em namespaces da frota nos escopos de equipe recebem identificadores. O valor é seu pool de identidade da carga de trabalho autogerenciado, com o formato POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog.
    • workloadIdentityPool: o nome do pool de identidade da carga de trabalho gerenciado pelo Google do projeto host da frota, de que todas as outras cargas de trabalho na frota recebem identidades por padrão.
  2. Opcional: verifique se o pool de identidade da carga de trabalho tem um namespace com o mesmo nome do namespace da frota:

    gcloud iam workload-identity-pools namespaces list \
        --workload-identity-pool=POOL_NAME \
        --location=global
    

    O resultado será assim:

    ---
    description: Fleet namespace NAMESPACE_NAME
    name: projects/FLEET_HOST_PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/namespaces/NAMESPACE_NAME
    state: ACTIVE
    

Agora, sua frota pode usar o pool de identidades de carga de trabalho autogerenciado para receber identidades para cargas de trabalho executadas em namespaces da frota. Para começar a usar o pool autogerenciado, configure como clusters específicos recebem identidades, conforme descrito na próxima seção.

Fazer com que as cargas de trabalho usem pools autogerenciados para identidades

Para que as cargas de trabalho usem o pool autogerenciado, configure namespaces específicos da frota em clusters membros da frota usando um ConfigMap do Kubernetes. Essa configuração por cluster e por namespace permite reduzir ainda mais o escopo das concessões de acesso de namespaces de frota inteiros para cargas de trabalho executadas em namespaces de frota específicos em clusters específicos.

  1. Conecte-se ao cluster membro da frota:

    gcloud container clusters get-credentials FLEET_CLUSTER_NAME \
        --project=CLUSTER_PROJECT_ID \
        --location=CLUSTER_LOCATION
    

    Substitua:

    • FLEET_CLUSTER_NAME: o nome de um cluster membro da frota que já está vinculado a um escopo de equipe.
    • CLUSTER_PROJECT_ID: o ID do projeto do cluster.
    • CLUSTER_LOCATION: O local do cluster.
  2. Receba o nome completo do pool de Identidade da carga de trabalho autogerenciado. Você vai precisar dele mais tarde.

    kubectl get membership membership -o json | jq -r ".spec.scope_tenancy_workload_identity_pool"
    

    O resultado será assim:

    POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog
    
  3. Receba o nome do provedor de identidade para escopos de equipe. Você precisará disso mais tarde.

    kubectl get membership membership -o json | jq -r ".spec.scope_tenancy_identity_provider"
    

    O resultado será assim:

    https://gkehub.googleapis.com/projects/FLEET_HOST_PROJECT_ID/locations/global/memberships/FLEET_CLUSTER_NAME
    
  4. Em um editor de texto, salve o seguinte manifesto YAML para um ConfigMap como self-managed-pool.yaml:

    kind: ConfigMap
    apiVersion: v1
    metadata:
      namespace: NAMESPACE_NAME
      name: google-application-credentials
    data:
      config: |
        {
          "type": "external_account",
          "audience": "identitynamespace:SELF_MANAGED_POOL_FULL_NAME:IDENTITY_PROVIDER",
          "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
          "token_url": "https://sts.googleapis.com/v1/token",
          "credential_source": {
            "file": "/var/run/secrets/tokens/gcp-ksa/token"
          }
        }
    

    Substitua:

    • NAMESPACE_NAME: o nome do namespace da frota.
    • SELF_MANAGED_POOL_FULL_NAME: o nome completo do pool de identidades da carga de trabalho autogerenciado da saída das etapas anteriores nesta seção. Por exemplo, example-pool.global.1234567890.workload.id.goog.
    • IDENTITY_PROVIDER: o nome do provedor de identidade da saída das etapas anteriores nesta seção. Por exemplo, https://gkehub.googleapis.com/projects/1234567890/locations/global/memberships/example-cluster.
  5. Implante o ConfigMap no cluster:

    kubectl create -f self-managed-pool.yaml
    

A implantação do ConfigMap indica ao GKE que as cargas de trabalho nesse namespace precisam usar o pool de identidade da carga de trabalho autogerenciado para receber identidades.

Conceder papéis do IAM aos principais

Nesta seção, você vai criar uma conta de serviço do Kubernetes em um namespace da frota e conceder uma função do IAM à conta de serviço. Os pods que usam essa ServiceAccount podem acessar os recursos Google Cloud em que você concede o papel.

  1. Crie uma conta de serviço do Kubernetes no namespace da frota:

    kubectl create serviceaccount SERVICEACCOUNT_NAME \
        --namespace=NAMESPACE_NAME
    

    Substitua:

    • SERVICEACCOUNT_NAME: o nome da nova ServiceAccount.
    • NAMESPACE_NAME: o nome do namespace da frota.
  2. Conceda um papel do IAM à ServiceAccount. O comando de exemplo a seguir concede o papel de Leitor de objetos do Storage (roles/storage.objectViewer) em um bucket à conta de serviço:

    gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
        --member=principal://iam.googleapis.com/projects/FLEET_HOST_PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog/subject/ns/NAMESPACE_NAME/sa/SERVICEACCOUNT_NAME \
        --role=roles/storage.objectViewer \
        --condition=None
    

A flag member contém o identificador principal da nova ServiceAccount que você criou. As solicitações que suas cargas de trabalho enviam para as APIs do Google Cloud usam um token de acesso federado. Esse token de acesso federado inclui o identificador principal da entidade que envia a solicitação. Se o principal em uma política de permissão que concede um papel no recurso de destino corresponder ao principal no token de acesso federado, a autenticação e a autorização poderão continuar.

Implantar cargas de trabalho que usam o pool autogerenciado

Os manifestos do Kubernetes aplicados no namespace da frota precisam ser configurados para receber identidades do pool autogerenciado. As cargas de trabalho implantadas que precisam chamar APIs Google Cloud devem incluir os seguintes campos:

  • metadata.namespace: o nome do namespace da frota.
  • spec.serviceAccountName: o nome da ServiceAccount do Kubernetes no namespace da frota.
  • spec.containers.env: uma variável de ambiente chamada GOOGLE_APPLICATION_CREDENTIALS que indica o caminho para o arquivo de credenciais padrão do aplicativo (ADC).
  • spec.containers.volumeMounts: um volume somente leitura que permite ao contêiner usar o token de autenticação para a ServiceAccount.
  • spec.volumes: um volume projetado que ativa um token ServiceAccount no pod. O público-alvo do token é o pool de identidade da carga de trabalho autogerenciado. O ConfigMap que contém a configuração da federação de identidade da carga de trabalho da frota é uma origem para o volume.

Para ver um exemplo de arquivo de manifesto configurado corretamente, consulte a seção Verificar a autenticação de uma carga de trabalho.

Verificar a autenticação de uma carga de trabalho

Esta seção oferece instruções opcionais para verificar se você configurou corretamente o pool de identidade da carga de trabalho autogerenciado listando o conteúdo de um exemplo de bucket do Cloud Storage. Você cria um bucket, concede uma função nele a uma conta de serviço em um namespace da frota e implanta um pod para tentar acessar o bucket.

  1. Crie um bucket do Cloud Storage:

    gcloud storage buckets create gs://FLEET_HOST_PROJECT_ID-workload-id-bucket \
        --location=LOCATION \
        --project=FLEET_HOST_PROJECT_ID
    
  2. Conceda o papel roles/storage.objectViewer no bucket à conta de serviço no namespace da frota:

    gcloud storage buckets add-iam-policy-binding gs://FLEET_HOST_PROJECT_ID-workload-id-bucket \
        --condition=None \
        --role=roles/storage.objectViewer \
        --member=principal://iam.googleapis.com/projects/FLEET_PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog/subject/ns/NAMESPACE_NAME/sa/SERVICEACCOUNT_NAME
    

    Substitua:

    • FLEET_HOST_PROJECT_NUMBER: o número do projeto host da frota.
    • POOL_NAME: o nome do pool de identidade da carga de trabalho autogerenciado.
    • NAMESPACE_NAME: o nome do namespace da frota em que você quer executar o pod.
    • SERVICEACCOUNT_NAME: o nome da ServiceAccount do Kubernetes que o pod deve usar.
  3. Salve o seguinte manifesto como pod-bucket-access.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: bucket-access-pod
      namespace:  NAMESPACE_NAME
    spec:
      serviceAccountName: SERVICEACCOUNT_NAME
      containers:
      - name: sample-container
        image: google/cloud-sdk:slim
        command: ["sleep","infinity"]
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/run/secrets/tokens/gcp-ksa/google-application-credentials.json
        volumeMounts:
        - name: gcp-ksa
          mountPath: /var/run/secrets/tokens/gcp-ksa
          readOnly: true
      volumes:
      - name: gcp-ksa
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              path: token
              audience: POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog
              expirationSeconds: 172800
          - configMap:
              name: my-cloudsdk-config
              optional: false
              items:
              - key: "config"
                path: "google-application-credentials.json"
    

    Substitua:

    • NAMESPACE_NAME: o nome do namespace da frota em que você quer executar o pod.
    • SERVICEACCOUNT_NAME: o nome da ServiceAccount do Kubernetes que o pod deve usar.
    • POOL_NAME: o nome do pool de identidade da carga de trabalho autogerenciado.
    • FLEET_HOST_PROJECT_NUMBER: o número do projeto host da frota.
  4. Implante o pod no cluster:

    kubectl apply -f pod-bucket-access.yaml
    
  5. Abra uma sessão do shell no pod:

    kubectl exec -it bucket-access-pod -n NAMESPACE_NAME -- /bin/bash
    
  6. Tente listar os objetos no bucket:

    curl -X GET -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        "https://storage.googleapis.com/storage/v1/b/FLEET_HOST_PROJECT_ID-workload-id-bucket/o"
    

    A saída é esta:

    {
      "kind": "storage#objects"
    }
    

Você pode verificar se um namespace e uma ServiceAccount semelhantes em um cluster de membro de frota diferente não poderão declarar a mesma identidade. Em um cluster que usa a federação de identidade da carga de trabalho da frota, mas não tem um namespace de frota ou uma configuração de pool autogerenciada, siga estas etapas:

  1. Crie um namespace do Kubernetes com o mesmo nome do namespace da frota em que você configurou o pool de identidades de carga de trabalho autogerenciado.
  2. Crie uma conta de serviço do Kubernetes com o mesmo nome da conta a que você concedeu um papel do IAM nas seções anteriores.
  3. Implante um pod que use a mesma ServiceAccount e o mesmo namespace, mas em que o campo spec.volumes.projected.sources.serviceAccountToken especifique o pool de identidades da carga de trabalho gerenciado pelo Google. Esse pool tem a seguinte sintaxe:

    FLEET_HOST_PROJECT_ID.svc.id.goog
    
  4. Tente acessar o bucket do Cloud Storage em uma sessão de shell no Pod.

A saída precisa ser um erro 401: Unauthorized, porque o identificador principal do pod que usa o pool de identidades de carga de trabalho gerenciado pelo Google é diferente do identificador principal do pod que usa o pool autogerenciado.

A seguir