Como acessar recursos de um provedor de identidade OIDC

Este documento mostra como usar a federação de identidades para acessar recursos do Google Cloud a partir de um provedor de identidade compatível com o OpenID Connect (OIDC).

Os aplicativos executados fora do Google Cloud costumavam usar chaves de conta de serviço para acessar os recursos do Google Cloud. Com a federação de identidade, é possível permitir que uma identidade externa personifique uma conta de serviço. Isso possibilita que a carga de trabalho acesse os recursos do Google Cloud diretamente, usando um token de acesso de curta duração, e elimina a sobrecarga de manutenção e segurança associada às chaves de conta de serviço.

Antes de começar

  1. Ative as APIs IAM, Resource Manager, Service Account Credentials, and Security Token Service (STS).

    Ative as APIs

  2. Verifique se você tem o papel Administrador de pool de Identidade da carga de trabalho (roles/iam.workloadIdentityPoolAdmin).

    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.

  3. Atualize a política da sua organização para permitir federações do provedor de identidade.

  4. Crie uma conta de serviço do Google Cloud.

  5. Conceda à conta de serviço acesso para chamar as APIs do Google Cloud necessárias à carga de trabalho.

Como criar um pool de identidades de carga de trabalho

Use um pool de identidade de carga de trabalho para organizar e gerenciar identidades externas. Os pools de identidade de carga de trabalho são isolados uns dos outros, mas um único pool pode representar qualquer número de contas de serviço. Em geral, recomendamos a criação de um novo pool para cada um dos ambientes, como desenvolvimento, preparação ou produção.

Para criar um novo pool de identidades de carga de trabalho, você precisa fornecer um ID. Também é possível fornecer uma description e um nome de exibição opcionais.

gcloud

Execute o comando gcloud iam workload-identity-pools create para criar um pool de identidades da carga de trabalho:

gcloud iam workload-identity-pools create pool-id \
    --location="global" \
    --description="description" \
    --display-name="display-name"

A resposta é semelhante ao exemplo a seguir:

Created workload identity pool [pool-id].

REST

O método projects.locations.workloadIdentityPools.create cria um pool de identidades da carga de trabalho.

Método HTTP e URL:

POST https://iam.googleapis.com/v1beta/projects/project-id/locations/global/workloadIdentityPools?workloadIdentityPoolId=pool-id

Corpo JSON da solicitação:

{
  "description": "description",
  "display-name": "display-name"
}

Para enviar a solicitação, expanda uma destas opções:

O método retorna uma Operation de longa duração semelhante a esta:

{
  "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/operations/operation-id"
}

Como adicionar um provedor de identidade OIDC

Para configurar um provedor de identidade OIDC para seu pool de identidades de carga de trabalho, forneça pelo menos:

  • Um ID do provedor.

  • O ID do pool de identidades de carga de trabalho da seção anterior deste documento.

  • O URI do emissor do provedor. Ele normalmente tem o formato https://example.com. Consulte a documentação do seu provedor sobre a integração de OIDC para encontrar o URI.

  • Uma lista de mapeamentos de atributo que mapeiam as declarações em um token externo para os atributos em um token do Google. Use assertion para referenciar a credencial externa, google para atributos do Google e attribute para atributos personalizados.

    Há dois atributos do Google: google.subject e google.groups. É possível mencionar esses atributos nas vinculações de papéis do IAM. google.subject também aparece nas entradas de registro do Cloud Logging.

    É preciso fornecer um mapeamento para google.subject. Em geral, recomendamos mapeá-lo para assertion.sub, que precisa fornecer um identificador estável para uso em vinculações de papéis do IAM. O mapeamento é semelhante a este:

    google.subject=assertion.sub
    

    Para declarações mais complexas, use a Common Expression Language. Por exemplo, se o pool de identidades de carga de trabalho tiver vários provedores de identidade, será possível acrescentar um prefixo para diferenciá-los:

    google.subject="provider-a::" + assertion.sub
    

    O campo google.subject não pode exceder 127 caracteres.

    Também é possível especificar atributos personalizados. Por exemplo, o comando a seguir mapeia assertion.foo para attribute.bar:

    attribute.bar=assertion.foo
    

    Consulte a documentação do seu provedor sobre tokens de acesso para ver uma lista completa das declarações que você pode usar como referência.

    Para referir-se a uma parte específica de uma declaração em uma expressão, use a função extract() CEL, que extrai um valor de uma declaração com base em um modelo fornecido por você. Para saber mais sobre extract(), consulte Como extrair valores de atributos.

    Para verificar se uma credencial contém uma declaração, use a função has().

  • Uma lista de públicos permitidos especificando quais valores o campo aud da credencial externa pode conter. É possível configurar no máximo 10 públicos, cada um com até 256 caracteres. Consulte a documentação do provedor para mais informações sobre os valores padrão de aud.

    Como alternativa, caso seu provedor de identidade permita que você configure um valor personalizado para aud, deixe o parâmetro de público permitido em branco e defina o valor de aud como o nome de recurso completo do seu provedor de identidade de carga de trabalho. O prefixo HTTP é opcional. Por exemplo:

    //iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
    https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
    

    Em ambos os casos, todas as solicitações de troca de token que não contiverem um dos valores permitidos serão rejeitadas.

