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 Cloud de Confiance by S3NS

Para autorizar cargas de trabalho da federação de identidade de carga de trabalho usando as bibliotecas de cliente doCloud de Confiance , 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 Cloud de Confiance .

  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 Cloud de Confiance , 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 doCloud de Confiance .

    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 doCloud de Confiance .

    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 Cloud de Confiance Security Token Service por meio de um handshake mTLS padrão.

  2. Chame os serviços do Cloud de Confiance 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