Como acessar recursos do Microsoft Azure

Neste documento, mostramos como usar a federação de identidades para acessar recursos do Google Cloud no Microsoft Azure.

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 gerenciada para um recurso do Azure personifique uma conta de serviço. Isso permite 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. Verifique se você tem o papel Administrador de pool de Identidade da carga de trabalho (roles/iam.workloadIdentityPoolAdmin).

    Como alternativa, os papéis básicos de Proprietário (roles/owner) e Editor (roles/editor) do IAM também incluem 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.

  2. Atualize a política da organização para sua organização para permitir a federação do Azure.

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

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

Um pool de identidade de carga de trabalho é um contêiner para uma coleção de 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. O ID não pode começar com gcp- porque esse prefixo está reservado para uso do Google.

gcloud

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

gcloud beta 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 o Azure como um provedor de identidade

Para configurar o Azure como provedor de identidade 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.

  • Seu ID do locatário do Azure.

  • Uma lista de mapeamentos de atributos que mapeiam as declarações em um token para uma identidade gerenciada pelo Azure para os atributos em um token do Google. Use assertion para se referenciar ao token do Azure, google para os 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 contém o ID de objeto de uma identidade gerenciada que você criará na próxima seção. Isso fornece 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="azure::" + assertion.tid + "::" + 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.tid para attribute.tid:

    attribute.tid=assertion.tid
    

    O exemplo a seguir atribui um nome de exibição baseado no valor de assertion.oid:

    attribute.managed_identity_name={
    "8bb39bdb-1cc5-4447-b7db-a19e920eb111":"workload1",
    "55d36609-9bcf-48e0-a366-a3cf19027d2a":"workload2"
    }[assertion.oid]
    

    Para receber uma lista completa das declarações que você pode referenciar, consiga um token de acesso para uma VM do Azure na sua carga de trabalho. Na solicitação, substitua o parâmetro resource pelo nome completo do recurso do pool de identidade da carga de trabalho.

    Exemplo:

    curl

    curl -s \
      'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id' \
      -H Metadata:true -H "Cache-Control: no-cache"
    

    PowerShell

    Invoke-WebRequest \
        -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id' \
        -Headers @{Metadata="true"}
    

    A resposta é um objeto JSON com um campo access_token, que contém um token de acesso para a VM do Azure. Para decodificar o token de acesso e ver as reivindicações disponíveis, siga estas etapas:

    1. Copie todo o token de acesso.
    2. Em um navegador da Web, acesse https://jwt.ms/.
    3. Cole o token de acesso na caixa de texto.
    4. Clique em Reivindicações.

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

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 do Azure 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:

    "e968c2ef-047c-498d-8d79-16ca1b61e77e" in assertion.groups
    

    Para saber mais sobre casos de uso comuns de condições, consulte a visão geral da federação de identidade da carga de trabalho.

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

gcloud

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

gcloud beta iam workload-identity-pools providers create-oidc provider-id \
    --workload-identity-pool="pool-id" \
    --issuer-uri="https://sts.windows.net/azure-tenant-id" \
    --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 o Azure como provedor.

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:

{
  "attributeMapping": {
    "google.subject": "assertion.sub"
  },
  "oidc": {
    "issuerUri": "https://sts.windows.net/azure-tenant-id"
  }
}

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 configurar o locatário do Azure para a federação de identidade

Para preparar o locatário do Azure para a federação de identidade:

  1. Crie um aplicativo do Azure AD e o principal de serviço e defina o URI do ID do aplicativo para o nome completo do recurso do provedor que você criou na seção anterior:

    https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
    
  2. Crie uma identidade gerenciada e anote o ID do objeto.

  3. Atribua a identidade gerenciada à máquina virtual em que você quer conceder acesso aos recursos do Google Cloud.

Como conceder permissão para personificar 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 a uma identidade gerenciada específica:

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/managed-identity-object-id"

Para adicionar essa vinculação em todas as identidades de um pool:

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/azure-tenant-id"

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 trocar um token do Azure por um token do Google

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

Para trocar credenciais:

  1. Use o Serviço de metadados de instância (IMDS) do Azure para conseguir um token de acesso do Azure. Defina o parâmetro de consulta resource para o seguinte valor:

    https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
    
  2. Transmita o token de acesso do Azure para o método token() do Security Token Service para 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": "azure-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