Configura la federación de identidades para carga de trabajo con Kubernetes

En esta guía, se describe cómo usar la federación de identidades para carga de trabajo para permitir que las cargas de trabajo que se ejecutan en Azure Kubernetes Service (AKS), Amazon Elastic Kubernetes Service o en un clúster de Kubernetes autoalojado se autentique en Google Cloud.

Kubernetes te permite configurar un clúster para que las cargas de trabajo puedan obtener tokens de cuenta de servicio de Kubernetes de un volumen proyectado. Cuando configuras la federación de identidades para carga de trabajo, puedes permitir que las cargas de trabajo usen estos tokens de cuenta de servicio de Kubernetes para autenticarse en Google Cloud.

Si usas GKE, usa Workload Identity en lugar de configurar la federación de identidades para carga de trabajo.

Antes de comenzar

Antes de configurar la federación de identidades para carga de trabajo, asegúrate de que tu clúster de Kubernetes cumpla con los siguientes criterios:

AKS

Asegúrate de que tu clúster cumpla con los siguientes requisitos:

  • Habilitaste la función entidad emisora de OIDC.

    Debes habilitar esta función para que la federación de identidades para carga de trabajo pueda acceder a los metadatos de OpenID Connect y el conjunto de claves web JSON (JWKS) para el clúster.

EKS

No es necesario que realices ningún cambio en la configuración de EKS.

Kubernetes

Asegúrate de que tu clúster cumpla con los siguientes requisitos:

  • Ejecutas Kubernetes 1.20 o una versión posterior.

    Las versiones anteriores de Kubernetes usaban un formato de token de cuenta de servicio diferente que no es compatible con las instrucciones de este documento.

  • Configuraste kube-apiserver para que admita proyecciones de volumen de token ServiceAccount .

No es necesario que se acceda al clúster a través de Internet.

Configura la federación de identidades para cargas de trabajo

Solo debes seguir estos pasos una vez para cada clúster de Kubernetes. Luego, puedes usar el mismo grupo y proveedor de identidades para cargas de trabajo para varios pods de Kubernetes y en varios proyectos de Google Cloud.

Para comenzar a configurar la federación de identidades para cargas de trabajo, haz lo siguiente:

  1. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  2. Te recomendamos que uses un proyecto dedicado para administrar grupos de identidades para cargas de trabajo y proveedores.
  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  4. Habilita las API de IAM, Resource Manager, Service Account Credentials, and Security Token Service.

    Habilita las API

Define una condición y la asignación de atributos

Los tokens de la cuenta de servicio de Kubernetes contienen varias reclamaciones, incluidas las que se detallan a continuación:

  • sub: Contiene el espacio de nombres y el nombre de la cuenta de servicio, por ejemplo, system:serviceaccount:NAMESPACE:KSA_NAME, en el que NAMESPACE es el espacio de nombres de la cuenta de servicio y KSA_NAME es el nombre de la cuenta de servicio.
  • "kubernetes.io".namespace: Contiene el espacio de nombres de la cuenta de servicio.
  • "kubernetes.io".serviceaccount.name: Contiene el nombre de la cuenta de servicio.
  • "kubernetes.io".pod.name: Contiene el nombre del Pod.

Para usar sub como identificador de asunto (google.subject) en Google Cloud, usa la siguiente asignación:

google.subject=assertion.sub

De manera opcional, puedes asignar atributos adicionales. Luego, puedes hacer referencia a estos atributos adicionales cuando otorgues acceso a los recursos. Por ejemplo:

google.subject=assertion.sub,
attribute.namespace=assertion['kubernetes.io']['namespace'],
attribute.service_account_name=assertion['kubernetes.io']['serviceaccount']['name'],
attribute.pod=assertion['kubernetes.io']['pod']['name']

De manera opcional, puedes definir una condición de atributo. Las condiciones de los atributos son expresiones CEL que pueden verificar los atributos de aserción y los atributos de destino. Si la condición del atributo se evalúa como true para una credencial determinada, se acepta la credencial. De lo contrario, se rechaza la credencial.

