Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 77 additions & 6 deletions .github/workflows/terraform-ci.yml
Original file line number Diff line number Diff line change
@@ -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 > envs/dev/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
});
42 changes: 42 additions & 0 deletions iam/github-oidc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# github-oidc

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6.6, < 2.0.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [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 |
|------|-------------|------|---------|:--------:|
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | n/a | `string` | `"us-east-1"` | no |
| <a name="input_github_repo"></a> [github\_repo](#input\_github\_repo) | Formato OWNER/REPO (ej: juandiegocv27/infra-terraform) | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | n/a |
<!-- END_TF_DOCS -->
75 changes: 75 additions & 0 deletions iam/github-oidc/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
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 = "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"]
}

data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]

principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.github.arn]
}

# Audience debe ser STS
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}

# 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",
"repo:${var.github_repo}:ref:refs/heads/*",
"repo:${var.github_repo}:environment:ci",
]
}
}
}

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 (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"
}

output "role_arn" {
value = aws_iam_role.github_actions_terraform.arn
}