Configurar o acesso baseado em certificado para a federação de identidade da carga de trabalho

Neste documento, descrevemos como configurar o acesso baseado em certificado para a federação de identidade da carga de trabalho usando certificados X.509.

O acesso baseado em certificado usa o TLS mútuo (mTLS) para autenticar o cliente e o servidor durante um handshake de TLS. Nesse processo, uma vinculação mTLS incorpora políticas com base 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 vinculação mTLS garante que todo o fluxo de autenticação esteja vinculado com segurança a uma carga de trabalho confiável. Isso reduz o risco de roubo de credenciais, porque o sistema vincula a autenticação a um endpoint específico e confiável.

Visão geral da configuração do acesso baseado em certificado para a federação de identidade da carga de trabalho

Confira a seguir uma visão geral do processo de configuração do acesso baseado em certificado para a federação de identidade da carga de trabalho:

  1. Estabeleça a 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 o acesso baseado em certificado.

  3. Adicione o nível de acesso a uma política de acesso baseado no contexto que aplica a vinculação de mTLS.

Antes de começar

Verifique se você atende aos seguintes pré-requisitos:

Criar um nível de acesso para certificados

  1. Crie um nível de acesso mTLS. O nível de acesso mTLS valida certificados ao determinar o acesso aos recursos.

    Console

    No Access Context Manager, crie um nível de acesso personalizado e insira a seguinte expressão no campo Expressão CEL: 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:

    • ACCESS_LEVEL_NAME: o nome do nível de acesso.
    • TITLE: o título do nível de acesso.
    • FILE: um arquivo YAML com o seguinte conteúdo: expression: "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 você criou para uma variável de ambiente para uso nas etapas 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.

Criar uma vinculação de acesso baseado no contexto para um pool de Identidade da carga de trabalho

  1. Configure as variáveis de ambiente a seguir:

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

    Substitua:

    • ORG_ID: o ID da organização.
    • CALLER_PROJECT_ID: o ID do projeto a ser usado para chamar as APIs.
    • FEDERATED_PRINCIPAL: o nome do principal de identidade no pool de identidade da carga de trabalho que segue a política de acesso baseado no contexto. Você pode usar uma das seguintes opções:

      • Uma única identidade: principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE
      • Todas as identidades em um pool: principalSet://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:

    • ACCESS_LEVEL_ID: o nome do nível de acesso.
    • DRY_RUN_ACCESS_LEVEL_ID: o nome do nível de acesso de simulação. Recomendamos que você ative primeiro uma vinculação de política de simulação para entender o impacto potencial no tráfego atual.

    curl

    1. Crie um arquivo JSON com a vinculação do acesso baseado no contexto:

      É possível fornecer apenas um nível de acesso em uma solicitação, mesmo que o campo seja repetido. É possível usar os seguintes tipos de principais federados:

      • Identidade única: principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE
      • Todas as identidades em um pool: principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
      cat <<EOF > request.json
      {
        "principal": {
          "federatedPrincipal": "${FEDERATED_PRINCIPAL:?}"
        },
        "accessLevels": ["${ACCESS_LEVEL_ID:?}"]
      }
      EOF
      
    2. Use curl para enviar a seguinte solicitação 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"
      

Autorizar usando as bibliotecas de cliente do Google Cloud

Para autorizar cargas de trabalho da federação de identidade de carga de trabalho usando as bibliotecas de cliente doGoogle Cloud , siga estas etapas:

  1. Crie um arquivo do Application Default Credentials (ADC) configurado para autenticação da federação de identidade da carga 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:

    • IDENTITY_POOL_ID: o ID do pool de Identidade da carga de trabalho.
    • WORKLOAD_CERTIFICATE_PATH: o caminho para o arquivo de certificado da carga de trabalho.
    • WORKLOAD_KEY_PATH: o caminho para o arquivo de chave privada da carga de trabalho.
    • ADC_FILE_OUTPUT_PATH: o caminho de saída do arquivo ADC.

    Esse comando também gera um arquivo de configuração de certificado no diretório de configuração padrão da CLI gcloud. O arquivo de configuração de certificado é compatível com a autenticação inicial e estabelece handshakes mTLS para solicitações subsequentes a recursos do Google Cloud .

  2. Defina uma variável de ambiente para apontar para o arquivo do ADC e tornar suas credenciais detectáveis pelas bibliotecas de cliente do Google:

    export GOOGLE_APPLICATION_CREDENTIALS=ADC_FILE_OUTPUT_PATH
    

    Esta etapa é opcional se você omitir o argumento --output-file ao gerar o arquivo do ADC. Se você omitir o argumento, a CLI gcloud vai criar e ler o arquivo do ADC no diretório de configuração padrão da CLI gcloud.

  3. O recurso é compatível com as bibliotecas de cliente em Go, Python e Java. É necessário definir a variável de ambiente para ativar o mTLS para Python e Java.

  4. Para estabelecer e testar rapidamente o acesso mTLS às APIs da Google Cloud , use os seguintes exemplos de código:

    Go

    1. Use o exemplo a seguir para criar um arquivo 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 doGoogle Cloud .

    2. Para executar um teste em uma 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 a seguir para criar um arquivo de teste, como python_test.py:

      import google.auth
      import google.auth.transport.requests
      import requests
      
      def test_python_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_python_example()
      

      Substitua PROJECT_ID pelo ID do projeto doGoogle Cloud .

    2. Para executar um teste em uma VM do Compute Engine, siga estas etapas:

      1. Configurar um ambiente virtual de Python.
      2. Instale as bibliotecas necessárias:

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

        python3 python_test.py
        

Autorizar usando solicitações HTTP simples

Para autorizar cargas de trabalho da federação de identidade da carga de trabalho usando solicitações HTTP simples, siga estas etapas:

  1. Receba um token de acesso vinculado ao certificado do Google Cloud Security Token Service por meio de um handshake mTLS padrão.

  2. Chame os serviços do Google Cloud com o token de acesso que você recebeu do Security Token Service. Este exemplo consulta o Cloud Storage:

    curl --key WORKLOAD_KEY_PATH --cert WORKLOAD_CERTIFICATE_PATH \
     -X GET "https://storage.mtls.googleapis.com/RESOURCE_PATH" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
    
  3. A vinculação de mTLS impõe o uso de mTLS. Execute o seguinte comando para verificar se uma conexão não mTLS falha com um erro de não autorização:

    curl -X GET "https://storage.googleapis.com/RESOURCE_PATH" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
    

Listar a vinculação de política

Para listar a vinculação de política da federação de identidade da carga de trabalho, execute o seguinte comando:

gcloud

O comando a seguir lista vinculações específicas em uma determinada organização, filtrando aquelas que se aplicam a principais 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"

Atualizar uma vinculação de política

Para atualizar uma vinculação de política, siga estas etapas:

gcloud

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

curl

Adicione o novo nível de acesso ao arquivo request.json e execute o seguinte comando:

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"

Excluir uma vinculação de política

Para excluir uma vinculação de política, execute o seguinte comando:

gcloud

gcloud alpha access-context-manager cloud-bindings delete \
--binding=BINDING_ID \
--organization=ORG_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:?}"

A seguir