Puedes usar una condición de atributo para restringir qué cuentas de servicio de Kubernetes pueden usar la federación de identidades para cargas de trabajo para obtener tokens de Google Cloud de corta duración. Por ejemplo, la siguiente condición restringe el acceso a las cuentas de servicio de Kubernetes desde los espacios de nombres backend y monitoring:

assertion['kubernetes.io']['namespace'] in ['backend', 'monitoring']

Crea el proveedor y el grupo de identidades para cargas de trabajo

Roles obligatorios

Para obtener los permisos que necesitas para configurar la federación de identidades para cargas de trabajo, pídele a tu administrador que te otorgue los siguientes roles de IAM en el proyecto:

Si quieres obtener más información para otorgar roles, consulta Administra el acceso.

También puedes obtener los permisos necesarios a través de roles personalizados o cualquier otro rol predefinido.

De manera alternativa, el rol básico de propietario de IAM (roles/owner) también incluye permisos para configurar la federación de identidades. No deberías otorgar roles básicos en un entorno de producción, pero puedes otorgarlas en un entorno de prueba o desarrollo.

Para crear un proveedor y un grupo de identidades para cargas de trabajo, haz lo siguiente:

AKS

  1. Determina la URL de la entidad emisora de tu clúster de AKS:

    az aks show -n NAME -g RESOURCE_GROUP --query "oidcIssuerProfile.issuerUrl" -otsv
    

    Reemplaza lo siguiente:

    • NAME: el nombre del clúster
    • RESOURCE_GROUP: Es el grupo de recursos del clúster

    El comando genera la URL de la entidad emisora. Necesitas la URL de la entidad emisora en uno de los siguientes pasos.

    Si el comando no devuelve una URL de la entidad emisora, verifica que hayas habilitado la función entidad emisora de OIDC.

  2. Crea un nuevo grupo de identidades para cargas de trabajo:

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    Reemplaza lo siguiente:

    • POOL_ID: el ID único para el grupo.
    • DISPLAY_NAME: el nombre del grupo.
    • DESCRIPTION: una descripción del grupo que eliges. Esta descripción aparece cuando otorgas acceso a identidades de grupo.
  3. Agrega el clúster de AKS como proveedor de grupos de identidades para cargas de trabajo:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    Reemplaza lo siguiente:

    • PROVIDER_ID: Un ID de proveedor de grupos de identidades para cargas de trabajo único que elijas.
    • POOL_ID: El ID del grupo de identidades de cargas de trabajo que creaste antes.
    • ISSUER: El URI de la entidad emisora que determinaste antes.
    • MAPPINGS: Una lista separada por comas de las asignaciones de atributos que creaste antes en esta guía.
    • CONDITIONS: Es una condición de atributo opcional que creaste antes en esta guía. Quita el parámetro si no tienes una condición de atributo.

EKS

  1. Determina la URL de la entidad emisora de tu clúster de EKS:

    aws eks describe-cluster --name NAME --query "cluster.identity.oidc.issuer" --output text
    

    Reemplaza NAME por el nombre del clúster.

    El comando genera la URL de la entidad emisora. Necesitas la URL de la entidad emisora en uno de los siguientes pasos.

  2. Crea un nuevo grupo de identidades para cargas de trabajo:

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    Reemplaza lo siguiente:

    • POOL_ID: el ID único para el grupo.
    • DISPLAY_NAME: el nombre del grupo.
    • DESCRIPTION: una descripción del grupo que eliges. Esta descripción aparece cuando otorgas acceso a identidades de grupo.
  3. Agrega el clúster de EKS como proveedor de grupos de identidades para cargas de trabajo:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    Reemplaza lo siguiente:

    • PROVIDER_ID: Un ID de proveedor de grupos de identidades para cargas de trabajo único que elijas.
    • POOL_ID: El ID del grupo de identidades de cargas de trabajo que creaste antes.
    • ISSUER: El URI de la entidad emisora que determinaste antes.
    • MAPPINGS: Una lista separada por comas de las asignaciones de atributos que creaste antes en esta guía.
    • CONDITIONS: Es una condición de atributo opcional que creaste antes en esta guía. Quita el parámetro si no tienes una condición de atributo.