Também é possível especificar vários parâmetros opcionais:

  • Um nome de exibição e uma descrição

  • Uma condição que especifica aqueles que o principal precisa apresentar. A condição pode ser aplicada a declarações da credencial externa ou a atributos da credencial do Google. Qualquer solicitação que não atenda à condição será rejeitada.

    As condições são formatadas como uma expressão CEL que retorna um booleano. Por exemplo, o comando a seguir rejeita solicitações de qualquer identidade que não seja membro de um grupo específico:

    group in assertion.groups
    

    Se o provedor de identidade estiver disponível para o público em geral, é recomendável usar as condições. Para saber mais sobre casos de uso comuns de condições, consulte a visão geral dafederação de identidade da carga de trabalho.

No exemplo a seguir, veja como adicionar um provedor de identidade:

gcloud

Execute o comando gcloud iam workload-identity-pools providers create-oidc para adicionar um provedor de identidade:

gcloud iam workload-identity-pools providers create-oidc provider-id \
    --workload-identity-pool="pool-id" \
    --issuer-uri="issuer-uri" \
    --location="global" \
    --attribute-mapping="google.subject=assertion.sub"

A resposta é semelhante ao exemplo a seguir:

Created workload identity pool provider [provider-id].

REST

O método projects.locations.workloadIdentityPools.providers.create adiciona um provedor de identidade OIDC.

Método HTTP e URL:

POST https://iam.googleapis.com/v1beta/projects/project-id/locations/global/workloadIdentityPools/pool-id/providers?workloadIdentityPoolProviderId=provider-id

Corpo JSON da solicitação:

{
  "issuerUrl": "issuer-uri"
}

Para enviar a solicitação, expanda uma destas opções:

O método retorna uma Operation de longa duração semelhante a esta:

{
  "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id/operations/operation-id"
}

Como conceder permissão para representar uma conta de serviço

Identidades externas não podem acessar a maioria dos recursos do Google Cloud diretamente. Em vez disso, você permite que as identidades representem uma conta de serviço, concedendo a elas a função do usuário da Identidade de carga de trabalho (roles/iam.workloadIdentityUser).

Para adicionar essa vinculação de papel a uma identidade específica, use o valor mapeado para google.subject:

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"

Para adicionar essa vinculação a todos os membros de um grupo:

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role roles/iam.workloadIdentityUser \
    --member "principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/group/group-name"

Também é possível conceder acesso com base em atributos personalizados. Exemplo:

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/attribute.custom-attribute-name/custom-attribute-value"

Para revogar o acesso, substitua add-iam-policy-binding por remove-iam-policy-binding.

