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 sin estado alojados en contenedores.

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 completas este instructivo, puedes ver cómo la federación de identidades para cargas de trabajo te permite autenticar la aplicación de Jenkins con Google Cloud mediante 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 en Google Cloud puede beneficiarse de esta función.

La federación de identidades para cargas de trabajo te permite usar tu IdP para autenticarte directamente con Google Cloud. Para autenticar, 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 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 federado.
  6. La biblioteca envía el token a IAM.
  7. IAM intercambia el token por un token de OpenID Connect de una cuenta de servicio. Para obtener más información, consulta Genera tokens de ID de OpenID Connect.
  8. La biblioteca proporciona el token de OpenID Connect 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.

Objetivos

  • Configura Jenkins como la carga de trabajo externa.
  • Configura Keycloak como el proveedor de identidad compatible con OpenID Connect.
  • Conecta Jenkins con Keycloak.
  • Instala las bibliotecas cliente de Cloud para obtener el token JWT de Keycloak en Google Cloud.
  • Conecta Google Cloud a Keycloak y Jenkins
  • Obtén el JWT del usuario autenticado de Keycloak.

Aunque en este instructivo se usa Keycloak, puedes usar cualquier proveedor de identidad que admita OpenID Connect, como GitLab, Okta o OneLogin.

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

  1. In the Google Cloud console, go to the project selector page.

    Go to project selector

  2. Select or create a Google Cloud project.

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Configura un microservicio en Cloud Run. Para obtener más información, consulta la Guía de inicio rápido: Implementa un contenedor en Cloud Run.

Configura Jenkins

Completa estas tareas en un entorno que no sea de Google 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 Cómo instalar 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.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 puedas 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 adecuados 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 el 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 el 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 del administrador 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 que tengas 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 JSON de OIDC de Keycloak. 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 otro grupo de prueba. 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 información de una cuenta de usuario.

      Agregar usuario de Keycloak

    3. Haz clic en la pestaña Credentials 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 Credentials 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 antes.

    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 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 volver a obtener los datos JSON, completa lo siguiente:

    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.

    El siguiente es 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.

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

Instala 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 con Google Cloud mediante el SDK.

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

    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 que puedas 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 de Google Cloud que aloja tu contenedor sin servidor 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 que se le adjuntan. 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 por ti. Sin embargo, usar la cuenta de servicio predeterminada no es una práctica recomendada de seguridad porque la cuenta tiene un conjunto amplio 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 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 lo siguiente:

    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, establece 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'
    
    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 por 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 dentro de 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.

Realiza una limpieza

Puedes borrar tu proyecto para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo.

Borra el proyecto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

¿Qué sigue?