Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Acceso seguro a servicios de Google Cloud desde GitLab Pipelines con Workload Identity Federation

By Chimbu ChinnaduraiSep 1, 20236 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

Secure-access-to-GCP-services-in-GitLab-Pipelines-with-Workload-Identity-Federation-DoiT-International

Tradicionalmente, al consumir servicios como Google Cloud desde un entorno externo a GCP (por ejemplo, un entorno de CI/CD como los pipelines de GitLab), los desarrolladores tenían que usar claves de cuenta de servicio u otras credenciales de larga duración para autenticarse con los servicios de Google Cloud. Sin embargo, este enfoque conlleva varios riesgos de seguridad:

  • Exposición de credenciales de larga duración: las claves de cuenta de servicio son credenciales de larga duración, normalmente válidas hasta que se revocan o rotan manualmente. Almacenarlas en repositorios de código fuente, archivos de configuración o entornos de CI/CD aumenta el riesgo de acceso no autorizado si esos repositorios o entornos se ven comprometidos.
  • Escalación de privilegios: las claves de cuenta de servicio suelen tener permisos amplios, pensados para ejecutar diversas tareas dentro de Google Cloud. Si un atacante consigue una de estas claves, puede acceder a una gran cantidad de recursos, mucho más allá de lo que requiere una aplicación o un workload específico.
  • Gestión de credenciales: rotar las claves de cuenta de servicio con regularidad es una buena práctica de seguridad fundamental. Sin embargo, la rotación manual es engorrosa y propensa a errores, lo que puede derivar en brechas de seguridad.
  • Auditoría y trazabilidad limitadas: con las claves de cuenta de servicio resulta difícil atribuir acciones específicas a usuarios o servicios concretos. Esa falta de granularidad complica las tareas de auditoría y dificulta rastrear las acciones hasta su origen.

GCP Workload Identity Federation resuelve estas preocupaciones de seguridad y te permite usar tu proveedor de identidad (IdP) actual para autenticarte en Google Cloud Platform (GCP). Resulta muy útil en los pipelines de GitLab, ya que puedes usar tus credenciales de GitLab para autenticarte en GCP sin tener que gestionar cuentas de servicio o credenciales aparte.

Componentes clave de GCP Workload Identity Federation:

  • Proveedor de identidad (IdP): el IdP es el sistema que autentica a los usuarios y les emite credenciales. GCP es compatible con distintos proveedores de identidad como Active Directory Federation Services (ADFS), Okta, Azure Active Directory o cualquier proveedor que admita OpenID Connect (OIDC) o SAML 2.0.
  • Workload identity pool: una entidad que te permite gestionar identidades externas. Recomendamos crear un pool nuevo para cada entorno externo a Google Cloud que necesite acceder a recursos de Google Cloud.
  • Cuenta de servicio: en GCP, las cuentas de servicio se utilizan para representar workloads. Para acceder a los recursos, las identidades del pool deben tener acceso a una cuenta de servicio. Una vez añadidas, esas identidades podrán acceder a cualquier servicio de Google Cloud al que tenga acceso la cuenta de servicio.
  • Token federado: es un token emitido por el IdP que se intercambia por un token de cuenta de servicio. El token federado permite que el workload se autentique en GCP como si fuera la cuenta de servicio.

En este artículo veremos cómo configurar Workload Identity Federation en GCP y acceder de forma segura a los servicios de GCP usando tokens de corta duración en los pipelines de GitLab.

Requisitos previos

  • Asegúrate de contar con los roles Workload Identity Pool Admin (roles/iam.workloadIdentityPoolAdmin) y Service Account Admin (roles/iam.serviceAccountAdmin) en el proyecto.
  • Habilita las siguientes APIs.
#Update $GCP_PROJECT_ID value
gcloud services enable cloudresourcemanager.googleapis.com \
iam.googleapis.com \
iamcredentials.googleapis.com \
sts.googleapis.com \
--project $GCP_PROJECT_ID
  • Una cuenta de GitLab. Si no la tienes, crea una cuenta nueva.