Kubernetes

  1. Conéctate a tu clúster de Kubernetes y usa kubectl para determinar la URL de la entidad emisora de tu clúster:

    kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
    

    Necesitas la URL de la entidad emisora en uno de los siguientes pasos.

  2. Descarga el conjunto de claves web JSON (JWKS) del clúster:

    kubectl get --raw /openid/v1/jwks > cluster-jwks.json
    

    En uno de los siguientes pasos, subes el JWKS para que la federación de identidades para cargas de trabajo pueda verificar la autenticidad de los tokens de la cuenta de servicio de Kubernetes que emite el clúster.

  3. Crea un nuevo grupo de identidades para cargas de trabajo:

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    Reemplaza lo siguiente:

    • POOL_ID: el ID único para el grupo.
    • DISPLAY_NAME: el nombre del grupo.
    • DESCRIPTION: una descripción del grupo que eliges. Esta descripción aparece cuando otorgas acceso a identidades de grupo.
  4. Agrega el clúster de Kubernetes como un proveedor de grupos de identidades para cargas de trabajo y sube los JWKS del clúster:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS" \
        --jwk-json-path="cluster-jwks.json"
    

    Reemplaza lo siguiente:

    • PROVIDER_ID: Un ID de proveedor de grupos de identidades para cargas de trabajo único que elijas.
    • POOL_ID: El ID del grupo de identidades de cargas de trabajo que creaste antes.
    • ISSUER: El URI de la entidad emisora que determinaste antes.
    • MAPPINGS: Una lista separada por comas de las asignaciones de atributos que creaste antes en esta guía.
    • CONDITIONS: Es una condición de atributo opcional que creaste antes en esta guía. Quita el parámetro si no tienes una condición de atributo.

Autentica una carga de trabajo de Kubernetes

En esta sección, se describe cómo configurar una carga de trabajo de Kubernetes para usar la federación de identidades para cargas de trabajo.

Debes seguir estos pasos una vez por cada carga de trabajo de Kubernetes que necesite acceso a Google Cloud.

Crea un par de cuentas de servicio

Para permitir que una carga de trabajo de Kubernetes se autentique en Google Cloud, necesitas un par de cuentas de servicio:

  • Una cuenta de servicio de Kubernetes que conectas al pod de Kubernetes.
  • Una cuenta de servicio de IAM a la que la carga de trabajo de Kubernetes puede suplantar a través de su cuenta de servicio de Kubernetes adjunta.

Para crear las cuentas de servicio, haz lo siguiente:

  1. Crea una cuenta de servicio de IAM que represente la carga de trabajo.

    No es necesario que la cuenta de servicio esté en el mismo proyecto que el grupo de identidades para cargas de trabajo.

    gcloud iam service-accounts create SA_NAME
    

    Reemplaza lo siguiente:

    • SA_NAME: el nombre de la cuenta de servicio.
  2. Crea una cuenta de servicio de Kubernetes:

    kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
    

    Reemplaza lo siguiente:

    • KSA_NAME: el nombre de la cuenta de servicio.
    • NAMESPACE: Es el espacio de nombres en el que se creará la cuenta de servicio.
  3. Otorga acceso a la cuenta de servicio de IAM a los recursos a los que deseas que acceda la carga de trabajo de Kubernetes.

  4. Otorga el rol de usuario de Workload Identity (roles/iam.workloadIdentityUser) a la identidad externa de la cuenta de servicio de Kubernetes:

    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/SUBJECT"
    

    Reemplaza lo siguiente:

    • SERVICE_ACCOUNT_EMAIL: La dirección de correo electrónico de la cuenta de servicio
    • PROJECT_NUMBER: Es el número del proyecto que contiene el grupo de identidades para cargas de trabajo.
    • POOL_ID: el ID del grupo de identidades para cargas de trabajo.
    • SUBJECT: Es el valor esperado para el atributo que asignaste a google.subject, por ejemplo, system:serviceaccount:NAMESPACE:KSA_NAME.

Implementa la carga de trabajo de Kubernetes

