From 96209b4ec8ef0dc1a38b00145c8c7198b2f80bca Mon Sep 17 00:00:00 2001 From: Andre Wlodkovski Date: Mon, 1 Apr 2024 17:58:19 -0300 Subject: [PATCH 1/5] Add Terraform ignore files --- .dockerignore | 5 +++-- .gitignore | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.dockerignore b/.dockerignore index 9b9920f..6211f1a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,9 @@ node_modules -.github -.vscode +terraform build docs +.github +.vscode .env *.log .gitignore diff --git a/.gitignore b/.gitignore index 9897e88..1c5f1b5 100644 --- a/.gitignore +++ b/.gitignore @@ -138,4 +138,11 @@ src/database/schemas/generated src/docs/swagger_output.json # TSDoc artifacts -docs \ No newline at end of file +docs + +# Terraform files +*.tfvars +*.tfvars.json +*.tfstate +*.tfstate.* +**/.terraform/* \ No newline at end of file From aa88666da92624b9f69f3058c794885310ddf7a1 Mon Sep 17 00:00:00 2001 From: Andre Wlodkovski Date: Mon, 1 Apr 2024 18:28:12 -0300 Subject: [PATCH 2/5] Add AWS RDS Terraform resources --- terraform/main.tf | 57 ++++++++++++++++++++++++++++++++++++++++++ terraform/variables.tf | 56 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 terraform/main.tf create mode 100644 terraform/variables.tf diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..2003d8d --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,57 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.43.0" + } + } + + required_version = ">= 1.7.5" +} + +provider "aws" { + access_key = var.aws_access_key_id + secret_key = var.aws_secret_access_key + region = var.aws_region +} + +# RDS Resources +resource "aws_db_instance" "authentication_db" { + allocated_storage = var.db_storage + db_name = "${var.db_name}-${var.infra_env}" + engine = "postgres" + engine_version = "16.2" + instance_class = var.db_instance_type + username = var.db_username + password = var.db_password + skip_final_snapshot = true + publicly_accessible = true + + tags = { + "Environment" = var.infra_env + "Name" = "${var.db_name}-${var.infra_env}" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_secretsmanager_secret" "db_secret" { + name = "${var.db_name}-${var.infra_env}-secret" + + tags = { + "Environment" = var.infra_env + "Name" = "${var.db_name}-${var.infra_env}-secret" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_secretsmanager_secret_version" "db_secret_values" { + secret_id = aws_secretsmanager_secret.db_secret.id + secret_string = jsonencode({ + "DATABASE_URL" = "postgres://${var.db_username}:${var.db_password}@${aws_db_instance.authentication_db.endpoint}/${var.db_schema_name}?schema=public" + "ENDPOINT" = "${aws_db_instance.authentication_db.endpoint}" + }) +} \ No newline at end of file diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..f1e6780 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,56 @@ +variable "infra_env" { + type = string + description = "Infrastructure environment (prod/dev/test)" +} + +variable "aws_access_key_id" { + type = string + description = "AWS Access Key ID" + sensitive = true +} + +variable "aws_secret_access_key" { + type = string + description = "AWS Secret Access Key" + sensitive = true +} + +variable "aws_region" { + type = string + description = "AWS primary region to create resources" + default = "us-east-1" +} + +variable "db_storage" { + type = number + description = "Amount of storage allocated into the RDS instance, in GB" + default = 10 +} + +variable "db_name" { + type = string + description = "Name of the RDS instance" +} + +variable "db_schema_name" { + type = string + description = "Name of the authentication system schema in the RDS database" +} + +variable "db_instance_type" { + type = string + description = "Type of the RDS instance" + default = "db.t3.micro" +} + +variable "db_username" { + type = string + description = "RDS database username" + sensitive = true +} + +variable "db_password" { + type = string + description = "RDS database password" + sensitive = true +} \ No newline at end of file From a5c37542f0e72eeeaf3d93462e627f5f899d6eab Mon Sep 17 00:00:00 2001 From: Andre Wlodkovski Date: Mon, 1 Apr 2024 18:57:51 -0300 Subject: [PATCH 3/5] Add AWS VPC Terraform resources --- terraform/main.tf | 137 +++++++++++++++++++++++++++++++++++++++++ terraform/variables.tf | 24 ++++++++ 2 files changed, 161 insertions(+) diff --git a/terraform/main.tf b/terraform/main.tf index 2003d8d..e17ab3e 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -15,6 +15,143 @@ provider "aws" { region = var.aws_region } +# VPC Resources +resource "aws_vpc" "main_vpc" { + cidr_block = var.vpc_cidr + + tags = { + "Environment" = var.infra_env + "Name" = "auth-vpc-${var.infra_env}" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_subnet" "public_subnets" { + for_each = var.public_subnet_map + + vpc_id = "${aws_vpc.vpc.id}" + cidr_block = "${each.value}" + availability_zone = "${each.key}" + map_public_ip_on_launch = true + + tags = { + "Environment" = var.infra_env + "Name" = "auth-public-subnet" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_internet_gateway" "igw" { + vpc_id = "${aws_vpc.main_vpc.id}" + + tags = { + "Environment" = var.infra_env + "Name" = "auth-vpc-igw" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_route_table" "public_route_table" { + vpc_id = "${aws_vpc.main_vpc.id}" + + tags = { + "Environment" = var.infra_env + "Name" = "auth-vpc-public-rt" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_route" "public_internet_gateway" { + route_table_id = aws_route_table.public_route_table.id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.igw.id +} + +resource "aws_route_table_association" "public_subnets_associations" { + for_each = toset(aws_subnet.public_subnets) + + subnet_id = each.key.id + route_table_id = aws_route_table.public_route_table.id +} + +resource "aws_security_group" "public_sg" { + name = "auth-public-sg" + description = "Security group to allow inbound/outbound from the VPC on application ports" + vpc_id = aws_vpc.main_vpc.id + depends_on = [aws_vpc.main_vpc] + + ingress { + from_port = "80" + to_port = "80" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = "443" + to_port = "443" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = "0" + to_port = "0" + protocol = "-1" + self = true + } + + egress { + from_port = "0" + to_port = "0" + protocol = "-1" + cidr_blocks = [ "0.0.0.0" ] + } + tags = { + "Environment" = var.infra_env + "Name" = "auth-public-sg" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_security_group" "private_sg" { + name = "auth-private-sg" + description = "Security group for internal VPC traffic" + vpc_id = aws_vpc.main_vpc.id + depends_on = [aws_vpc.main_vpc] + + ingress { + from_port = "0" + to_port = "0" + protocol = "-1" + self = true + } + + egress { + from_port = "0" + to_port = "0" + protocol = "-1" + cidr_blocks = [ "0.0.0.0" ] + } + tags = { + "Environment" = var.infra_env + "Name" = "auth-public-sg" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + # RDS Resources resource "aws_db_instance" "authentication_db" { allocated_storage = var.db_storage diff --git a/terraform/variables.tf b/terraform/variables.tf index f1e6780..ca798d1 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -21,6 +21,30 @@ variable "aws_region" { default = "us-east-1" } +variable "vpc_cidr" { + type = string + description = "CIDR of the main VPC" + default = "10.0.0.0/24" +} + +variable "public_subnet_map" { + type = map(string) + description = "Mapping between public subnet AZs and CIDRs" + default = { + "us-east-1a" = "10.0.0.0/28" + "us-east-1b" = "10.0.0.16/28" + } +} + +variable "private_subnet_map" { + type = map(string) + description = "Mapping between private subnet AZs and CIDRs" + default = { + "us-east-1a" = "10.0.0.32/28" + "us-east-1b" = "10.0.0.48/28" + } +} + variable "db_storage" { type = number description = "Amount of storage allocated into the RDS instance, in GB" From 06a4517bf318732dea6136d5a3e38cf99aa8f5f2 Mon Sep 17 00:00:00 2001 From: Andre Wlodkovski Date: Mon, 1 Apr 2024 19:03:23 -0300 Subject: [PATCH 4/5] Move AWS RDS instance to VPC subnet --- terraform/main.tf | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/terraform/main.tf b/terraform/main.tf index e17ab3e..cd3651a 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -45,6 +45,10 @@ resource "aws_subnet" "public_subnets" { } } +locals { + public_subnet_ids = [ for subnet in aws_subnet.public_subnets : subnet.id ] +} + resource "aws_internet_gateway" "igw" { vpc_id = "${aws_vpc.main_vpc.id}" @@ -76,9 +80,9 @@ resource "aws_route" "public_internet_gateway" { } resource "aws_route_table_association" "public_subnets_associations" { - for_each = toset(aws_subnet.public_subnets) + for_each = toset(local.public_subnet_ids) - subnet_id = each.key.id + subnet_id = each.key route_table_id = aws_route_table.public_route_table.id } @@ -153,6 +157,19 @@ resource "aws_security_group" "private_sg" { } # RDS Resources +resource "aws_db_subnet_group" "authentication_db_sng" { + name = "authdbsng" + subnet_ids = local.public_subnet_ids + + tags = { + "Environment" = var.infra_env + "Name" = "authdbsng" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + resource "aws_db_instance" "authentication_db" { allocated_storage = var.db_storage db_name = "${var.db_name}-${var.infra_env}" @@ -162,7 +179,9 @@ resource "aws_db_instance" "authentication_db" { username = var.db_username password = var.db_password skip_final_snapshot = true - publicly_accessible = true + publicly_accessible = true + + db_subnet_group_name = aws_db_subnet_group.authentication_db_sng.name tags = { "Environment" = var.infra_env From 3e4b88c2d300ef12dc2c64da32b52ab4e4cafaea Mon Sep 17 00:00:00 2001 From: Andre Wlodkovski Date: Mon, 1 Apr 2024 20:06:12 -0300 Subject: [PATCH 5/5] Add AWS EKS Terraform resources --- terraform/main.tf | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/terraform/main.tf b/terraform/main.tf index cd3651a..95cd792 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -210,4 +210,79 @@ resource "aws_secretsmanager_secret_version" "db_secret_values" { "DATABASE_URL" = "postgres://${var.db_username}:${var.db_password}@${aws_db_instance.authentication_db.endpoint}/${var.db_schema_name}?schema=public" "ENDPOINT" = "${aws_db_instance.authentication_db.endpoint}" }) +} + +# IAM Resources +resource "aws_iam_role" "eks_fargate_execution_role" { + name = "eks-fargate-execution-role" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "eks-fargate-pods.amazonaws.com" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_iam_role_policy_attachment" "eks_fargate_execution_attachment" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy" + role = aws_iam_role.eks_fargate_execution_role.arn +} + +resource "aws_iam_role" "eks_cluster_role" { + name = "eks-cluster-role" + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "eks.amazonaws.com" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_iam_role_policy_attachment" "eks_cluster_policy_attachment" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" + role = aws_iam_role.eks_cluster_role.name +} + +resource "aws_iam_role_policy_attachment" "eks_cluster_vpc_policy_attachment" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController" + role = aws_iam_role.eks_cluster_role.name +} + +# EKS Resources +resource "aws_eks_cluster" "authentication_cluster" { + name = "authentication-cluster-${var.infra_env}" + role_arn = aws_iam_role.eks_cluster_role.arn + + vpc_config { + security_group_ids = [aws_security_group.public_sg.id, aws_security_group.private_sg.id] + subnet_ids = local.public_subnet_ids + } + + tags = { + "Environment" = var.infra_env + "Name" = "authentication-cluster-${var.infra_env}" + "Project" = "authentication-app" + "ManagedBy" = "terraform" + "Organization" = "andrewlod" + } +} + +resource "aws_eks_fargate_profile" "auth_cluster_fargate_profile" { + fargate_profile_name = "authentication-cluster-profile-${var.infra_env}" + cluster_name = aws_eks_cluster.authentication_cluster.name + pod_execution_role_arn = aws_iam_role.eks_fargate_execution_role.arn + subnet_ids = local.public_subnet_ids + + selector { + namespace = "default" + } } \ No newline at end of file