Configurar Workload Identity Federation

  • Paso 1: crea un Workload Identity Pool.
#Update $GCP_PROJECT_ID value
gcloud iam workload-identity-pools create gitlab-demo-wip \
--location="global" \
--description="Gitlab demo workload Identity pool" \
--display-name="gitlab-demo-wip"
--project=$GCP_PROJECT_ID

gitlab-ci-cd

workload identity pool

gitlab

configuración del workload identity pool

  • Paso 2: añade un proveedor de workload identity pool para GitLab y usa Attribute conditions para restringir qué identidades pueden autenticarse a través del workload identity pool.
  • La configuración del attribute mapping es una pieza clave al configurar Workload Identity Federation. Te permite mapear atributos de las credenciales de autenticación emitidas por un proveedor de identidad externo hacia atributos de Google Cloud, como subject e email. Algunos proveedores de identidad llaman a estos atributos "claims".
  • Cada proveedor de identidad externo expone atributos distintos. Para AWS, Google ofrece mapeos predeterminados que cubren la mayoría de los escenarios habituales. También puedes definir mapeos personalizados.
  • Para proveedores OIDC como GitLab, los mapeos los defines tú. Para construirlos, consulta la documentación del proveedor con la lista de atributos disponibles en sus credenciales. En el caso de GitLab, revisa el payload del ID Token para ver los claims que incluye cada ID token.

La attribute condition que aparece a continuación restringe las identidades exclusivamente a mi namespace personal de GitLab. Consulta GitLab Namespace para saber si estás viendo un namespace de grupo o personal.

#Update GITLAB_NAMESPACE_PATH value
gcloud iam workload-identity-pools providers create-oidc gitlab-identity-provider --location="global" \
--workload-identity-pool="gitlab-demo-wip" \
--issuer-uri="https://gitlab.com" \
--allowed-audiences=https://gitlab.com \
--attribute-mapping="google.subject=assertion.sub,attribute.aud=assertion.aud,attribute.project_path=assertion.project_path,attribute.project_id=assertion.project_id,attribute.namespace_id=assertion.namespace_id,attribute.namespace_path=assertion.namespace_path,attribute.user_email=assertion.user_email,attribute.ref=assertion.ref,attribute.ref_type=assertion.ref_type" \
--attribute-condition="assertion.namespace_path.startsWith(\"$GITLAB_NAMESPACE_PATH\")" \
--project=$GCP_PROJECT_ID

ci

resultado de ejemplo del comando gcloud

pipeline

proveedor de GitLab añadido al workload identity pool

gitlab

configuración del proveedor de identidad de GitLab

  • Llegado este punto ya puedes autenticarte desde un job de GitLab CI/CD en Google Cloud. Sin embargo, todavía no tienes permisos en Google Cloud (autorización).
  • Paso 3: crea una cuenta de servicio que la identidad externa de GitLab pueda suplantar.
#Create a service account
gcloud iam service-accounts create gitlab-wif-demo --project=$GCP_PROJECT_ID
#Add sample permissions to the Service account
gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
--member=serviceAccount:gitlab-wif-demo@${GCP_PROJECT_ID}.iam.gserviceaccount.com \
--role=roles/storage.admin
  • Paso 4: otorga a la identidad externa de GitLab los permisos para suplantar la cuenta de servicio. Así, un job de GitLab CI/CD podrá autorizarse en Google Cloud mediante la suplantación de cuenta de servicio. Este paso concede el permiso de IAM sobre la propia cuenta de servicio y le da a la identidad externa la autoridad para actuar como esa cuenta.

El siguiente comando permite que todas las identidades del pool accedan a recursos de GCP mediante la suplantación de cuenta de servicio, pero recomendamos restringir la suplantación a identidades externas concretas según sus atributos.

