From 0b0fd98059e7acfe624497ef649d0841c4d99c7c Mon Sep 17 00:00:00 2001 From: juandiegocv27 Date: Sat, 20 Dec 2025 02:59:31 -0600 Subject: [PATCH 1/4] ci(terraform): fmt/validate/plan on PRs via OIDC --- .github/workflows/terraform-ci.yml | 83 +++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/.github/workflows/terraform-ci.yml b/.github/workflows/terraform-ci.yml index 13a0f48..e4f1d91 100644 --- a/.github/workflows/terraform-ci.yml +++ b/.github/workflows/terraform-ci.yml @@ -1,14 +1,85 @@ name: terraform-ci + on: pull_request: + paths: + - "envs/**" + - ".github/workflows/terraform-ci.yml" push: - paths: ["envs/**", ".github/workflows/terraform-ci.yml"] + paths: + - "envs/**" + - ".github/workflows/terraform-ci.yml" + +permissions: + contents: read + id-token: write + pull-requests: write + +concurrency: + group: terraform-${{ github.ref }} + cancel-in-progress: true + jobs: - fmt-validate: + fmt-validate-plan: + name: fmt/validate/plan (envs/dev) runs-on: ubuntu-latest + environment: ci + steps: - uses: actions/checkout@v4 - - uses: hashicorp/setup-terraform@v3 - - run: terraform -chdir=envs/dev fmt -check - - run: terraform -chdir=envs/dev init -backend=false - - run: terraform -chdir=envs/dev validate + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.6.6 + + - name: Configure AWS credentials (OIDC) + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ vars.AWS_ROLE_ARN }} + aws-region: ${{ vars.AWS_REGION }} + + - name: Terraform fmt (check) + run: terraform -chdir=envs/dev fmt -check -recursive + + - name: Terraform init + run: terraform -chdir=envs/dev init -no-color + + - name: Terraform validate + run: terraform -chdir=envs/dev validate -no-color + + - name: Terraform plan + run: terraform -chdir=envs/dev plan -no-color -out=plan.tfplan + + - name: Render plan to text + run: terraform -chdir=envs/dev show -no-color plan.tfplan > plan.txt + + - name: Upload plan artifact + uses: actions/upload-artifact@v4 + with: + name: terraform-plan-${{ github.event.pull_request.number || github.run_number }} + path: | + envs/dev/plan.tfplan + envs/dev/plan.txt + retention-days: 7 + + - name: Comment plan (PR only) + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const plan = fs.readFileSync('envs/dev/plan.txt', 'utf8'); + const body = [ + '### Terraform Plan (envs/dev)', + '', + '```', + plan.length > 60000 ? plan.slice(0, 60000) + '\n... (truncado)' : plan, + '```' + ].join('\n'); + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body + }); From 1bac657d1a3c63155bd4a49ff592eeaa7a0b0f80 Mon Sep 17 00:00:00 2001 From: juandiegocv27 Date: Sat, 20 Dec 2025 03:19:51 -0600 Subject: [PATCH 2/4] feat: add modify readme --- iam/github-oidc/README.md | 42 +++++++++++++++++++++ iam/github-oidc/main.tf | 78 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 iam/github-oidc/README.md create mode 100644 iam/github-oidc/main.tf diff --git a/iam/github-oidc/README.md b/iam/github-oidc/README.md new file mode 100644 index 0000000..4edff84 --- /dev/null +++ b/iam/github-oidc/README.md @@ -0,0 +1,42 @@ +# github-oidc + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.6.6, < 2.0.0 | +| [aws](#requirement\_aws) | ~> 5.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_openid_connect_provider.github](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource | +| [aws_iam_role.github_actions_terraform](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.admin](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_region](#input\_aws\_region) | n/a | `string` | `"us-east-1"` | no | +| [github\_repo](#input\_github\_repo) | OWNER/REPO | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [role\_arn](#output\_role\_arn) | n/a | + diff --git a/iam/github-oidc/main.tf b/iam/github-oidc/main.tf new file mode 100644 index 0000000..b199f4e --- /dev/null +++ b/iam/github-oidc/main.tf @@ -0,0 +1,78 @@ +terraform { + required_version = ">= 1.6.6, < 2.0.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = var.aws_region +} + +variable "aws_region" { + type = string + default = "us-east-1" +} + +variable "github_repo" { + type = string + description = "OWNER/REPO" +} + +resource "aws_iam_openid_connect_provider" "github" { + url = "https://token.actions.githubusercontent.com" + + client_id_list = ["sts.amazonaws.com"] + + thumbprint_list = [ + "6938fd4d98bab03faadb97b34396831e3780aea1" + ] +} + +data "aws_iam_policy_document" "assume_role" { + statement { + effect = "Allow" + actions = ["sts:AssumeRoleWithWebIdentity"] + + principals { + type = "Federated" + identifiers = [aws_iam_openid_connect_provider.github.arn] + } + + + condition { + test = "StringEquals" + variable = "token.actions.githubusercontent.com:sub" + values = [ + "repo:${var.github_repo}:pull_request", + "repo:${var.github_repo}:ref:refs/heads/*", + "repo:${var.github_repo}:environment:ci" + ] + } + + # Para PRs: GitHub manda sub = repo:OWNER/REPO:pull_request + condition { + test = "StringLike" + variable = "token.actions.githubusercontent.com:sub" + values = ["repo:${var.github_repo}:pull_request"] + } + } +} + +resource "aws_iam_role" "github_actions_terraform" { + name = "github-actions-terraform-plan" + assume_role_policy = data.aws_iam_policy_document.assume_role.json +} + +# Para arrancar rápido: admin. Después lo bajás a least-privilege. +resource "aws_iam_role_policy_attachment" "admin" { + role = aws_iam_role.github_actions_terraform.name + policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" +} + +output "role_arn" { + value = aws_iam_role.github_actions_terraform.arn +} From de7a459be53c64cbc5c34c81d31e8499b348ae54 Mon Sep 17 00:00:00 2001 From: juandiegocv27 Date: Sat, 20 Dec 2025 03:36:40 -0600 Subject: [PATCH 3/4] fix(iam): correct GitHub OIDC trust policy (aud + sub patterns) pt2 --- iam/github-oidc/README.md | 2 +- iam/github-oidc/main.tf | 33 +++++++++++++++------------------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/iam/github-oidc/README.md b/iam/github-oidc/README.md index 4edff84..30d0d89 100644 --- a/iam/github-oidc/README.md +++ b/iam/github-oidc/README.md @@ -32,7 +32,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [aws\_region](#input\_aws\_region) | n/a | `string` | `"us-east-1"` | no | -| [github\_repo](#input\_github\_repo) | OWNER/REPO | `string` | n/a | yes | +| [github\_repo](#input\_github\_repo) | Formato OWNER/REPO (ej: juandiegocv27/infra-terraform) | `string` | n/a | yes | ## Outputs diff --git a/iam/github-oidc/main.tf b/iam/github-oidc/main.tf index b199f4e..d45587f 100644 --- a/iam/github-oidc/main.tf +++ b/iam/github-oidc/main.tf @@ -1,5 +1,6 @@ terraform { required_version = ">= 1.6.6, < 2.0.0" + required_providers { aws = { source = "hashicorp/aws" @@ -19,17 +20,13 @@ variable "aws_region" { variable "github_repo" { type = string - description = "OWNER/REPO" + description = "Formato OWNER/REPO (ej: juandiegocv27/infra-terraform)" } resource "aws_iam_openid_connect_provider" "github" { - url = "https://token.actions.githubusercontent.com" - - client_id_list = ["sts.amazonaws.com"] - - thumbprint_list = [ - "6938fd4d98bab03faadb97b34396831e3780aea1" - ] + url = "https://token.actions.githubusercontent.com" + client_id_list = ["sts.amazonaws.com"] + thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"] } data "aws_iam_policy_document" "assume_role" { @@ -42,22 +39,22 @@ data "aws_iam_policy_document" "assume_role" { identifiers = [aws_iam_openid_connect_provider.github.arn] } - + # Audience debe ser STS condition { test = "StringEquals" - variable = "token.actions.githubusercontent.com:sub" - values = [ - "repo:${var.github_repo}:pull_request", - "repo:${var.github_repo}:ref:refs/heads/*", - "repo:${var.github_repo}:environment:ci" - ] + variable = "token.actions.githubusercontent.com:aud" + values = ["sts.amazonaws.com"] } - # Para PRs: GitHub manda sub = repo:OWNER/REPO:pull_request + # Permitir PRs, pushes a branches, y uso de Environment "ci" condition { test = "StringLike" variable = "token.actions.githubusercontent.com:sub" - values = ["repo:${var.github_repo}:pull_request"] + values = [ + "repo:${var.github_repo}:pull_request", + "repo:${var.github_repo}:ref:refs/heads/*", + "repo:${var.github_repo}:environment:ci", + ] } } } @@ -67,7 +64,7 @@ resource "aws_iam_role" "github_actions_terraform" { assume_role_policy = data.aws_iam_policy_document.assume_role.json } -# Para arrancar rápido: admin. Después lo bajás a least-privilege. +# Para arrancar rápido (luego bajás a least-privilege) resource "aws_iam_role_policy_attachment" "admin" { role = aws_iam_role.github_actions_terraform.name policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" From 57414c7216f6811bdcefe64a756fa57e7c80f140 Mon Sep 17 00:00:00 2001 From: juandiegocv27 Date: Sat, 20 Dec 2025 03:45:56 -0600 Subject: [PATCH 4/4] fix(ci): write plan.txt under envs/dev --- .github/workflows/terraform-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/terraform-ci.yml b/.github/workflows/terraform-ci.yml index e4f1d91..947fd75 100644 --- a/.github/workflows/terraform-ci.yml +++ b/.github/workflows/terraform-ci.yml @@ -52,7 +52,7 @@ jobs: run: terraform -chdir=envs/dev plan -no-color -out=plan.tfplan - name: Render plan to text - run: terraform -chdir=envs/dev show -no-color plan.tfplan > plan.txt + run: terraform -chdir=envs/dev show -no-color plan.tfplan > envs/dev/plan.txt - name: Upload plan artifact uses: actions/upload-artifact@v4