From 2274e644f92339c43fd39103bc5e0ed4c5a46c43 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Wed, 5 Jul 2023 14:57:50 +0100 Subject: [PATCH] first commit of the infrastructure repo, setting up --- infrastructure/terraform/README.md | 53 +++++++++++++++++++++++++ infrastructure/terraform/dev.tfvars | 6 +++ infrastructure/terraform/main.tf | 56 +++++++++++++++++++++++++++ infrastructure/terraform/secrets.tf | 1 + infrastructure/terraform/variables.tf | 24 ++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 infrastructure/terraform/README.md create mode 100644 infrastructure/terraform/dev.tfvars create mode 100644 infrastructure/terraform/main.tf create mode 100644 infrastructure/terraform/secrets.tf create mode 100644 infrastructure/terraform/variables.tf diff --git a/infrastructure/terraform/README.md b/infrastructure/terraform/README.md new file mode 100644 index 00000000..75c7c2f5 --- /dev/null +++ b/infrastructure/terraform/README.md @@ -0,0 +1,53 @@ +# Infrastructure Terraform Repository + +This repository manages the permanent infrastructure behind the assessment model. Key components to this include + +- Database +- Blob storage (s3 buckets) + +# Terraform AWS Deployment + +This project uses Terraform to create infrastructure in AWS. This README covers the steps necessary to deploy the resources. + +## Prerequisites + +- AWS CLI v2 installed and configured with profiles +- Terraform v1.2.0 or higher + +## Deploying + +The deployment process can be broken down into the following steps: + +1. Initialization: This downloads the necessary provider plugins for Terraform. + +```bash +terraform init +``` + +2. Planning: This step creates an execution plan, showing what changes Terraform will make to reach the desired state. + +```bash +terraform plan -var-file=dev.tfvars +``` + +Note: replace dev.tfvars with your appropriate variables file. For a production deployment, this would be the prod.tfvars file. + +3. Apply: This step applies the desired changes to reach the desired infrastructure state. + +```bash +terraform apply -var-file=dev.tfvars +``` + +Note: replace dev.tfvars with your appropriate variables file. + +## AWS Profiles + +This project uses AWS profiles for managing different environments. Ensure you have your profiles set up in your AWS credentials file `(~/.aws/credentials)`. Here is a sample: + +```ini +[DevAdmin] +aws_access_key_id = YOUR_ACCESS_KEY +aws_secret_access_key = YOUR_SECRET_KEY +``` + +In the given example, DevAdmin is the profile for the development environment. Replace YOUR_ACCESS_KEY and YOUR_SECRET_KEY with your actual AWS credentials. diff --git a/infrastructure/terraform/dev.tfvars b/infrastructure/terraform/dev.tfvars new file mode 100644 index 00000000..09af07c5 --- /dev/null +++ b/infrastructure/terraform/dev.tfvars @@ -0,0 +1,6 @@ +profile = "DevAdmin" + +# Database +allocated_storage = 20 +instance_class = "db.t2.micro" +database_name = "DevAssessmentModelDB" \ No newline at end of file diff --git a/infrastructure/terraform/main.tf b/infrastructure/terraform/main.tf new file mode 100644 index 00000000..a645e291 --- /dev/null +++ b/infrastructure/terraform/main.tf @@ -0,0 +1,56 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + profile = var.profile + region = var.region +} + +resource "random_password" "password" { + length = 16 + special = true +} + +# Check if a secret already exists with this name +data "aws_secretsmanager_secret" "existing_secret" { + name = "db_credentials" + count = "${can(data.aws_secretsmanager_secret.existing_secret.name) ? 1 : 0}" +} + +# Only create a new secret if one does not already exist +resource "aws_secretsmanager_secret" "db_credentials" { + name = "db_credentials" + count = "${data.aws_secretsmanager_secret.existing_secret.name != "db_credentials" ? 1 : 0}" +} + +# Only create a new secret version if one does not already exist +# We can update this approach at a later stage if we wish to rotate the password on a regular basis but because of potental +# side affects, we make it so that we only create a new secret version if one does not already exist +resource "aws_secretsmanager_secret_version" "db_credentials" { + secret_id = aws_secretsmanager_secret.db_credentials[count.index].id + secret_string = jsonencode({ + username = "your_db_username" + password = random_password.password.result + }) + count = "${data.aws_secretsmanager_secret.existing_secret.name != "db_credentials" ? 1 : 0}" +} + +resource "aws_db_instance" "default" { + allocated_storage = var.allocated_storage + engine = "postgres" + engine_version = "13.3" + instance_class = var.instance_class + name = var.database_name + username = jsondecode(aws_secretsmanager_secret_version.db_credentials.secret_string)["username"] + password = jsondecode(aws_secretsmanager_secret_version.db_credentials.secret_string)["password"] + parameter_group_name = "default.postgres13" + skip_final_snapshot = true +} diff --git a/infrastructure/terraform/secrets.tf b/infrastructure/terraform/secrets.tf new file mode 100644 index 00000000..5524c6bf --- /dev/null +++ b/infrastructure/terraform/secrets.tf @@ -0,0 +1 @@ +# This script contains secrets which for the moment, are being stored in aws secrets manager \ No newline at end of file diff --git a/infrastructure/terraform/variables.tf b/infrastructure/terraform/variables.tf new file mode 100644 index 00000000..c62adb6e --- /dev/null +++ b/infrastructure/terraform/variables.tf @@ -0,0 +1,24 @@ +variable "profile" { + description = "AWS profile to use" + type = string +} + +variable "region" { + description = "AWS region" + type = string +} + +variable allocated_storage { + description = "The allocated storage in gigabytes" + type = number +} + +variable instance_class { + description = "The instance type of the RDS instance" + type = string +} + +variable database_name { + description = "The name of the database to create when the DB instance is created" + type = string +} \ No newline at end of file