From 744c5d1413a59a0b2d3fc17615b80a3ce686f394 Mon Sep 17 00:00:00 2001 From: Evert Daniel Romero Garrido Date: Wed, 15 Apr 2026 12:50:31 -0600 Subject: [PATCH] =?UTF-8?q?feat(iam):=20implementa=20autenticaci=C3=B3n=20?= =?UTF-8?q?OIDC=20entre=20Bitbucket=20Pipelines=20y=20AWS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Agrega aws_iam_openid_connect_provider y roles IAM para DEV/PROD - Actualiza bitbucket-pipelines.yml para usar OIDC en steps 03, 05, 07 - Crea script helper scripts/aws-oidc-setup.sh - Agrega provider tls en terraform/provider.tf - Documenta el flujo completo en docs/14-oidc-bitbucket-aws.md Elimina la dependencia de AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY estáticos en el pipeline, permitiendo autenticación sin credenciales de larga vida via AssumeRoleWithWebIdentity. Refs: cuenta DEV 668889063715, PROD 523761210517 --- bitbucket-pipelines.yml | 21 +- docs/14-oidc-bitbucket-aws.md | 352 ++++++++++++++++++++++++++++++++++ scripts/aws-oidc-setup.sh | 42 ++++ terraform/oidc-bitbucket.tf | 118 ++++++++++++ terraform/provider.tf | 4 + 5 files changed, 533 insertions(+), 4 deletions(-) create mode 100644 docs/14-oidc-bitbucket-aws.md create mode 100755 scripts/aws-oidc-setup.sh create mode 100644 terraform/oidc-bitbucket.tf diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index e7943e0..cb3a8fa 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -9,6 +9,11 @@ image: atlassian/default-image:5 +options: + oidc: + audiences: + - sts.amazonaws.com + definitions: steps: - step: ¬ify-start @@ -60,15 +65,15 @@ pipelines: - step: name: 03_terraform + oidc: true script: - set -euo pipefail + - source scripts/aws-oidc-setup.sh dev - cd terraform - wget -q "https://releases.hashicorp.com/terraform/1.11.4/terraform_1.11.4_linux_amd64.zip" - unzip -q terraform_1.11.4_linux_amd64.zip - mv terraform /usr/local/bin/terraform - terraform version - - export AWS_ACCESS_KEY_ID="${DEV_AWS_ACCESS_KEY_ID}" - - export AWS_SECRET_ACCESS_KEY="${DEV_AWS_SECRET_ACCESS_KEY}" - export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-mx-central-1}" - terraform init -backend-config=backend.dev.hcl - terraform plan -var-file=environments/dev.tfvars -var="db_password=${DEV_DB_PASSWORD}" -out=dev.tfplan @@ -91,8 +96,10 @@ pipelines: - step: name: 05_publish + oidc: true script: - set -euo pipefail + - source scripts/aws-oidc-setup.sh dev - aws s3 sync build/ "s3://${DEV_S3_FRONTEND_BUCKET}/" --delete - aws s3 cp build/libs/*.jar "s3://${DEV_S3_ARTIFACTS_BUCKET}/develop/proyectosacc-app.jar" @@ -111,8 +118,10 @@ pipelines: - step: name: 07_deploy + oidc: true script: - set -euo pipefail + - source scripts/aws-oidc-setup.sh dev - echo "${DEV_SSH_PRIVATE_KEY_THOTH_PROYECTOSACC}" | base64 -d > ~/.ssh/sacc4_key - chmod 600 ~/.ssh/sacc4_key - | @@ -148,15 +157,15 @@ pipelines: - step: name: 03_terraform + oidc: true script: - set -euo pipefail + - source scripts/aws-oidc-setup.sh prod - cd terraform - wget -q "https://releases.hashicorp.com/terraform/1.11.4/terraform_1.11.4_linux_amd64.zip" - unzip -q terraform_1.11.4_linux_amd64.zip - mv terraform /usr/local/bin/terraform - terraform version - - export AWS_ACCESS_KEY_ID="${PROD_AWS_ACCESS_KEY_ID}" - - export AWS_SECRET_ACCESS_KEY="${PROD_AWS_SECRET_ACCESS_KEY}" - export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-mx-central-1}" - terraform init -backend-config=backend.prod.hcl - terraform plan -var-file=environments/prod.tfvars -var="db_password=${PROD_DB_PASSWORD}" -out=prod.tfplan @@ -179,8 +188,10 @@ pipelines: - step: name: 05_publish + oidc: true script: - set -euo pipefail + - source scripts/aws-oidc-setup.sh prod - aws s3 sync build/ "s3://${PROD_S3_FRONTEND_BUCKET}/" --delete - aws s3 cp build/libs/*.jar "s3://${PROD_S3_ARTIFACTS_BUCKET}/main/proyectosacc-app.jar" @@ -199,8 +210,10 @@ pipelines: - step: name: 07_deploy + oidc: true script: - set -euo pipefail + - source scripts/aws-oidc-setup.sh prod - echo "${PROD_SSH_PRIVATE_KEY_THOTH_PROYECTOSACC}" | base64 -d > ~/.ssh/sacc4_key - chmod 600 ~/.ssh/sacc4_key - | diff --git a/docs/14-oidc-bitbucket-aws.md b/docs/14-oidc-bitbucket-aws.md new file mode 100644 index 0000000..2de2f17 --- /dev/null +++ b/docs/14-oidc-bitbucket-aws.md @@ -0,0 +1,352 @@ +# 14 - Autenticación OIDC entre Bitbucket Pipelines y AWS + +> Guía paso a paso para eliminar Access Keys estáticas y usar OpenID Connect (OIDC) en el pipeline de `proyectosacc`. + +--- + +## 1. ¿Por qué OIDC? + +En muchos equipos, los pipelines de CI/CD usan **IAM Users** con **Access Keys de larga vida** (`AWS_ACCESS_KEY_ID` y `AWS_SECRET_ACCESS_KEY`). Esto tiene varios problemas: + +| Problema | Explicación | +|----------|-------------| +| **Rotación manual** | Las keys deben renovarse periódicamente (cada 90 días recomendado). Si se olvida, el pipeline falla. | +| **Fuga de secretos** | Si las keys se filtran (logs, commits, etc.), un atacante puede usarlas desde cualquier lugar del mundo. | +| **Deny de IAM** | En organizaciones maduras, los administradores bloquean `iam:CreateUser` e `iam:CreateAccessKey`, haciendo imposible este camino. | + +**OIDC resuelve todo esto** permitiendo que el pipeline de Bitbucket asuma un **rol IAM temporal** automáticamente, sin guardar credenciales estáticas. Cada ejecución obtiene un token JWT que AWS valida y convierte en credenciales temporales (vencen en 1 hora por defecto). + +--- + +## 2. ¿Cómo funciona el flujo? + +El proceso es como mostrar una credencial de invitado en la entrada de un edificio: + +``` +┌─────────────────┐ 1. Solicita token OIDC ┌─────────────────┐ +│ Bitbucket │ ───────────────────────────────▶│ Bitbucket │ +│ Pipelines │ OIDC Provider │ +│ (runner) │◀────────────────────────────────│ │ +└─────────────────┘ 2. Devuelve JWT firmado └─────────────────┘ + │ + │ 3. Presenta JWT + Role ARN + ▼ +┌─────────────────┐ 4. Valida JWT contra ┌─────────────────┐ +│ AWS STS │ ───────────────────────────────▶│ AWS IAM │ +│ (sts:AssumeRole│ OIDC Provider │ +│ WithWebIdent.)│◀────────────────────────────────│ │ +└─────────────────┘ 5. Confía si aud/sub OK └─────────────────┘ + │ + │ 6. Devuelve credenciales temporales + ▼ +┌─────────────────┐ +│ Pipeline │ 7. Ejecuta Terraform / aws s3 / cloudfront ... +│ con acceso AWS │ +└─────────────────┘ +``` + +**Claims importantes del JWT:** + +| Claim | Significado | Ejemplo | +|-------|-------------|---------| +| `aud` | Audience (a quién va dirigido el token) | `sts.amazonaws.com` | +| `sub` | Subject (quién solicita el token) | `{REPO_UUID}:{STEP_UUID}` | +| `iss` | Issuer (quién emitió el token) | `https://api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc` | + +--- + +## 3. Pre-requisitos + +Antes de empezar, asegúrate de tener: + +1. **Acceso administrativo a AWS** (consola o CLI) en ambas cuentas: + - DEV: `668889063715` + - PROD: `523761210517` +2. **Permiso para crear** `iam:CreateOpenIDConnectProvider` y `iam:CreateRole`. +3. El **Repository UUID** de `ccsoft1/proyectosacc`. Lo encuentras en: + - Bitbucket > Repository settings > OpenID Connect > **Repository UUID** + - Formato: `{1de489be-ce6a-42a0-a8c8-eadbf1174ac7}` (incluye las llaves `{}`) + +--- + +## 4. Bootstrap manual: crear OIDC Provider y Roles + +> **IMPORTANTE**: El pipeline NO puede crear su propio rol OIDC porque aún no tiene credenciales. La primera vez, un administrador debe crear el `OIDC Provider` y los `IAM Roles` manualmente o ejecutando Terraform desde su laptop con credenciales de admin. + +### Opción A: Aplicar con Terraform local (recomendado) + +1. Clona el repo en tu máquina: + ```bash + git clone https://bitbucket.org/ccsoft1/proyectosacc.git + cd proyectosacc/terraform + ``` + +2. Edita `terraform/oidc-bitbucket.tf` y reemplaza el placeholder: + ```hcl + bitbucket_repo_uuid = "{1de489be-ce6a-42a0-a8c8-eadbf1174ac7}" + ``` + +3. Configura tus credenciales de admin para la cuenta **DEV**: + ```bash + export AWS_ACCESS_KEY_ID="AKIA..." + export AWS_SECRET_ACCESS_KEY="..." + export AWS_DEFAULT_REGION="mx-central-1" + ``` + +4. Inicializa y aplica: + ```bash + terraform init -backend-config=backend.dev.hcl + terraform plan -var-file=environments/dev.tfvars -target=aws_iam_openid_connect_provider.bitbucket -target=aws_iam_role.bitbucket_ci_cd + terraform apply -var-file=environments/dev.tfvars -target=aws_iam_openid_connect_provider.bitbucket -target=aws_iam_role.bitbucket_ci_cd + ``` + +5. Repite para la cuenta **PROD** cambiando el backend: + ```bash + terraform init -backend-config=backend.prod.hcl -reconfigure + terraform plan -var-file=environments/prod.tfvars -target=aws_iam_openid_connect_provider.bitbucket -target=aws_iam_role.bitbucket_ci_cd + terraform apply -var-file=environments/prod.tfvars -target=aws_iam_openid_connect_provider.bitbucket -target=aws_iam_role.bitbucket_ci_cd + ``` + +### Opción B: Crear desde la Consola AWS (paso a paso) + +#### Paso 1: Crear el OIDC Provider + +Repite esto en **DEV** y **PROD**: + +1. Ve a **IAM > Identity Providers > Add Provider**. +2. Selecciona **OpenID Connect**. +3. **Provider URL**: `https://api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc` +4. Haz clic en **Get thumbprint** (AWS lo obtendrá automáticamente). +5. **Audience**: `sts.amazonaws.com` +6. Guarda con el nombre sugerido: `bitbucket-pipelines-oidc` + +#### Paso 2: Crear el Rol IAM para DEV + +1. Ve a **IAM > Roles > Create Role**. +2. Tipo de entidad confiable: **Web Identity**. +3. Selecciona el provider creado en el paso anterior. +4. **Audience**: `sts.amazonaws.com`. +5. En **Conditions**, agrega una condición personalizada (avanzado) o edita el trust policy después de crearlo. +6. Nombre del rol: `BitbucketProyectosaccCICDRoleDev` +7. Adjunta la política `AdministratorAccess` (solo como punto de partida). +8. Edita el **Trust Policy** para que quede así: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::668889063715:oidc-provider/api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc:aud": "sts.amazonaws.com" + }, + "StringLike": { + "api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc:sub": "{REPO_UUID}:*" + } + } + } + ] +} +``` + +Reemplaza `{REPO_UUID}` por el UUID real del repositorio. + +#### Paso 3: Crear el Rol IAM para PROD + +Repite exactamente el paso 2 pero en la cuenta PROD (`523761210517`) y con el nombre: + +``` +BitbucketProyectosaccCICDRoleProd +``` + +El ARN del provider federado cambiará a: +``` +arn:aws:iam::523761210517:oidc-provider/api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc +``` + +--- + +## 5. Configuración del pipeline + +El archivo `bitbucket-pipelines.yml` ya fue actualizado para usar OIDC. Estos son los cambios clave: + +### 5.1 Audience global + +```yaml +options: + oidc: + audiences: + - sts.amazonaws.com +``` + +Esto le dice a Bitbucket que el token OIDC incluya `sts.amazonaws.com` en el claim `aud`. + +### 5.2 Activar OIDC en los steps + +Cada step que interactúa con AWS debe tener `oidc: true`: + +```yaml +- step: + name: 03_terraform + oidc: true + script: + - source scripts/aws-oidc-setup.sh dev + - ... +``` + +En `proyectosacc`, los steps con OIDC son: +- `03_terraform` +- `05_publish` +- `07_deploy` + +### 5.3 Script helper `aws-oidc-setup.sh` + +Este script: +1. Lee `BITBUCKET_STEP_OIDC_TOKEN` (lo inyecta Bitbucket automáticamente). +2. Lo guarda en un archivo temporal. +3. Exporta `AWS_WEB_IDENTITY_TOKEN_FILE` y `AWS_ROLE_ARN`. +4. AWS CLI y Terraform usan estas variables para asumir el rol automáticamente. + +--- + +## 6. ¿Cómo probar que funciona? + +### Prueba 1: Verificar el token JWT + +Crea un pipeline de prueba temporal o agrega este comando al inicio de un step: + +```bash +echo "$BITBUCKET_STEP_OIDC_TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool +``` + +Deberías ver algo como: +```json +{ + "sub": "{1de489be-ce6a-42a0-a8c8-eadbf1174ac7}:{759de0c6-eaee-4eaa-b7a6-c507eec759a7}", + "aud": "sts.amazonaws.com", + "iss": "https://api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc", + ... +} +``` + +### Prueba 2: Verificar AssumeRole desde el pipeline + +Agrega temporalmente esto al step `03_terraform`: + +```bash +source scripts/aws-oidc-setup.sh dev +aws sts get-caller-identity +``` + +Debería devolver el ARN del rol asumido: +```json +{ + "UserId": "AROA...:bot/session", + "Account": "668889063715", + "Arn": "arn:aws:sts::668889063715:assumed-role/BitbucketProyectosaccCICDRoleDev/bot/session" +} +``` + +### Prueba 3: Pipeline completo en DEV + +1. Haz push a la rama `developer`. +2. Ve a Bitbucket > Pipelines. +3. Verifica que `03_terraform`, `05_publish` y `07_deploy` terminen en verde. +4. Si falla, revisa la sección de Troubleshooting. + +--- + +## 7. Troubleshooting común + +### Error: `BITBUCKET_STEP_OIDC_TOKEN no está definido` + +**Causa**: Olvidaste agregar `oidc: true` al step. + +**Solución**: Verifica que los steps `03_terraform`, `05_publish` y `07_deploy` tengan: +```yaml +oidc: true +``` + +--- + +### Error: `An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation` + +**Causa**: El `aud` del token no coincide con el `client_id_list` del OIDC Provider. + +**Solución**: +1. Verifica que `bitbucket-pipelines.yml` tenga: + ```yaml + options: + oidc: + audiences: + - sts.amazonaws.com + ``` +2. Verifica que el OIDC Provider en AWS tenga `sts.amazonaws.com` en `client_id_list`. + +--- + +### Error: `AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity` + +**Causa**: El trust policy del rol no coincide con el claim `sub` del token. + +**Solución**: +1. Obtén el `sub` real del token (ver Prueba 1). +2. Ajusta el trust policy. Si usas `StringLike`, asegúrate de que el patrón termine en `:*`: + ```json + "StringLike": { + "api.bitbucket.org/2.0/workspaces/ccsoft1/pipelines-config/identity/oidc:sub": "{REPO_UUID}:*" + } + ``` +3. Si aún no conoces el `REPO_UUID`, puedes poner `"*"` temporalmente **solo para pruebas** (menos seguro). + +--- + +### Error: `Unable to locate credentials` + +**Causa**: AWS CLI no encuentra el token o el rol. + +**Solución**: +1. Confirma que `scripts/aws-oidc-setup.sh` se ejecutó antes de cualquier comando `aws` o `terraform`. +2. Verifica que `AWS_WEB_IDENTITY_TOKEN_FILE` y `AWS_ROLE_ARN` estén exportadas. +3. Asegúrate de usar una versión reciente de AWS CLI (`aws --version` >= 2.x). + +--- + +### Error: `terraform init` falla por permisos al bucket de estado + +**Causa**: El rol OIDC no tiene permisos para leer/escribir el bucket S3 de estado ni la tabla DynamoDB de locks. + +**Solución**: Como usamos `AdministratorAccess` como punto de partida, esto no debería pasar. Si en el futuro restringes la política, asegúrate de incluir permisos sobre: +- `s3:GetObject`, `s3:PutObject`, `s3:ListBucket` en el bucket de estado +- `dynamodb:GetItem`, `dynamodb:PutItem`, `dynamodb:DeleteItem` en la tabla de locks + +--- + +## 8. Roadmap de hardening + +Aunque `AdministratorAccess` hace que todo funcione inmediatamente, es una mala práctica de seguridad dejarlo así a largo plazo. + +| Prioridad | Acción | Justificación | +|-----------|--------|---------------| +| **Alta** | Reemplazar `AdministratorAccess` por una política custom basada en `docs/iam-policy-ci-cd-proyectosacc.json`. | Mínimo privilegio. | +| **Media** | Restringir el `sub` claim al `REPO_UUID` exacto. | Evita que otros repos del workspace asuman el rol. | +| **Media** | Separar roles: uno para Terraform (infraestructura) y otro para despliegue de aplicación (S3 + CloudFront). | Reduce el blast radius. | +| **Baja** | Agregar condiciones de IP en el trust policy (si el pipeline siempre corre desde rangos conocidos de Bitbucket). | Capa extra de seguridad. | + +--- + +## Referencias + +- [Deploy on AWS using Bitbucket Pipelines OpenID Connect – Atlassian](https://support.atlassian.com/bitbucket-cloud/docs/deploy-on-aws-using-bitbucket-pipelines-openid-connect/) +- [AWS Docs: Creating OpenID Connect identity providers](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) +- [docs/12-credenciales-aws-ci-cd.md](12-credenciales-aws-ci-cd.md) — Contexto anterior de credenciales estáticas. +- [docs/iam-policy-ci-cd-proyectosacc.json](iam-policy-ci-cd-proyectosacc.json) — Política mínima de referencia. + +--- + +*Área de Tecnología y Desarrollo — CCsoft — Abril 2026* diff --git a/scripts/aws-oidc-setup.sh b/scripts/aws-oidc-setup.sh new file mode 100755 index 0000000..37b2203 --- /dev/null +++ b/scripts/aws-oidc-setup.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# =============================================================================================================== +# aws-oidc-setup.sh - Configura credenciales AWS via OIDC para Bitbucket Pipelines +# Descripción: +# Exporta las variables necesarias para que AWS CLI y Terraform usen +# el token OIDC de Bitbucket y asuman el rol IAM correspondiente. +# +# Uso: +# source scripts/aws-oidc-setup.sh +# +# Requiere: +# - El step de bitbucket-pipelines.yml debe tener "oidc: true" +# - AWS CLI moderno que soporte AWS_WEB_IDENTITY_TOKEN_FILE +# =============================================================================================================== + +set -euo pipefail + +ENV="${1:-dev}" + +if [[ -z "${BITBUCKET_STEP_OIDC_TOKEN:-}" ]]; then + echo "ERROR: BITBUCKET_STEP_OIDC_TOKEN no está definido." + echo "Asegúrate de agregar 'oidc: true' al step en bitbucket-pipelines.yml" + exit 1 +fi + +export AWS_WEB_IDENTITY_TOKEN_FILE="$(pwd)/web-identity-token" +printf '%s' "${BITBUCKET_STEP_OIDC_TOKEN}" > "${AWS_WEB_IDENTITY_TOKEN_FILE}" + +if [[ "$ENV" == "prod" ]]; then + export AWS_ROLE_ARN="arn:aws:iam::523761210517:role/BitbucketProyectosaccCICDRoleProd" +else + export AWS_ROLE_ARN="arn:aws:iam::668889063715:role/BitbucketProyectosaccCICDRoleDev" +fi + +export AWS_DEFAULT_REGION="mx-central-1" + +echo "=== AWS OIDC Setup ===" +echo "Ambiente : $ENV" +echo "Role ARN : $AWS_ROLE_ARN" +echo "Region : $AWS_DEFAULT_REGION" +echo "Token file: $AWS_WEB_IDENTITY_TOKEN_FILE" +echo "======================" diff --git a/terraform/oidc-bitbucket.tf b/terraform/oidc-bitbucket.tf new file mode 100644 index 0000000..d22a194 --- /dev/null +++ b/terraform/oidc-bitbucket.tf @@ -0,0 +1,118 @@ +# =============================================================================================================== +# oidc-bitbucket.tf - Configuración OIDC entre Bitbucket Pipelines y AWS +# Descripción: +# Crea el IAM OIDC Provider para Bitbucket y el rol IAM que el pipeline +# asumirá mediante Web Identity Federation (AssumeRoleWithWebIdentity). +# +# IMPORTANTE (Bootstrap): +# Este archivo debe aplicarse MANUALMENTE la primera vez por un +# administrador con credenciales AWS válidas. Una vez creados el +# OIDC provider y el rol, el pipeline puede autenticarse solo. +# =============================================================================================================== + +locals { + bitbucket_workspace = "ccsoft1" + bitbucket_oidc_url = "https://api.bitbucket.org/2.0/workspaces/${local.bitbucket_workspace}/pipelines-config/identity/oidc" + + # ------------------------------------------------------------------ + # REPO_UUID de proyectosacc + # ------------------------------------------------------------------ + # Obtener en Bitbucket: Repository settings > OpenID Connect > Repository UUID + # Ejemplo real: "{1de489be-ce6a-42a0-a8c8-eadbf1174ac7}" + # + # NOTA DE SEGURIDAD: + # Si aún no conoces el UUID exacto, puedes dejar "*" temporalmente + # para permitir cualquier repo del workspace. Esto es MENOS SEGURO + # y solo debe usarse durante las pruebas iniciales. En producción, + # reemplázalo por el UUID exacto del repo ccsoft1/proyectosacc. + # ------------------------------------------------------------------ + bitbucket_repo_uuid = "{REPO_UUID_PLACEHOLDER}" +} + +# Obtener el thumbprint del certificado TLS del issuer OIDC +data "tls_certificate" "bitbucket_oidc" { + url = local.bitbucket_oidc_url +} + +# ------------------------------------------------------------------------------- +# OIDC Provider para Bitbucket Pipelines +# ------------------------------------------------------------------------------- +resource "aws_iam_openid_connect_provider" "bitbucket" { + url = local.bitbucket_oidc_url + + # Usamos "sts.amazonaws.com" como audience para simplificar la + # configuración y evitar depender del Workspace UUID de Bitbucket. + # Esto requiere configurar "audiences: [sts.amazonaws.com]" en + # bitbucket-pipelines.yml. + client_id_list = [ + "sts.amazonaws.com" + ] + + thumbprint_list = [ + data.tls_certificate.bitbucket_oidc.certificates[0].sha1_fingerprint + ] + + tags = { + Name = "bitbucket-pipelines-oidc" + Project = var.project_name + ManagedBy = "terraform" + Environment = var.environment + } +} + +# ------------------------------------------------------------------------------- +# Rol IAM para CI/CD desde Bitbucket Pipelines +# ------------------------------------------------------------------------------- +resource "aws_iam_role" "bitbucket_ci_cd" { + name = "BitbucketProyectosaccCICDRole${title(var.environment)}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Federated = aws_iam_openid_connect_provider.bitbucket.arn + } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "${trimprefix(local.bitbucket_oidc_url, "https://")}:aud" = "sts.amazonaws.com" + } + StringLike = { + "${trimprefix(local.bitbucket_oidc_url, "https://")}:sub" = "${local.bitbucket_repo_uuid}:*" + } + } + } + ] + }) + + tags = { + Name = "bitbucket-ci-cd-role-${var.environment}" + Project = var.project_name + Environment = var.environment + ManagedBy = "terraform" + } +} + +# ------------------------------------------------------------------------------- +# Política de permisos: AdministratorAccess (punto de partida) +# ------------------------------------------------------------------------------- +# TODO: Reemplazar AdministratorAccess por una política custom con +# mínimo privilegio. Ver docs/iam-policy-ci-cd-proyectosacc.json como +# base para construir la política restrictiva. +# ------------------------------------------------------------------------------- +resource "aws_iam_role_policy_attachment" "bitbucket_ci_cd_admin" { + role = aws_iam_role.bitbucket_ci_cd.name + policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" +} + +# ------------------------------------------------------------------------------- +# Política mínima alternativa (descomentar cuando esté lista) +# ------------------------------------------------------------------------------- +# resource "aws_iam_role_policy" "bitbucket_ci_cd_minimal" { +# name = "${var.project_name}-bitbucket-ci-cd-minimal-${var.environment}" +# role = aws_iam_role.bitbucket_ci_cd.id +# +# policy = file("${path.module}/../docs/iam-policy-ci-cd-proyectosacc.json") +# } diff --git a/terraform/provider.tf b/terraform/provider.tf index d8f488d..9d1ee64 100644 --- a/terraform/provider.tf +++ b/terraform/provider.tf @@ -17,6 +17,10 @@ terraform { source = "hashicorp/aws" version = ">= 5.94.0" } + tls = { + source = "hashicorp/tls" + version = ">= 4.0.0" + } } }