Consulta https://cloud.google.com/iam/docs/workload-identity-federation#impersonation para ver escenarios habituales de asignación de roles.

PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value core/project) --format=value\(projectNumber\) --project $GCP_PROJECT_ID)
gcloud iam service-accounts add-iam-policy-binding gitlab-wif-demo@${GCP_PROJECT_ID}.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="principalSet://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/gitlab-demo-wip/*"

gitlab

cuenta de servicio conectada al workload identity pool

Probar la configuración de Workload Identity Federation en un GitLab Pipeline

En los pasos anteriores configuramos el workload identity pool para que confíe en las identidades de mi namespace personal de GitLab. No hace falta cambiar nada en tu cuenta de GitLab y puedes habilitar Workload Identity Federation por cada job de CI/CD. Personaliza la configuración según lo que necesites.

  • Paso 5: crea un proyecto vacío en GitLab o usa uno existente.

gitlab

repositorio de GitLab

  • Paso 6: crea un archivo llamado .gitlab-ci.yml y configura un pipeline de GitLab con la siguiente plantilla. Consulta los pipelines de CI/CD para conocer más sobre los pipelines de GitLab.
#Update the $GCP_PROJECT_NAME and $GCP_PROJECT_NUMBER values
variables:
GCP_PROJECT_NAME: $GCP_PROJECT_NAME
GCP_WORKLOAD_IDENTITY_PROVIDER: "projects/$GCP_PROJECT_NUMBER/locations/global/workloadIdentityPools/gitlab-demo-wip/providers/gitlab-identity-provider"
SERVICE_ACCOUNT_EMAIL: "gitlab-wif-demo@$GCP_PROJECT_NAME.iam.gserviceaccount.com"
stages:
- gcp_wif_demo
.gcp_wif_auth: &gcp_wif_auth
#id_tokens to create JSON web tokens (JWT) to authenticate with third party services.This replaces the CI_JOB_JWT_V2
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.com
before_script:
- apt-get update && apt-get install -yq jq
#Get temporary credentials using the ID token
- |
PAYLOAD=$(cat <<EOF
{
"audience": "//iam.googleapis.com/${GCP_WORKLOAD_IDENTITY_PROVIDER}",
"grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
"requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
"subjectToken": "${GITLAB_OIDC_TOKEN}"
}
EOF
)
- |
FEDERATED_TOKEN=$(curl -s -X POST "https://sts.googleapis.com/v1/token" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "${PAYLOAD}" \
| jq -r '.access_token'
)
#Use the federated token to impersonate the service account linked to workload identity pool
#The resulting access token is stored in CLOUDSDK_AUTH_ACCESS_TOKEN environment variable and this will be passed to the gcloud CLI
- |
export CLOUDSDK_AUTH_ACCESS_TOKEN=$(curl -s -X POST "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${SERVICE_ACCOUNT_EMAIL}:generateAccessToken" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${FEDERATED_TOKEN}" \
--data '{"scope": ["https://www.googleapis.com/auth/cloud-platform"]}' \
| jq -r '.accessToken'
)
gcloud_test:
<<: *gcp_wif_auth
stage: gcp_wif_demo
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:441.0.0
script:
- gcloud config set project ${GCP_PROJECT_NAME}
- gcloud storage ls

workload

.gitlab-ci.yml

  • POR DEFECTO, los pipelines de GitLab CI/CD se ejecutan automáticamente al subir nuevos commits. Revisa la salida del pipeline en Build -> Pipelines.

gcp

estado de ejecución del pipeline de GitLab

workload

log de ejemplo del job de GitLab

Los logs del job confirman que la autenticación y la autorización funcionaron como se esperaba con el token de corta duración generado a través de Workload Identity Federation.

En definitiva, Workload Identity Federation es un servicio muy útil para proteger tus pipelines de GitLab y reforzar tu postura de seguridad. Si todavía no lo usas, te recomiendo adoptarlo en tus pipelines en lugar de las claves de cuenta de servicio.