|
1 | | -# Poc-Terraform-AWS |
| 1 | +# Proof of Concept: Node.js to AWS ECR with Terraform & GitHub Actions |
| 2 | + |
| 3 | +This project serves as a Proof of Concept (PoC) demonstrating the deployment of a Node.js (Express) backend application, containerized with Docker, to Amazon Elastic Container Registry (ECR) using Terraform for infrastructure provisioning and GitHub Actions for CI/CD automation. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The primary goal is to showcase an automated workflow where: |
| 8 | +1. Terraform defines and manages the AWS ECR repository and related resources. |
| 9 | +2. A local setup script (`setup_tf_backend.sh`) configures the Terraform backend using AWS S3 and DynamoDB. |
| 10 | +3. GitHub Actions, upon a push to the `main` branch, authenticates to AWS using an IAM Role (OIDC), builds the Docker image, and pushes it to the ECR repository provisioned by Terraform. |
| 11 | + |
| 12 | +## Features |
| 13 | + |
| 14 | +- Infrastructure as Code (IaC) using Terraform for AWS ECR. |
| 15 | +- Automated CI/CD pipeline with GitHub Actions. |
| 16 | +- Secure authentication to AWS from GitHub Actions using IAM Roles for Service Accounts (OIDC). |
| 17 | +- Docker containerization of a Node.js Express application. |
| 18 | +- Automated Terraform backend configuration (S3 bucket and DynamoDB table for state locking). |
| 19 | + |
| 20 | +## Tech Stack |
| 21 | + |
| 22 | +- **Cloud Provider:** AWS |
| 23 | + - ECR (Elastic Container Registry) |
| 24 | + - S3 (for Terraform backend state) |
| 25 | + - DynamoDB (for Terraform state locking) |
| 26 | + - IAM (Identity and Access Management - OIDC for GitHub Actions) |
| 27 | +- **IaC:** Terraform |
| 28 | +- **CI/CD:** GitHub Actions |
| 29 | +- **Containerization:** Docker |
| 30 | +- **Application:** Node.js (Express.js) |
2 | 31 |
|
3 | 32 | ## Prerequisites |
4 | 33 |
|
5 | | -- Terraform |
6 | | -- AWS CLI |
7 | | -- Docker |
8 | | -- Node.js |
9 | | -- Yarn |
| 34 | +Before you begin, ensure you have the following installed and configured: |
| 35 | + |
| 36 | +- [Terraform CLI](https://learn.hashicorp.com/tutorials/terraform/install-cli) |
| 37 | +- [AWS CLI](https://aws.amazon.com/cli/) |
| 38 | +- [Docker](https://docs.docker.com/get-docker/) |
| 39 | +- An AWS Account. |
| 40 | +- A GitHub Repository. |
| 41 | + |
| 42 | +## Setup and Configuration |
| 43 | + |
| 44 | +### 1. AWS IAM Role for GitHub Actions (OIDC) |
| 45 | + |
| 46 | +Create an IAM Role in your AWS account that GitHub Actions can assume. This role needs permissions to manage ECR, S3 (for Terraform backend), and DynamoDB (for Terraform state lock table). |
| 47 | + |
| 48 | +- Follow the AWS documentation for [Configuring OpenID Connect in Amazon Web Services](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html). |
| 49 | +- The trust relationship for the IAM role should be configured for GitHub Actions. Example policy snippet: |
| 50 | + |
| 51 | + ```json |
| 52 | + { |
| 53 | + "Version": "2012-10-17", |
| 54 | + "Statement": [ |
| 55 | + { |
| 56 | + "Effect": "Allow", |
| 57 | + "Principal": { |
| 58 | + "Federated": "arn:aws:iam::YOUR_AWS_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com" |
| 59 | + }, |
| 60 | + "Action": "sts:AssumeRoleWithWebIdentity", |
| 61 | + "Condition": { |
| 62 | + "StringLike": { |
| 63 | + "token.actions.githubusercontent.com:sub": "repo:YOUR_GITHUB_USERNAME/YOUR_REPOSITORY_NAME:*" |
| 64 | + } |
| 65 | + } |
| 66 | + } |
| 67 | + ] |
| 68 | + } |
| 69 | + ``` |
| 70 | +- Attach necessary permission policies to this role (e.g., `AmazonEC2ContainerRegistryFullAccess`, plus custom policies for S3 backend bucket creation/access and DynamoDB table creation/access if the setup script handles this). |
| 71 | + |
| 72 | +### 2. Configure GitHub Secrets |
| 73 | + |
| 74 | +In your GitHub repository, navigate to `Settings > Secrets and variables > Actions` and add the following secrets: |
| 75 | + |
| 76 | +- `AWS_REGION`: Your AWS region (e.g., `us-east-1`). |
| 77 | +- `AWS_IAM_ROLE_ARN`: The ARN of the IAM role created in the previous step (e.g., `arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/YOUR_IAM_ROLE_NAME`). |
| 78 | + |
| 79 | +### 3. Terraform Backend Setup Script |
| 80 | + |
| 81 | +The `setup_tf_backend.sh` script automates the creation of the S3 bucket and DynamoDB table for the Terraform backend and generates the necessary Terraform configuration files. |
| 82 | + |
| 83 | +- The script is expected to create: |
| 84 | + - `terraform/backend.tf`: Configures the S3 backend for Terraform state. |
| 85 | + - `terraform/variables.tf`: May define variables used by the backend setup or main configuration (e.g., `TF_STATE_KEY`, `TF_BACKEND_REGION` if these are dynamically set or user-provided). |
| 86 | + |
| 87 | +**Note:** Ensure your Terraform configuration in the `terraform/` directory (especially `main.tf` or a dedicated backend setup file) defines the resources for the S3 bucket and DynamoDB table that the `setup_tf_backend.sh` script will use or create. The script utilizes outputs like `s3_backend_bucket_name` and `dynamodb_lock_table_name` from a preliminary Terraform apply for the backend resources. |
| 88 | + |
| 89 | +## How to Run / Deployment Workflow |
| 90 | + |
| 91 | +1. **Clone the repository:** |
| 92 | + ```bash |
| 93 | + git clone https://github.com/YOUR_GITHUB_USERNAME/YOUR_REPOSITORY_NAME.git |
| 94 | + cd YOUR_REPOSITORY_NAME |
| 95 | + ``` |
| 96 | + |
| 97 | +2. **Make the setup script executable:** |
| 98 | + ```bash |
| 99 | + chmod +x setup_tf_backend.sh |
| 100 | + ``` |
| 101 | + |
| 102 | +3. **Run the setup script:** |
| 103 | + This script will typically run `terraform init` and `terraform apply` against a configuration designed to provision the S3 bucket and DynamoDB table for the state backend. It then uses the outputs to generate `terraform/backend.tf` (and potentially `terraform/variables.tf`). |
| 104 | + ```bash |
| 105 | + ./setup_tf_backend.sh |
| 106 | + ``` |
| 107 | + Follow any prompts from the script. |
| 108 | + |
| 109 | +4. **Commit and Push Changes:** |
| 110 | + After the script successfully generates `terraform/backend.tf` and `terraform/variables.tf`, commit these files and any other changes to your repository: |
| 111 | + ```bash |
| 112 | + git add terraform/backend.tf terraform/variables.tf |
| 113 | + git commit -m "Configure Terraform backend" |
| 114 | + git push origin main |
| 115 | + ``` |
| 116 | + |
| 117 | +5. **GitHub Actions Workflow:** |
| 118 | + Pushing to the `main` branch will trigger the GitHub Actions workflow defined in `.github/workflows/deploy-to-ecr.yml`. This workflow will: |
| 119 | + - Configure AWS credentials using the OIDC role. |
| 120 | + - Run `terraform init` and `terraform apply` to create/update the ECR repository defined in your main Terraform configuration (e.g., `terraform/main.tf`). |
| 121 | + - Build the Docker image using the `Dockerfile`. |
| 122 | + - Push the Docker image to the ECR repository. |
10 | 123 |
|
11 | | -## How to run |
| 124 | +## Project Structure |
12 | 125 |
|
13 | | -1. correr el pre-terraform para obtener el bucket y la tabla de locks |
14 | | -2. poner el bucket y la tabla de locks en el archivo terraform/main.tf |
15 | | -3. tener cuidado con la region |
| 126 | +``` |
| 127 | +. |
| 128 | +├── .github/workflows/ # GitHub Actions workflows |
| 129 | +│ └── deploy-to-ecr.yml # Workflow for ECR deployment |
| 130 | +├── app/ # Node.js application source code |
| 131 | +│ ├── app.js # Express application (e.g., Hello World on port 3011) |
| 132 | +│ └── package.json # Node.js dependencies |
| 133 | +├── terraform/ # Terraform configuration files |
| 134 | +│ ├── main.tf # Main infrastructure (ECR repository, etc.) |
| 135 | +│ ├── variables.tf # Terraform input variables |
| 136 | +│ ├── outputs.tf # Terraform outputs (ECR URL, region) |
| 137 | +│ └── backend.tf # (Generated by setup_tf_backend.sh) Terraform backend config |
| 138 | +├── Dockerfile # Dockerfile to build the Node.js application image |
| 139 | +├── setup_tf_backend.sh # Script to setup Terraform backend and generate config |
| 140 | +└── README.md # This file |
0 commit comments