Integra Cloud Run y la federación de identidades para cargas de trabajo

En este instructivo, se describe cómo usar la federación de identidades para cargas de trabajo para autenticar las cargas de trabajo que se ejecutan fuera de Google Cloud a fin de que puedan acceder a los microservicios que aloja Cloud Run. Este instructivo está dirigido a los administradores que desean integrar la federación de identidades para cargas de trabajo con su proveedor de identidad existente (IdP). La federación de identidades para cargas de trabajo te permite conectar cargas de trabajo externas a cargas de trabajo que se ejecutan en Google Cloud. Cloud Run te permite ejecutar microservicios en contenedores sin estado.

En este instructivo, se proporcionan instrucciones para configurar Jenkins como la carga de trabajo externa, Keycloak como IdP, Cloud Run y la federación de identidades para cargas de trabajo. Cuando completes este instructivo, podrás ver cómo la federación de identidades para cargas de trabajo te permite autenticar tu aplicación de Jenkins con Google Cloud a través de la autenticación de OpenID Connect.

Autenticación externa de cargas de trabajo mediante la federación de identidades para cargas de trabajo

La federación de identidades para cargas de trabajo te permite autenticar cargas de trabajo fuera de Google Cloud sin usar una clave de cuenta de servicio estática. Cualquier carga de trabajo externa que necesite consumir servicios enGoogle Cloud puede beneficiarse de esta función.

La federación de identidades para cargas de trabajo te permite usar tu IdP para autenticarte directamente conGoogle Cloud. Para autenticarte, usa OpenID Connect. Cloud Run acepta tokens de OpenID Connect de tu IdP para la autenticación.

El proceso de autenticación cuando se usa la federación de identidades para cargas de trabajo es el siguiente:

  1. Tu biblioteca de autenticación (AUTHN) envía una solicitud de token web JSON (JWT) al IdP.
  2. Tu IdP firma los tokens web JSON (JWT). La biblioteca de AUTHN lee estos datos de una variable.
  3. La biblioteca envía un comando POST al Servicio de tokens de seguridad que incluye el token firmado.
  4. El servicio de tokens de seguridad analiza el proveedor de grupos de Workload Identity que configuraste para compilar la relación de confianza y verifica la identidad en la credencial.
  5. El servicio de tokens de seguridad devuelve un token de acceso federado.
  6. La biblioteca envía el token de acceso federado a IAM.
  7. IAM intercambia el token de acceso federado por un token de ID. Para obtener más información, consulta Crea un token de ID de OpenID Connect (OIDC).
  8. La biblioteca proporciona el token de ID a Jenkins.
  9. Jenkins usa este token para autenticarse con Cloud Run.

En el siguiente diagrama, se muestra el flujo de autenticación:

Flujo de autenticación.

Configura Jenkins

Completa estas tareas en un entorno que no sea deGoogle Cloud , como tu entorno local o en otra nube.

Si ya tienes un proveedor de identidad que admite OpenID Connect y una carga de trabajo externa, puedes omitir este paso y pasar a Instalar las bibliotecas cliente de Cloud.

