Configure o acesso baseado em certificados para a federação de identidades da carga de trabalho

Este documento descreve como configurar o acesso baseado em certificados para a Workload Identity Federation através de certificados X.509.

O acesso baseado em certificados usa o TLS mútuo (mTLS) para autenticar o cliente e o servidor durante um handshake TLS. Neste processo, uma associação mTLS incorpora políticas baseadas no contexto de transporte e usa o estado do certificado do cliente na sessão TLS para tomar decisões de autorização.

Para a federação de identidade da carga de trabalho X.509, uma associação mTLS garante que todo o fluxo de autenticação está seguramente associado a uma carga de trabalho fidedigna. Isto mitiga o risco de roubo de credenciais, porque a autenticação está associada a um ponto final específico e fidedigno.

Acesso baseado em certificados para a configuração da federação de identidades da carga de trabalho: vista geral

Segue-se uma vista geral de nível superior do processo de configuração do acesso baseado em certificados para a federação de identidades de cargas de trabalho:

  1. Estabeleça uma federação de identidade da carga de trabalho configurando a confiança com a âncora de confiança dos certificados X.509.

  2. Crie um nível de acesso para acesso baseado em certificado.

  3. Adicione o nível de acesso a uma política de acesso sensível ao contexto que aplique a associação mTLS.

Antes de começar

Verifique se cumpre os seguintes pré-requisitos:

Crie um nível de acesso para certificados

  1. Crie um nível de acesso mTLS. O nível de acesso mTLS valida os certificados quando determina o acesso aos recursos.

    Consola

    No Gestor de contexto de acesso, crie um nível de acesso personalizado e introduza a seguinte expressão no campo de expressão do IEC: request.auth.matchesMtlsTokens(origin) == true.

    gcloud

    Para criar um nível de acesso personalizado, execute o seguinte comando:

       gcloud access-context-manager levels create ACCESS_LEVEL_NAME 
    --title=TITLE
    --custom-level-spec=FILE
    --description=DESCRIPTION
    --policy=POLICY_NAME

    Substitua o seguinte:

    • ACCESS_LEVEL_NAME: o nome do nível de acesso.
    • TITLE: o título do nível de acesso.
    • FILE: um ficheiro YAML com o seguinte conteúdo: request.auth.matchesMtlsTokens(origin) == true.
    • DESCRIPTION: uma descrição do nível de acesso.
    • POLICY_NAME: o nome da política de acesso.
  2. Exporte o nível de acesso que criou para uma variável de ambiente. Esta variável é usada nos passos seguintes.

      export ACCESS_LEVEL_ID=ACCESS_LEVEL_ID
      

    Substitua ACCESS_LEVEL_ID pelo nome do nível de acesso, por exemplo, accessPolicies/12345/accessLevels/acl_1.