Também é possível adicionar ou revogar vinculações usando a API REST ou bibliotecas de cliente. Para saber mais, consulte Como conceder, alterar e revogar o acesso a recursos.

Como gerar credenciais do Google

Se você usa uma biblioteca de cliente compatível, pode configurá-la para que ela gere credenciais do Google automaticamente. Se preferir, gere um token de ID do OIDC manualmente e troque-o pelas credenciais do Google.

Quando possível, recomendamos que você gere credenciais automaticamente. Assim, não é necessário implementar o processo de troca de token por conta própria.

Como gerar credenciais automaticamente

Se você acessar o Google Cloud com uma biblioteca de cliente para um dos seguintes idiomas, será possível configurar a biblioteca de cliente para gerar credenciais automaticamente usando federação de identidade:

C++

A maioria das bibliotecas de cliente do Google Cloud para C++ é compatível com a federação de identidade usando um objeto ChannelCredentials, que é criado chamando grpc::GoogleDefaultCredentials(). Para inicializar essa credencial, crie as bibliotecas de cliente com a versão 1.36.0 ou posteriores do gRPC.

A biblioteca de cliente do Cloud Storage para C++ usa a API REST, não a gRPC. Portanto, ela não é compatível com a federação de identidade.

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 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.

A biblioteca de cliente pode receber tokens do provedor de identidade de algumas maneiras diferentes:

  • Credenciais originárias do arquivo: os tokens são carregados de um arquivo. Outro processo precisa atualizar esse arquivo com um novo token OIDC antes que o antigo expire. Por exemplo, se o token tiver um ciclo de vida de uma hora, você precisará atualizar o arquivo antes de ele completar 1 hora.
  • Credenciais fornecidas pelo URL: os tokens são carregados de um servidor local com um endpoint que responde a solicitações HTTP GET. A resposta precisa ser um token de ID do OIDC, em texto simples ou em formato JSON.

Para usar credenciais originadas de arquivos, execute o comando gcloud iam workload-identity-pools create-cred-config para gerar o arquivo de configuração. A sinalização --credential-source-type é opcional; a sinalização --credential-source-field-name é opcional, a menos que --credential-source-type seja json:

gcloud iam workload-identity-pools create-cred-config \
    projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id \
    --service-account=service-account-email \
    --output-file=configuration-filepath \
    --credential-source-file=token-filepath \
    --credential-source-type=source-type \
    --credential-source-field-name=field-name

Substitua os seguintes valores:

  • project-number: ID numérico do projeto.
  • pool-id: ID do pool de identidade da carga de trabalho.
  • provider-id: ID do provedor do pool de Identidade da carga de trabalho.
  • service-account-email: o endereço de e-mail da conta de serviço a ser personificada.
  • configuration-filepath: o caminho do arquivo de configuração.
  • token-filepath: o caminho do arquivo onde os tokens de ID do OIDC serão armazenados.
  • source-type: o formato do arquivo do token de ID do OIDC. Defina como text ou json. O padrão é text.
  • field-name: para arquivos de token JSON, o nome do campo JSON que contém o token. Obrigatório se --credential-source-type for json.

Para usar credenciais originadas de URL, você também precisa executar o comando gcloud iam workload-identity-pools create-cred-config para gerar o arquivo de configuração. As sinalizações --credential-source-headers e --credential-source-type são opcionais; a sinalização --credential-source-field-name é opcional, a menos que --credential-source-type seja json:

gcloud iam workload-identity-pools create-cred-config \
    projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id \
    --service-account=service-account-email \
    --output-file=configuration-filepath \
    --credential-source-url="token-url" \
    --credential-source-headers="key1=value1,key2=value2" \
    --credential-source-type=source-type \
    --credential-source-field-name=field-name