Para simular una carga de trabajo externa, puedes usar una VM con Jenkins instalado. Puedes ejecutar Jenkins como una imagen de Docker o instalarlo directamente en tu servidor. En los siguientes pasos, se demuestra cómo instalarlo directamente en el servidor.

  1. En la VM que elijas, abre una línea de comandos.
  2. Instala Java:

    $ sudo apt update
    $ sudo apt install openjdk-11-jre
    $ java -version
    
  3. Instala Jenkins:

    curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
    /usr/share/keyrings/jenkins-keyring.asc > /dev/null
    echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
    https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
    /etc/apt/sources.list.d/jenkins.list > /dev/null
    sudo apt-get update
    sudo apt-get install jenkins
    
  4. Verifica que puedes acceder a tu servidor de Jenkins en el puerto 8080. Si usas una VM que se encuentra detrás de un firewall, asegúrate de que los puertos correspondientes estén abiertos.

  5. Obtén tu contraseña de administrador y configura Jenkins. Para obtener instrucciones, consulta el Asistente de configuración posterior a la instalación.

  6. Completa las siguientes acciones para configurar SSL:

    1. Si tienes un proveedor de dominio, puedes usar su autoridad certificadora (CA) para solicitar un certificado firmado. Como alternativa, puedes obtener un certificado firmado gratis que dura 90 días desde zerossl.com.
    2. Descarga el archivo .zip del certificado y transfiérelo al servidor que ejecuta Jenkins:

      scp -i CERTFILE.pem -r CERTFILE.zip VM_FQDN:/home/USERNAME
      

      Reemplaza lo siguiente:

      • CERTFILE por el nombre del archivo de certificado que incluye tu clave pública.
      • VM_FQDN con el FQDN de tu servidor fuera de Google Cloud.
      • USERNAME por tu nombre de usuario
    3. Cambia el nombre de los archivos y genera un archivo .pkcs12 que Jenkins pueda usar:

      openssl rsa -in KEYFILE.com.key -out KEYFILE.com.key

      Reemplaza KEYFILE por el nombre del archivo.

  7. Actualiza el archivo /etc/sysconfig/jenkins:

    1. Abre el archivo en un editor de texto:

      vi /etc/sysconfig/jenkins
      
    2. Establece JENKINS_PORT en -1.

    3. Establece JENKINS_HTTPS_PORT en 8443.

    4. En la parte inferior del archivo, agrega los siguientes argumentos:

      JENKINS_ARGS="--httpsCertificate=/var/lib/jenkins/.ssl/CERTFILE.crt --httpsPrivateKeys=/var/lib/jenkins/.ssl/KEYFILE.pkcs1.key"

      Reemplaza lo siguiente:

      • CERTFILE por el nombre del archivo de certificado con formato .crt
      • KEYFILE por el nombre de archivo de la clave PKCS.
  8. Reinicia el servidor de Jenkins.

  9. Verifica que el puerto 8443 esté abierto en tu firewall y accede a Jenkins en el puerto 8443.

  10. Instala el complemento de Jenkins que necesitas para integrar Keycloak en Jenkins. Puedes elegir una de las siguientes opciones:

    Para instalar el complemento, haz lo siguiente:

    1. En el panel de Jenkins, ve a Administrar Jenkins > Administrar complementos.
    2. Selecciona Disponible y busca el complemento que prefieras. En la siguiente captura de pantalla, se muestra el Administrador de complementos con la pestaña Disponible.

      Administrador de complementos de Jenkins.

    3. Instala el complemento.

Configura Keycloak

