diff --git a/infra/terraform/rds.tf b/infra/terraform/rds.tf index 5373006..148fe93 100644 --- a/infra/terraform/rds.tf +++ b/infra/terraform/rds.tf @@ -28,6 +28,21 @@ resource "aws_db_subnet_group" "main" { subnet_ids = aws_subnet.private[*].id } +# Custom parameter group so we can flip rds.force_ssl on. The default +# parameter group is read-only. +resource "aws_db_parameter_group" "main" { + name = "${local.name}-postgres17" + family = "postgres17" + + parameter { + name = "rds.force_ssl" + value = "1" + # Static parameter — requires a reboot to take effect. RDS handles + # the reboot during the next maintenance window or you can force it. + apply_method = "pending-reboot" + } +} + resource "aws_db_instance" "main" { identifier = "${local.name}-postgres" engine = "postgres" @@ -39,9 +54,10 @@ resource "aws_db_instance" "main" { storage_type = "gp3" storage_encrypted = true - db_name = var.postgres_db_name - username = var.postgres_username - password = random_password.postgres.result + db_name = var.postgres_db_name + username = var.postgres_username + password = random_password.postgres.result + parameter_group_name = aws_db_parameter_group.main.name db_subnet_group_name = aws_db_subnet_group.main.name vpc_security_group_ids = [aws_security_group.rds.id] diff --git a/infra/terraform/secrets.tf b/infra/terraform/secrets.tf index 51044ff..d32c591 100644 --- a/infra/terraform/secrets.tf +++ b/infra/terraform/secrets.tf @@ -25,8 +25,11 @@ resource "aws_secretsmanager_secret" "postgres_url" { resource "aws_secretsmanager_secret_version" "postgres_url" { secret_id = aws_secretsmanager_secret.postgres_url.id + # sslmode=require pairs with rds.force_ssl=1 in the parameter group: + # the client refuses plaintext, the server refuses plaintext, no + # gap between the two. secret_string = format( - "postgresql+psycopg2://%s:%s@%s:%d/%s", + "postgresql+psycopg2://%s:%s@%s:%d/%s?sslmode=require", var.postgres_username, random_password.postgres.result, aws_db_instance.main.address,