Substitua os seguintes valores:

  • project-number: ID numérico do projeto.
  • pool-id: ID do pool de identidade da carga de trabalho.
  • provider-id: ID do provedor do pool de Identidade da carga de trabalho.
  • service-account-email: o endereço de e-mail da conta de serviço a ser personificada.
  • configuration-filepath: o caminho do arquivo de configuração.
  • token-url: o URL que fornece tokens de ID do OIDC em resposta às solicitações HTTP GET.
  • key1, key2: o nome de um cabeçalho HTTP a ser incluído na solicitação.
  • value1, value2: o valor de um cabeçalho HTTP a ser incluído na solicitação.
  • source-type: o formato do arquivo de token do OIDC. Defina como text ou json. O padrão é text.
  • field-name: para arquivos de token JSON, o nome do campo que contém o token. Obrigatório se --credential-source-type for json.

Depois de gerar o arquivo de configuração, defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS como o caminho de arquivo do arquivo de configuração. Essa variável de ambiente instrui a biblioteca de cliente a usar o Application Default Credentials para autenticar. Para detalhes, consulte Como localizar credenciais automaticamente.

Como trocar credenciais manualmente

Depois que sua identidade externa conseguir personificar uma conta de serviço, troque as credenciais dela por credenciais do Google manualmente.

Para trocar credenciais:

  1. Consiga um token de ID do OIDC do seu provedor de identidade (consulte a documentação do seu provedor de identidade para ver instruções detalhadas).

  2. Envie o token de ID do OIDC para o método token() do Security Token Service a fim de receber um token de acesso federado:

    REST

    O método token troca um token de terceiros por um do Google.

    Antes de usar os dados da solicitação abaixo, faça as substituições a seguir:

    • project-number: o número do projeto do Google Cloud.
    • pool-id: o ID do pool de identidades da carga de trabalho que você já criou neste tutorial.
    • provider-id: o ID do provedor de identidade que você já configurou neste tutorial.

    Método HTTP e URL:

    POST https://sts.googleapis.com/v1beta/token

    Corpo JSON da solicitação:

    {
      "audience": "//iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id",
      "grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
      "requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
      "scope": "https://www.googleapis.com/auth/cloud-platform",
      "subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
      "subjectToken": "oidc-id-token"
    }
    

    Para enviar a solicitação, expanda uma destas opções:

     

    O método retorna um token federado.

  3. Chame generateAccessToken() para trocar o token federado por um token de acesso de conta de serviço. Um número limitado de APIs do Google Cloud é compatível com tokens federados. Todas as APIs do Google Cloud são compatíveis com tokens de acesso da conta de serviço.

    REST

    O método serviceAccounts.generateAccessToken da API Service Account Credentials gera um token de acesso do OAuth 2.0 para uma conta de serviço.

    Antes de usar os dados da solicitação abaixo, faça as substituições a seguir:

    • project-id: o ID do projeto do Google Cloud.
    • sa-id: o ID da sua conta de serviço. Pode ser o endereço de e-mail da conta de serviço no formato sa-name@project-id.iam.gserviceaccount.com ou o ID numérico exclusivo da conta de serviço.
    • token: o token de acesso federado.

    Método HTTP e URL:

    POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/sa-name@project-id.iam.gserviceaccount.com:generateAccessToken

    Corpo JSON da solicitação:

    {
      "scope": [
        "https://www.googleapis.com/auth/cloud-platform"
      ]
    }
    

    Para enviar a solicitação, expanda uma destas opções:

    Se a solicitação generateAccessToken for bem-sucedida, o corpo da resposta conterá um token de acesso do OAuth 2.0 e um prazo de validade. O accessToken poderá ser usado para autenticar uma solicitação em nome da conta de serviço até que o expireTime seja atingido.

    {
      "accessToken": "eyJ0eXAi...NiJ9",
      "expireTime": "2020-04-07T15:01:23.045123456Z"
    }
    

Quando você tiver um token de acesso para uma conta de serviço, poderá usá-lo para chamar as APIs do Google Cloud incluindo o token no cabeçalho Authorization das suas solicitações:

Authorization: Bearer service-account-access-token

A solicitação está autorizada como a conta de serviço.

A seguir