En este instructivo, Keycloak administra los usuarios, grupos y roles. Keycloak usa dominios para administrar usuarios.

  1. En la VM que se ejecuta fuera de Google Cloud, instala el servidor de Keycloak. Para este instructivo, recomendamos instalar Keycloak desde un contenedor de Docker.

  2. Abre la consola de administración de Keycloak.

  3. Ve a Configuración de dominios.

  4. En la pestaña General, verifica que los campos estén configurados de la siguiente manera:

    • Habilitada: ACTIVADO
    • Acceso administrado por el usuario: DESACTIVADO
    • Extremos: Configuración de extremos de OpenID y Metadatos del proveedor de identidad de SAML 2.0

    La siguiente captura de pantalla muestra los campos que debes configurar.

    Configuración general de Keycloak.

  5. Crea un cliente para tener una entidad que pueda solicitar a Keycloak que autentique a un usuario. A menudo, los clientes son aplicaciones y servicios que usan Keycloak para proporcionar una solución de inicio de sesión único (SSO).

    1. En la Consola del administrador de Keycloak, haz clic en Clientes > Crear.
    2. Ingresa el siguiente comando:

      • ID de cliente: jenkins
      • Protocolo de cliente: openid-connect
      • URL raíz: http://JENKINS_IP_ADDRESS:8080, donde JENKINS_IP_ADDRESS es la dirección IP de tu servidor de Jenkins.

      La siguiente captura de pantalla muestra los campos que debes configurar.

      Agregar cliente de Keycloak.

    3. Haz clic en Guardar.

  6. En la pestaña Instalación, verifica que el formato del token sea Keycloak OIDC JSON. Haz una copia de este token, ya que lo necesitarás para completar la configuración de Jenkins.

  7. Para crear un grupo, haz lo siguiente:

    1. En la Consola del administrador de Keycloak, haz clic en Grupos > Nuevo.
    2. Ingresa un nombre para el grupo y haz clic en Guardar.
    3. Crea un grupo de prueba más. Puedes asignar roles a tus grupos, pero este instructivo no las requiere.
  8. Para crear un usuario de prueba y agregarlo al grupo, haz lo siguiente:

    1. En la Consola del administrador de Keycloak, haz clic en Administrar usuario > Agregar usuarios.
    2. Completa la información del usuario y haz clic en Guardar.

      En la siguiente captura de pantalla, se muestra un ejemplo de la información de una cuenta de usuario.

      Agrega un usuario a Keycloak.

    3. Haz clic en la pestaña Credenciales y verifica que Temporal esté configurado como Desactivado.

    4. Restablece la contraseña.

      Usarás esta cuenta más adelante en el JWT para la autenticación.

      En la siguiente captura de pantalla, se muestra la pestaña Credenciales con los campos que debes configurar.

      Cambiar la contraseña de Keycloak.

    5. Haz clic en la pestaña Grupos y selecciona uno de los grupos que creaste anteriormente.

    6. Haz clic en Unirse.

    7. Repite este paso para crear más usuarios de prueba.

Configura Jenkins para la configuración de OpenID Connect

En esta sección, se describe cómo configurar el complemento de OpenID Connect para Jenkins.

  1. En tu servidor de Jenkins, ve a Administrar Jenkins > Configurar seguridad global.
  2. En Dominio de seguridad, selecciona Complemento de autenticación de Keycloak. Haz clic en Guardar.

  3. Haz clic en Configurar sistema.

  4. En la configuración de Keycloak global, copia el archivo JSON de instalación de Keycloak que creaste en Configura Keycloak. Si necesitas obtener los datos JSON nuevamente, completa los siguientes pasos:

    1. En la Consola del administrador de Keycloak, ve a Clientes.

    2. Haga clic en el nombre de tu cliente.

    3. En la pestaña Instalación, haz clic en Opción de formato y selecciona JSON de OIDC de Keycloak.

    A continuación, se muestra un ejemplo de JSON de Keycloak:

    {
        "realm":"master"
        "auth-server-url":"AUTHSERVERURL"
        "ssl-required":"none"
        "resource":"jenkins"
        "public-client":true
        "confidential-port":0
    }
    

    AUTHSERVERURL es la URL de tu servidor de autenticación.

  5. Para guardar la configuración de OIDC, haz clic en Guardar.

Ahora Jenkins puede redireccionar a Keycloak para obtener información del usuario.

Instala las bibliotecas cliente de Cloud

Para enviar un JWT de Keycloak a Google Cloud, debes instalar las bibliotecas cliente de Cloud en el servidor de Jenkins. En este instructivo, se usa Python para interactuar conGoogle Cloud a través del SDK.

  1. En el servidor de Jenkins, instala Python. En los siguientes pasos, se muestra cómo instalar Python 3:

    sudo apt update
    sudo apt install software-properties-common
    sudo add-apt-repository ppa:deadsnakes/ppa
    sudo apt update
    sudo apt install python3.8
    
  2. Instala pip3 para poder descargar e importar las bibliotecas cliente de Cloud:

    pip3 –version
    sudo apt update
    sudo apt install python3-pip
    pip3 –version
    
  3. Instala las bibliotecas cliente de Cloud para Python con pip3:

    pip3 install –upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
    

    Por ejemplo:

    pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
    Collecting google-api-python-client
        Downloading google_api_python_client-2.42.0-py2.py3-none-any.whl (8.3 MB)
            USERNAME | 8.3 MB 19.9 MB/s
    Collecting google-auth-httplib2
        Downloading google_auth_httplib2-0.1.0-py2.py3-none-any.whl (9.3 MB)
    Collecting google-auth-oauthlib
    Downloading google_auth_oauthlib-0.5.1-py2.py3-non-any.whl (19 KB)
    

    Reemplaza USERNAME por tu nombre de usuario.

  4. Instala Google Cloud CLI en tu servidor de Jenkins. Para obtener instrucciones, consulta la Guía de inicio rápido: Instala gcloud CLI.