Ahora implementará una carga de trabajo de Kubernetes y le permitirá usar la vinculación de la cuenta de servicio:

  1. Crea un archivo de configuración de credenciales:

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --credential-source-file=/var/run/service-account/token \
        --credential-source-type=text \
        --output-file=credential-configuration.json
    

    Reemplaza lo siguiente:

    • PROJECT_NUMBER: Es el número del proyecto que contiene el grupo de identidades para cargas de trabajo
    • POOL_ID: El ID del grupo de identidades para cargas de trabajo
    • PROVIDER_ID: El ID del proveedor de grupos de identidades para cargas de trabajo
    • SERVICE_ACCOUNT_EMAIL: Dirección de correo electrónico de la cuenta de servicio

    El archivo de configuración de credenciales permite que las bibliotecas cliente de Cloud, gcloud CLI y Terraform determinen lo siguiente:

    • Dónde obtener credenciales externas
    • Qué grupo y proveedor de identidades para cargas de trabajo usar
    • Qué cuenta de servicio actuará en nombre de ella
  2. Importa el archivo de configuración de credenciales como un ConfigMap:

    kubectl create configmap CONFIGMAP_NAME \
      --from-file credential-configuration.json \
      --namespace NAMESPACE
    

    Reemplaza lo siguiente:

    • CONFIGMAP_NAME: El nombre del ConfigMap.
    • NAMESPACE: El espacio de nombres en el que se creará el ConfigMap.
  3. Implementar una carga de trabajo y dejar que use la cuenta de servicio de Kubernetes y ConfigMap.

    Crea un manifiesto y configúralo de la siguiente manera:

    • Activa un volumen de token proyectado para que la carga de trabajo pueda obtener un token de cuenta de servicio de Kubernetes desde un archivo local. Configura el volumen para que el token de la cuenta de servicio de Kubernetes use el público que espera el proveedor de grupos de federación de identidades para cargas de trabajo.
    • Activa el ConfigMap que contiene el archivo de configuración de credenciales para que la carga de trabajo pueda acceder a la configuración necesaria para usar la federación de identidades para cargas de trabajo.
    • Agrega una variable de entorno GOOGLE_APPLICATION_CREDENTIALS que contenga la ruta de acceso del archivo de configuración de credenciales para que las cargas de trabajo puedan encontrar el archivo.

    El siguiente es un manifiesto de ejemplo que usa la cuenta de servicio de Kubernetes y ConfigMap para permitir que Google Cloud CLI se autentique en Google Cloud:

    apiVersion: v1
    kind: Pod
    metadata:
      name: example
      namespace: NAMESPACE
    spec:
      containers:
      - name: example
        image: google/cloud-sdk:alpine
        command: ["/bin/sh", "-c", "gcloud auth login --cred-file $GOOGLE_APPLICATION_CREDENTIALS && gcloud auth list && sleep 600"]
        volumeMounts:
        - name: token
          mountPath: "/var/run/service-account"
          readOnly: true
        - name: workload-identity-credential-configuration
          mountPath: "/etc/workload-identity"
          readOnly: true
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: "/etc/workload-identity/credential-configuration.json"
    
      serviceAccountName: KSA_NAME
      volumes:
      - name: token
        projected:
          sources:
          - serviceAccountToken:
              audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
              expirationSeconds: 3600
              path: token
      - name: workload-identity-credential-configuration
        configMap:
          name: CONFIGMAP_NAME
    

    Puedes seguir el mismo enfoque para permitir que las herramientas y las cargas de trabajo que usan una de las siguientes bibliotecas cliente encuentren las credenciales automáticamente:

    C++

    Las bibliotecas cliente de Google Cloud para C++ admiten la federación de identidades para cargas de trabajo desde la versión v2.6.0. Para usar la federación de identidades para cargas de trabajo, debes compilar las bibliotecas cliente con la versión 1.36.0 o posterior de gRPC.

    Go

    Las bibliotecas cliente para Go admiten la federación de identidades si usan la versión v0.0.0-20210218202405-ba52d332ba99 o una versión posterior del módulo golang.org/x/oauth2.

    Para verificar qué versión de este módulo usa tu biblioteca cliente, ejecuta los siguientes comandos:

    cd $GOPATH/src/cloud.google.com/go
    go list -m golang.org/x/oauth2
    

    Java

    Las bibliotecas cliente para Java admiten la federación de identidades si usan la versión 0.24.0 o posterior del artefacto com.google.auth:google-auth-library-oauth2-http.

    Para verificar qué versión de este artefacto usa tu biblioteca cliente, ejecuta el siguiente comando de Maven en el directorio de tu aplicación:

    mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http
    

    Node.js

    Las bibliotecas cliente de Node.js admiten la federación de identidades para cargas de trabajo si usan la versión 7.0.2 o una versión posterior del paquete google-auth-library.

    Para verificar qué versión de este paquete usa tu biblioteca cliente, ejecuta el siguiente comando en el directorio de tu aplicación:

    npm list google-auth-library
    

    Cuando creas un objeto GoogleAuth, puedes especificar un ID del proyecto o puedes permitir que GoogleAuth encuentre el ID del proyecto automáticamente. Para encontrar el ID del proyecto de manera automática, la cuenta de servicio en el archivo de configuración debe tener el rol de Navegador (roles/browser) o un rol con permisos equivalentes en tu proyecto. Para obtener más información, consulta el README del paquete google-auth-library.

    Python

    Las bibliotecas cliente para Python admiten la federación de identidades si usan la versión 1.27.0 o posterior del paquete google-auth.

    Para verificar qué versión de este paquete usa tu biblioteca cliente, ejecuta el siguiente comando en el entorno en el que está instalado el paquete:

    pip show google-auth
    

    Si deseas especificar un ID del proyecto para el cliente de autenticación, puedes configurar la variable de entorno GOOGLE_CLOUD_PROJECT o permitir que el cliente busque el ID del proyecto automáticamente. Para encontrar el ID del proyecto de manera automática, la cuenta de servicio en el archivo de configuración debe tener el rol de Navegador (roles/browser) o un rol con permisos equivalentes en tu proyecto. Para obtener más información, consulta la guía del usuario del paquete google-auth.

    gcloud

    Para autenticar con la federación de identidades para cargas de trabajo, usa el comando gcloud auth login:

    gcloud auth login --cred-file=FILEPATH.json
    

    Reemplaza FILEPATH por la ruta de acceso al archivo de configuración de credenciales.

    La asistencia para la federación de identidades para cargas de trabajo en la CLI de gcloud está disponible en la versión 363.0.0 y posteriores de gcloud CLI.

    Terraform

    El proveedor de servicios en la nube admite la federación de identidades para cargas de trabajo si usas la versión 3.61.0 o una posterior:

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = "~> 3.61.0"
        }
      }
    }
    

    gsutil

    Para autenticar a través de la federación de identidades para cargas de trabajo, usa uno de los siguientes métodos:

    Cuando uses gsutil junto con gcloud, accede con normalidad:

    gcloud auth login --cred-file=FILEPATH.json
    

    Cuando uses gsutil como una aplicación de línea de comandos independiente, edita el archivo .boto para incluir la siguiente sección:

    [Credentials]
    gs_external_account_file = FILEPATH
    

    En ambos casos, reemplaza FILEPATH por la ruta de acceso al archivo de configuración de la credencial.

    La asistencia para la federación de identidades para cargas de trabajo en gsutil está disponible en la versión 379.0.0 y posteriores de gcloud CLI.

    bq

    Para autenticar a través de la federación de identidades para cargas de trabajo, usa el comando gcloud auth login de la siguiente manera:

    gcloud auth login --cred-file=FILEPATH.json
    

    Reemplaza FILEPATH por la ruta de acceso al archivo de configuración de credenciales.

    La compatibilidad con la federación de identidades para cargas de trabajo en bq está disponible en la versión 390.0.0 y posteriores de gcloud CLI.

  4. De manera opcional, ejecuta el siguiente comando para verificar que la autenticación funcione de forma correcta:

    kubectl exec example --namespace NAMESPACE -- gcloud auth print-access-token
    

Próximos pasos