Crie uma associação de acesso sensível ao contexto para um Workload Identity Pool

  1. Defina as seguintes variáveis de ambiente.

    export ORG_ID=ORG_ID
    export CALLER_PROJECT_ID=CALLER_PROJECT_ID
    export FEDERATED_PRINCIPAL=FEDERATED_PRINCIPAL
    

    Substitua o seguinte:

    • ORG_ID: o ID da sua organização.
    • CALLER_PROJECT_ID: o ID do projeto a usar para chamar as APIs.
    • FEDERATED_PRINCIPAL: o nome do principal de identidade no Workload Identity Pool que cumpre a política de acesso sensível ao contexto. Pode usar uma das seguintes opções:

      uma única identidade com o formatoprincipal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE

      OU

      todas as identidades num conjunto com o formatoprincipalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*

    gcloud

    gcloud alpha access-context-manager cloud-bindings create \
    --organization=ORG_ID \
    --federated-principal=FEDERATED_PRINCIPAL \
    --level=ACCESS_LEVEL_ID
    --dry-run-level=DRY_RUN_ACCESS_LEVEL_ID
    

    Substitua o seguinte:

    • ACCESS_LEVEL_ID: o nome do nível de acesso.
    • DRY_RUN_ACCESS_LEVEL_ID: o nome do nível de acesso da execução de ensaio. Recomendamos que ative primeiro uma associação de políticas de teste para compreender o potencial impacto no tráfego existente.

    curl

    1. Crie um ficheiro JSON com a associação do acesso sensível ao contexto.

      Só pode fornecer um nível de acesso num pedido, mesmo que o campo seja repetido. Pode usar os seguintes tipos de entidades federadas:

      • Identidade única: principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE
      • Todas as identidades num conjunto: principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
      echo { \
        \"principal\": { \
          \"federatedPrincipal\": \"${FEDERATED_PRINCIPAL:?}\" \
        },\
        \"accessLevels\": [\"${ACCESS_LEVEL_ID:?}\"] \
      } \
      >> request.json
      
    2. Use curl para enviar o seguinte pedido HTTP.

      curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X POST \
         -H "Authorization: Bearer $(gcloud auth print-access-token)" \
         -H "Content-Type: application/json; charset=utf-8" \
         -d @request.json \
       "https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings"
      

Autorize a utilização das Google Cloud bibliotecas de cliente

Para autorizar cargas de trabalho da Workforce Identity Federation através das Google Cloud bibliotecas de cliente, conclua os seguintes passos.

  1. Crie um ficheiro de credenciais padrão da aplicação (ADC) configurado para a autenticação da federação de identidade da força de trabalho.

    gcloud iam workload-identity-pools create-cred-config IDENTITY_POOL_ID \
    --credential-cert-path WORKLOAD_CERTIFICATE_PATH \
    --credential-cert-private-key-path WORKLOAD_KEY_PATH \
    --output-file ADC_FILE_OUTPUT_PATH
    

    Substitua o seguinte:

    • IDENTITY_POOL_ID: o ID do seu Workload Identity Pool.
    • WORKLOAD_CERTIFICATE_PATH: o caminho para o ficheiro de certificado da sua carga de trabalho.
    • WORKLOAD_KEY_PATH: o caminho para o ficheiro de chave privada da sua carga de trabalho.
    • ADC_FILE_OUTPUT_PATH: o caminho de saída do ficheiro ADC.

    Este comando também gera um ficheiro de configuração de certificado no diretório de configuração predefinido da CLI gcloud. O ficheiro de configuração do certificado suporta a autenticação inicial e estabelece negociações de mTLS para pedidos subsequentes a recursos Google Cloud .

  2. Defina uma variável de ambiente para apontar para o ficheiro ADC. Isto torna as suas credenciais detetáveis pelas bibliotecas cliente do Google.

    export GOOGLE_APPLICATION_CREDENTIALS=${application_default_credentials.json}
    

    Este passo é opcional se omitir o argumento --output-file quando gerar o ficheiro ADC. Se omitir o argumento, o ficheiro ADC é criado e lido a partir do diretório de configuração predefinido da CLI gcloud.

  3. Para estabelecer e testar o acesso às APIs Google Cloud , conclua os seguintes passos. Pode usar o Go ou o Python.

    Ir

    1. Use o exemplo seguinte para criar um ficheiro Go, como golang_test.go.

      package golang_test
      
      import (
           "io"
           "log"
           "testing"
      
           "cloud.google.com/go/auth/credentials"
           "cloud.google.com/go/auth/httptransport"
      )
      
      func TestGoExample(t *testing.T) {
      
           scopes := []string{
                   "https://www.googleapis.com/auth/pubsub", // Scope for Pub/Sub access
                   // Add other scopes as needed
           }
      
           dopts := credentials.DetectOptions{
                   Scopes: scopes,
           }
      
           // Create httptransport.Options with the scopes
           opts := &httptransport.Options{
                   DetectOpts: &dopts,
           }
           hc, err := httptransport.NewClient(opts)
           if err != nil {
                   t.Fatalf("NewHTTPClient: %v", err)
           }
      
           resp, err := hc.Get("https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics")
           if err != nil {
                   t.Fatalf("Get: %v", err)
           }
           t.Logf("Status: %s", resp.Status)
      
           t.Cleanup(func() {
                  resp.Body.Close()
           })
      
           b, err := io.ReadAll(resp.Body)
           if err != nil {
                  t.Fatal(err)
           }
           log.Println(string(b))
      }
      

      Substitua PROJECT_ID pelo ID do projeto da CLI gcloud.

    2. Para executar um teste numa VM do Compute Engine, use o seguinte comando.

    go mod init example.com
    go mod tidy
    go test -v golang_test.go --count=1
    

    Python

    1. Use o exemplo seguinte para criar um ficheiro de teste, como python_test.py.

      import google.auth
      import google.auth.transport.requests
      import requests
      
      def test_go_example():
      # Define the required scopes for your application
      scopes = [
         "https://www.googleapis.com/auth/pubsub",  # Scope for Pub/Sub access
         # Add other scopes as needed
      ]
      
      # Obtain Application Default Credentials (ADC) with the specified scopes
      credentials, _ = google.auth.default(scopes=scopes)
      
      # Create an authorized HTTP session using the ADC credentials
      authed_session = google.auth.transport.requests.AuthorizedSession(credentials)
      
      try:
      # Make a GET request to the Pub/Sub API endpoint
      response = authed_session.get(
          "https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics"
      )
      
      # Check if the request was successful
      response.raise_for_status()  # Raise an exception for error statuses
      
      # Log the response status and content
      print(f"Status: {response.status_code}")
      print(response.text)
      
      except requests.exceptions.RequestException as e:
      print(f"Error making the request: {e}")
      
      if __name__ == "__main__":
      test_go_example()
      

      Substitua PROJECT_ID pelo ID do projeto da CLI gcloud.

    2. Para executar um teste numa VM do Compute Engine, conclua os passos seguintes.

      1. Configure um ambiente virtual do Python.
      2. Instale as bibliotecas necessárias.

        pip install google-auth google-auth-httplib2 requests
        
      3. Execute o teste:

        python3 python_test.py
        

Autorize a utilização de pedidos HTTP simples

Para autorizar cargas de trabalho da Workforce Identity Federation através de pedidos HTTP simples, conclua os seguintes passos.

  1. Obtenha um token de acesso associado a um certificado do Google Cloud Security Token Service através de um handshake mTLS padrão.

  2. Chame os Google Cloud serviços com o token de acesso que obteve do serviço de token de segurança. Este exemplo consulta o Cloud Storage.

    $ curl --key ${workload_key.pem} --cert ${workload_cert.pem} -X GET 'https://storage.mtls.googleapis.com/{replace_with_your_resources}' -H "Authorization: Bearer $ACCESS_TOKEN"
    
  3. A associação mTLS impõe a utilização de mTLS. Execute o seguinte comando para verificar se uma ligação não mTLS falha com um erro não autorizado.

    $ curl -X GET 'https://storage.googleapis.com/{replace_with_your_resources}' -H "Authorization: Bearer $ACCESS_TOKEN"
    

Indique a associação de políticas

Para apresentar a associação de políticas para a federação de identidade da carga de trabalho, execute o seguinte comando.

gcloud

O comando seguinte lista associações específicas numa determinada organização, filtrando as que se aplicam a diretores federados.

gcloud alpha access-context-manager cloud-bindings list \
--organization=ORG_ID \
--filter='principal:federatedPrincipal'

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings?filter=principal%3Afederated_principal"

Atualize uma associação de políticas

Para atualizar uma associação de políticas, adicione o novo nível de acesso a um ficheiro JSON e execute o seguinte comando.

gcloud

gcloud alpha access-context-manager cloud-bindings update \
--binding=BINDING_ID \
--level=NEW_ACCESS_LEVEL_ID

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X PATCH \
 -H "Authorization: Bearer $(gcloud auth print-access-token)" \
 -H "Content-Type: application/json; charset=utf-8" \
 -d @request.json \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}?updateMask=access_levels"

Elimine uma vinculação de política

Para eliminar uma associação de políticas, execute o seguinte comando.

gcloud

gcloud alpha access-context-manager cloud-bindings delete \
--binding=BINDING_ID

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X DELETE \
   -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}"

Resolução de problemas

Seguem-se alguns problemas comuns e ações sugeridas para os resolver:

  • Erro: 403 Forbidden, user does not have permission.

    Ação: verifique a política de IAM para confirmar se o conjunto do Workload Identity tem acesso ao seu Google Cloud recurso.

  • Erro: Unauthorized_client: Could not obtain a value for google.subject from the given credential.

    Ação: o back-end não conseguiu extrair um valor para google.subject do seu certificado de cliente com base no mapeamento de atributos. Verifique o certificado do cliente para confirmar se o campo que usa para fazer o mapeamento tem um valor.

  • Se encontrar recusas de acesso inesperadas após ativar o acesso sensível ao contexto, pode desbloquear rapidamente o tráfego removendo a associação do acesso sensível ao contexto através do seguinte comando:

    gcloud alpha access-context-manager cloud-bindings delete
    

    Depois de o acesso ser restaurado, reveja o registo de auditoria para determinar o motivo pelo qual os pedidos foram recusados.