Configura el acceso basado en certificados para la federación de identidades para cargas de trabajo

En este documento, se describe cómo configurar el acceso basado en certificados para la federación de identidades para cargas de trabajo con certificados X.509.

El acceso basado en certificados usa TLS mutua (mTLS) para autenticar tanto al cliente como al servidor durante un protocolo de enlace TLS. En este proceso, una vinculación de mTLS incorpora políticas basadas en el contexto de transporte y usa el estado del certificado del cliente dentro de la sesión de TLS para tomar decisiones de autorización.

En el caso de la federación de identidades para cargas de trabajo X.509, una vinculación de mTLS garantiza que todo el flujo de autenticación esté vinculado de forma segura a una carga de trabajo de confianza. Esto mitiga el riesgo de robo de credenciales, ya que la autenticación está vinculada a un extremo específico y confiable.

Descripción general de la configuración del acceso basado en certificados para la federación de identidades para cargas de trabajo

A continuación, se proporciona una descripción general del proceso para configurar el acceso basado en certificados para la federación de Workload Identity:

  1. Establece una federación de identidades para cargas de trabajo configurando la confianza con la entidad de certificación de los certificados X.509.

  2. Crea un nivel de acceso para el acceso basado en certificados.

  3. Agrega el nivel de acceso a una política de acceso adaptado al contexto que aplique la vinculación de mTLS.

Antes de comenzar

Verifica que cumplas con los siguientes requisitos previos:

Crea un nivel de acceso para los certificados

  1. Crea un nivel de acceso de mTLS. El nivel de acceso de mTLS valida los certificados cuando determina el acceso a los recursos.

    Console

    En Access Context Manager, crea un nivel de acceso personalizado y, luego, ingresa la siguiente expresión en el campo de expresión CEL: request.auth.matchesMtlsTokens(origin) == true.

    gcloud

    Para crear un nivel de acceso personalizado, ejecuta el siguiente comando:

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

    Reemplaza lo siguiente:

    • ACCESS_LEVEL_NAME: Es el nombre del nivel de acceso.
    • TITLE: Es el título del nivel de acceso.
    • FILE: Es un archivo YAML con el siguiente contenido: request.auth.matchesMtlsTokens(origin) == true.
    • DESCRIPTION: Es una descripción del nivel de acceso.
    • POLICY_NAME: Es el nombre de la política de acceso.
  2. Exporta el nivel de acceso que creaste a una variable de entorno. Esta variable se usa en pasos posteriores.

      export ACCESS_LEVEL_ID=ACCESS_LEVEL_ID
      

    Reemplaza ACCESS_LEVEL_ID por el nombre del nivel de acceso, por ejemplo, accessPolicies/12345/accessLevels/acl_1.