Configura tu entorno de Google Cloud

En esta sección, se describen los pasos que debes completar para asegurarte de que tu entorno deGoogle Cloud que aloja tu contenedor sin servidores pueda conectarse con Jenkins y Keycloak.

  1. En Google Cloud, crea una cuenta de servicio para que el microservicio en Cloud Run pueda acceder a los permisos adjuntos a ella. Por ejemplo, para crear una cuenta de servicio con gcloud CLI, haz lo siguiente:

    gcloud iam service-accounts create cloudrun-oidc \
      –-description="cloud run oidc sa"  \
      –-display-name="cloudrun-oidc"
    

    De forma predeterminada, Cloud Run crea una cuenta de servicio predeterminada para ti. Sin embargo, usar la cuenta de servicio predeterminada no es una práctica recomendada de seguridad, ya que la cuenta tiene un amplio conjunto de permisos. Por lo tanto, te recomendamos que crees una cuenta de servicio independiente para tu microservicio. Para obtener instrucciones sobre cómo crear una cuenta de servicio para Cloud Run, consulta Crea y administra cuentas de servicio.

  2. Crea un grupo de Workload Identity. Para crear un grupo con gcloud CLI, ejecuta lo siguiente:

    gcloud iam workload-identity-pools create cloudrun-oidc-pool \
      --location="global" \
      —-description="cloudrun-oidc" \
      —-display-name="cloudrun-oidc"
    
  3. Crea un proveedor de grupos de federación de Workload Identity para OpenID Connect:

    gcloud iam workload-identity-pools providers create-oidc cloud-run-provider \
      --workload-identity-pool="cloudrun-oidc-pool" \
      --issuer-uri="VAR_LINK_TO_ENDPOINT" \
      --location="global" \
      --attribute-mapping ="google.subject=assertion.sub,attribute.isadmin-assertion.isadmin,attribute.aud=assertion.aud" \
      --attribute-condition="attribute.isadmin=='true'"
    

    Reemplaza VAR_LINK_TO_ENDPOINT por una variable que contenga el vínculo al extremo de OIDC de Keycloak. Para encontrar este vínculo, en la ventana Dominio de la Consola del administrador de KeyCloud, haz clic en la pestaña General. El extremo debe ser HTTPS, lo que significa que debes configurar tu servidor de Keycloak con HTTPS.

