21/05/2023 - AWS, TERRAFORM
In this example we are going to create an AWS RDS for Postgres with Terraform. It will be publicly accessible from our local machine for testing purposes. In a real world scenario, you should provision AWS RDS instances in private subnets to shield them from direct internet traffic. You would have an application running in a public subnet and accessing to RDS in private subnet.
Make sure your IAM group or user has iam:*,ec2:*,rds:*,rds:*
permissions. However, ideally you should use bare minimum permissions. You can use tools like iamlive to identify exact permissions.
export TF_VAR_username=SecretUsername
export TF_VAR_password=SecretPassword
[default]
region = eu-west-1
output = json
[profile development]
source_profile = default
role_session_name = github-actions
role_arn = arn:aws:iam::1234567890:role/devops-provisioner
[default]
aws_access_key_id = QWERTYUIO12345678
aws_secret_access_key = sdfg23456/DFGHJKL9876543+plv/dft543
blog
└── terraform
└── development
├── aws_db_instance.tf
├── aws_security_group.tf
├── main.tf
├── outputs.tf
├── providers.tf
└── variables.tf
variable "username" {
description = "The master username for the database."
type = string
sensitive = true
}
variable "password" {
description = "The master password for the database."
type = string
sensitive = true
}
terraform {
required_version = "~> 1.4.4"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.30.0"
}
}
}
provider "aws" {
profile = "development"
region = "eu-west-1"
}
resource "aws_security_group" "postgres" {
name = "postgres-security-group"
description = "Security group for Postgres database"
ingress {
protocol = "tcp"
from_port = 5432
to_port = 5432
cidr_blocks = ["0.0.0.0/0"]
}
egress {
protocol = -1
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_db_instance" "blog" {
allocated_storage = 5
storage_type = "gp2"
instance_class = "db.t2.micro"
identifier = "blog"
engine = "postgres"
engine_version = "12.10"
parameter_group_name = "default.postgres12"
db_name = "blog"
username = var.username
password = var.password
vpc_security_group_ids = [aws_security_group.postgres.id]
publicly_accessible = true # Only for testing!
skip_final_snapshot = true
}
output "blog_database" {
value = aws_db_instance.blog.endpoint
}
Just bare in mind that creating RDS instance takes a bit of time.
$ terraform apply
...
aws_db_instance.blog: Creation complete after 3m37s [id=blog]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
blog_database = "blog.qwert12345.eu-west-1.rds.amazonaws.com:5432"
postgres://SecretUsername:SecretPassword@blog.qwert12345.eu-west-1.rds.amazonaws.com:5432/blog
postgres://SecretUsername:SecretPassword@blog.qwert12345.eu-west-1.rds.amazonaws.com:5432/blog?sslmode=disable