Crea una vinculación de Access Context Manager para un grupo de identidades para cargas de trabajo

  1. Configura las siguientes variables de entorno:

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

    Reemplaza lo siguiente:

    • ORG_ID: el ID de tu organización.
    • CALLER_PROJECT_ID: Es el ID del proyecto que se usará para llamar a las APIs.
    • FEDERATED_PRINCIPAL: Es el nombre de la principal de identidad en el grupo de identidades para cargas de trabajo que cumple con la política de Context-Aware Access. Puedes usar una de las siguientes opciones:

      una sola identidad con el formato: principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE

      O

      Todas las identidades de un grupo con el formato: 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
    

    Reemplaza lo siguiente:

    • ACCESS_LEVEL_ID: Es el nombre del nivel de acceso.
    • DRY_RUN_ACCESS_LEVEL_ID: Es el nombre del nivel de acceso de la ejecución de prueba. Te recomendamos que primero habilites una vinculación de política de ejecución de prueba para comprender el posible impacto en el tráfico existente.

    curl

    1. Crea un archivo JSON con la vinculación de Access Context Manager.

      Solo puedes proporcionar un nivel de acceso en una solicitud, aunque el campo se repita. Puedes usar los siguientes tipos de principales federados:

      • Identidad única: principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE
      • Todas las identidades en un grupo: principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
      echo { \
        \"principal\": { \
          \"federatedPrincipal\": \"${FEDERATED_PRINCIPAL:?}\" \
        },\
        \"accessLevels\": [\"${ACCESS_LEVEL_ID:?}\"] \
      } \
      >> request.json
      
    2. Usa curl para enviar la siguiente solicitud 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"
      

Autoriza el uso de las Google Cloud bibliotecas cliente

Para autorizar cargas de trabajo de la federación de identidades de personal con las bibliotecas cliente deGoogle Cloud , completa los siguientes pasos.

  1. Crea un archivo de credenciales predeterminadas de la aplicación (ADC) configurado para la autenticación de la federación de identidades de personal.

    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
    

    Reemplaza lo siguiente:

    • IDENTITY_POOL_ID: Es el ID de tu grupo de identidades para cargas de trabajo.
    • WORKLOAD_CERTIFICATE_PATH: Es la ruta de acceso al archivo de certificado de tu carga de trabajo.
    • WORKLOAD_KEY_PATH: Es la ruta de acceso al archivo de clave privada de tu carga de trabajo.
    • ADC_FILE_OUTPUT_PATH: Es la ruta de acceso de salida del archivo ADC.

    Este comando también genera un archivo de configuración de certificado en el directorio de configuración predeterminado de gcloud CLI. El archivo de configuración del certificado admite la autenticación inicial y establece negociaciones de mTLS para las solicitudes posteriores a los recursos de Google Cloud .

  2. Establece una variable de entorno para que apunte al archivo de ADC. Esto hace que las bibliotecas cliente de Google puedan descubrir tus credenciales.

    export GOOGLE_APPLICATION_CREDENTIALS=${application_default_credentials.json}
    

    Este paso es opcional si omites el argumento --output-file cuando generas el archivo de ADC. Si omites el argumento, el archivo de ADC se crea y se lee desde el directorio de configuración predeterminado de gcloud CLI.

  3. Para establecer y probar el acceso a las APIs de Google Cloud , completa los siguientes pasos. Puedes usar Go o Python.

    Go

    1. Usa el siguiente ejemplo para crear un archivo 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))
      }
      

      Reemplaza PROJECT_ID por el ID de tu proyecto de gcloud CLI.

    2. Para ejecutar una prueba en una VM de Compute Engine, usa el siguiente comando.

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

    Python

    1. Usa el siguiente ejemplo para crear un archivo de prueba, 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()
      

      Reemplaza PROJECT_ID por el ID de tu proyecto de gcloud CLI.

    2. Para ejecutar una prueba en una VM de Compute Engine, completa los siguientes pasos.

      1. Configura un entorno virtual de Python.
      2. Instala las bibliotecas requeridas.

        pip install google-auth google-auth-httplib2 requests
        
      3. Ejecuta la prueba:

        python3 python_test.py
        

Autoriza con solicitudes HTTP sin formato

Para autorizar cargas de trabajo de la federación de identidades de personal con solicitudes HTTP simples, completa los siguientes pasos.

  1. Obtén un token de acceso vinculado a un certificado del servicio de tokens de seguridad a través de un protocolo de enlace de mTLS estándar. Google Cloud

  2. Llama a los servicios de Google Cloud con el token de acceso que obtuviste del servicio de tokens de seguridad. En este ejemplo, se consulta 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. La vinculación de mTLS aplica el uso de mTLS. Ejecuta el siguiente comando para verificar que una conexión que no es de mTLS falla con un error de no autorizado.

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

Enumera la vinculación de políticas

Para enumerar la vinculación de políticas para la federación de identidades para cargas de trabajo, ejecuta el siguiente comando.

gcloud

El siguiente comando enumera las vinculaciones específicas dentro de una organización determinada y filtra las que se aplican a los principales 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"

Actualiza una vinculación de política

Para actualizar una vinculación de política, agrega el nuevo nivel de acceso a un archivo JSON y ejecuta el siguiente 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"

Borra una vinculación de políticas

Para borrar una vinculación de política, ejecuta el siguiente 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:?}"

Soluciona problemas

A continuación, se indican algunos problemas habituales y las acciones sugeridas para resolverlos:

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

    Acción: Verifica la política de IAM para confirmar que el grupo de identidades de cargas de trabajo tenga acceso a tu recurso Google Cloud .

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

    Acción: El backend no pudo extraer un valor para google.subject de tu certificado de cliente según la asignación de atributos. Verifica tu certificado de cliente para comprobar que el campo que usas para la asignación tenga un valor.

  • Si encuentras denegaciones de acceso inesperadas después de habilitar el Acceso adaptado al contexto, puedes desbloquear rápidamente el tráfico quitando la vinculación del Acceso adaptado al contexto con el siguiente comando:

    gcloud alpha access-context-manager cloud-bindings delete
    

    Después de restablecer el acceso, revisa el registro de auditoría para determinar por qué se rechazaron las solicitudes.