Obtén el JWT del usuario autenticado de Keycloak

  1. En la VM que ejecuta Keycloak, descarga el token en un archivo de texto. Por ejemplo, en Linux, ejecuta el siguiente comando:

    curl -L -X POST 'https://IP_FOR_KEYCLOAK:8080/auth/realms/master/protocol/openid-connect/token' -H 'Content-Type: application/x-www-form-urlencoded' \
      --data-urlencode 'client_id=jenks' \
      --data-urlencode 'grant_type=password' \
      --data-urlencode 'client_secret=CLIENT_SECRET \
      --data-urlencode 'scope=openid' \
      --data-urlencode 'username=USERNAME' \
      --data-urlencode 'password=PASSWORD' | grep access_token | cut -c18-1490 > token.txt
    

    Reemplaza lo siguiente:

    • IP_FOR_KEYCLOAK por la dirección IP del servidor de Keycloak.
    • CLIENT_SECRET por el secreto del cliente de Keycloak.
    • USERNAME con un usuario de Keycloak.
    • PASSWORD por la contraseña del usuario de Keycloak.

    Este comando incluye el ID de cliente, el secreto del cliente, el nombre de usuario y la contraseña. Como práctica recomendada de seguridad, te recomendamos que uses variables de entorno para enmascarar estos valores en lugar de usar la línea de comandos. El comando de ejemplo redirecciona las credenciales a un archivo llamado token.txt.

    De manera opcional, para automatizar este paso, puedes crear una secuencia de comandos de Bash.

  2. Valida tu token en jwt.io.

  3. En la VM, crea tu archivo de credenciales:

    gcloud iam workload-identity-pools create-cred-config \
    projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/providers/cloud-run/provider \
      --output-file=sts-creds.json \
      --credential-source-file=token.txt
    

    Para obtener más información, consulta gcloud iam workload-identity-pools create-cred-config.

    Tu archivo de salida debería verse de la siguiente manera:

    {
        "type": "external_account",
        "audience": "//iam.google.apis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/subject/USER_EMAIL",
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
        "token_url": "https://sts.googleapis.com/v1/token",
        "credential_source": {
            "file" "token.txt" }
    }
    

    PROJECT_NUMBER es tu número de proyecto.

  4. En la VM, configura el archivo sts.creds.json como una variable para ADC:

    export GOOGLE_APPLICATION_CREDENTIALS=/Users/USERNAME/sts-creds.json
    

    Reemplaza USERNAME por tu nombre de usuario de UNIX.

    Antes de que se lanzara la federación de identidades para cargas de trabajo, este valor era la clave de la cuenta de servicio. Con la federación de identidades para cargas de trabajo, este valor es el archivo de credenciales recién creado.

  5. Crea una vinculación de rol para que el usuario actúe en nombre de la cuenta de servicio:

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT \
        --role roles/iam.workloadIdentityUser \
        --member "principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/subject/USER_EMAIL
    

    Reemplaza lo siguiente:

  6. Permite que la cuenta de servicio acceda al servicio de Cloud Run:

    gcloud run services add-iam-policy-binding SERVICE_NAME
      --member-"serviceAccount:SERVICE_ACCOUNT" \
      --role="roles/run.invoker"
    

    Reemplaza lo siguiente:

    • SERVICE_NAME por el nombre del microservicio que se ejecuta en Cloud Run

    • SERVICE_ACCOUNT con la dirección de correo electrónico de la cuenta de servicio de Cloud Run.

    Para obtener más información, consulta gcloud run services add-iam-policy-binding.

  7. Genera un token de ID:

    #!/usr/bin/python
    from google.auth import credentials
    from google.cloud import iam_credentials_v1
    
    import google.auth
    import google.oauth2.credentials
    
    from google.auth.transport.requests import AuthorizedSession, Request
    
    url = "https://WORKLOAD_FQDN"
    aud = "https://WORKLOAD_FQDN"
    service_account = 'SERVICE_ACCOUNT'
    
    client = iam_credentials_v1.IAMCredentialsClient()
    
    name = "projects/-/serviceAccounts/{}".format(service_account)
    id_token = client.generate_id_token(name=name,audience=aud, include_email=True)
    
    print(id_token.token)
    
    creds = google.oauth2.credentials.Credentials(id_token.token)
    authed_session = AuthorizedSession(creds)
    r = authed_session.get(url)
    print(r.status_code)
    print(r.text)
    

    Reemplaza lo siguiente:

    • WORKLOAD_FQDN con el FQDN de tu carga de trabajo.

    • SERVICE_ACCOUNT con la dirección de correo electrónico de la cuenta de servicio de Cloud Run.

El token que uses puede llamar a la API de Identity and Access Management, lo que te dará el JWT nuevo que necesitas para invocar tu servicio de Cloud Run.

Puedes usar tu token en una canalización de Jenkins para invocar el contenedor sin servidores que ejecutas en Cloud Run. Sin embargo, estos pasos están fuera del alcance de este instructivo.