From 9a1a445c53cb183c5c70f2a1784883caca6ea677 Mon Sep 17 00:00:00 2001 From: RoseSecurity Date: Mon, 13 Oct 2025 11:22:26 -0400 Subject: [PATCH 1/7] feat: support RDS-managed admin password via Secrets Manager Add `manage_admin_user_password` variable to allow AWS RDS to manage the master user password in Secrets Manager. Adjust logic to ensure `admin_password` and `manage_admin_user_password` are mutually exclusive, and update module and locals to support this new option. This enhances security and flexibility for password management. --- src/cluster-regional.tf | 21 +++++++++++---------- src/main.tf | 11 ++++++++--- src/variables.tf | 7 +++++++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/cluster-regional.tf b/src/cluster-regional.tf index f40c025..5d201ed 100644 --- a/src/cluster-regional.tf +++ b/src/cluster-regional.tf @@ -7,16 +7,17 @@ module "aurora_postgres_cluster" { source = "cloudposse/rds-cluster/aws" version = "2.1.1" - cluster_type = "regional" - engine = var.engine - engine_version = var.engine_version - engine_mode = var.engine_mode - cluster_family = var.cluster_family - instance_type = var.instance_type - cluster_size = var.cluster_size - promotion_tier = var.promotion_tier - admin_user = local.admin_user - admin_password = local.admin_password + cluster_type = "regional" + engine = var.engine + engine_version = var.engine_version + engine_mode = var.engine_mode + cluster_family = var.cluster_family + instance_type = var.instance_type + cluster_size = var.cluster_size + promotion_tier = var.promotion_tier + admin_user = local.admin_user + admin_password = var.manage_admin_user_password != null ? null : local.admin_password + manage_admin_user_password = var.manage_admin_user_password db_name = local.database_name publicly_accessible = var.publicly_accessible diff --git a/src/main.tf b/src/main.tf index 8885d87..a5dfda4 100644 --- a/src/main.tf +++ b/src/main.tf @@ -14,9 +14,14 @@ locals { zone_id = module.dns_gbl_delegated.outputs.default_dns_zone_id - admin_user = length(var.admin_user) > 0 ? var.admin_user : join("", random_pet.admin_user[*].id) - admin_password = length(var.admin_password) > 0 ? var.admin_password : join("", random_password.admin_password[*].result) - database_name = length(var.database_name) > 0 ? var.database_name : join("", random_pet.database_name[*].id) + # 1. If manage_admin_user_password is not null, AWS manages the password (admin_password must be null) + # 2. If admin_password is provided, that value is used (manage_admin_user_password must be null) + # 3. If both are null, the module creates a random password + create_password = local.enabled && var.admin_password == "" && var.manage_admin_user_password == null + admin_password = local.create_password ? one(random_password.admin_password[*].result) : var.admin_password + + admin_user = length(var.admin_user) > 0 ? var.admin_user : join("", random_pet.admin_user[*].id) + database_name = length(var.database_name) > 0 ? var.database_name : join("", random_pet.database_name[*].id) cluster_dns_name_prefix = format("%v%v%v%v", module.this.name, module.this.delimiter, var.cluster_name, module.this.delimiter) cluster_dns_name = format("%v%v", local.cluster_dns_name_prefix, var.cluster_dns_name_part) diff --git a/src/variables.tf b/src/variables.tf index e6b8b8f..ba5040a 100644 --- a/src/variables.tf +++ b/src/variables.tf @@ -122,6 +122,13 @@ variable "admin_password" { } } +variable "manage_admin_user_password" { + type = bool + default = false + nullable = false + description = "Set to true to allow RDS to manage the master user password in Secrets Manager. Cannot be set if admin_password is provided" +} + # https://aws.amazon.com/rds/aurora/pricing variable "instance_type" { type = string From 8498a23d60f82396632f837a160a4e2594dc350f Mon Sep 17 00:00:00 2001 From: RoseSecurity <72598486+RoseSecurity@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:27:47 -0400 Subject: [PATCH 2/7] fix: adjust logic for admin password Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/cluster-regional.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cluster-regional.tf b/src/cluster-regional.tf index 5d201ed..292c70c 100644 --- a/src/cluster-regional.tf +++ b/src/cluster-regional.tf @@ -16,7 +16,7 @@ module "aurora_postgres_cluster" { cluster_size = var.cluster_size promotion_tier = var.promotion_tier admin_user = local.admin_user - admin_password = var.manage_admin_user_password != null ? null : local.admin_password + admin_password = var.manage_admin_user_password ? null : local.admin_password manage_admin_user_password = var.manage_admin_user_password db_name = local.database_name From 90511a90dcae84e638c008c7b43cd56fea250463 Mon Sep 17 00:00:00 2001 From: RoseSecurity <72598486+RoseSecurity@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:28:15 -0400 Subject: [PATCH 3/7] fix: update documentation Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/main.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.tf b/src/main.tf index a5dfda4..6c8b028 100644 --- a/src/main.tf +++ b/src/main.tf @@ -14,9 +14,9 @@ locals { zone_id = module.dns_gbl_delegated.outputs.default_dns_zone_id - # 1. If manage_admin_user_password is not null, AWS manages the password (admin_password must be null) - # 2. If admin_password is provided, that value is used (manage_admin_user_password must be null) - # 3. If both are null, the module creates a random password + # 1. If manage_admin_user_password is true, AWS manages the password (admin_password must be empty) + # 2. If admin_password is provided, that value is used (manage_admin_user_password must be false) + # 3. If both are unset/false/empty, the module creates a random password create_password = local.enabled && var.admin_password == "" && var.manage_admin_user_password == null admin_password = local.create_password ? one(random_password.admin_password[*].result) : var.admin_password From 45171ec7cb84f8bbed4567f49f06c8c25581a168 Mon Sep 17 00:00:00 2001 From: RoseSecurity Date: Mon, 13 Oct 2025 11:35:16 -0400 Subject: [PATCH 4/7] chore: update logic --- src/main.tf | 2 +- src/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.tf b/src/main.tf index 6c8b028..32d4a7c 100644 --- a/src/main.tf +++ b/src/main.tf @@ -17,7 +17,7 @@ locals { # 1. If manage_admin_user_password is true, AWS manages the password (admin_password must be empty) # 2. If admin_password is provided, that value is used (manage_admin_user_password must be false) # 3. If both are unset/false/empty, the module creates a random password - create_password = local.enabled && var.admin_password == "" && var.manage_admin_user_password == null + create_password = local.enabled && var.admin_password == "" && !var.manage_admin_user_password admin_password = local.create_password ? one(random_password.admin_password[*].result) : var.admin_password admin_user = length(var.admin_user) > 0 ? var.admin_user : join("", random_pet.admin_user[*].id) diff --git a/src/variables.tf b/src/variables.tf index ba5040a..cb4d8cc 100644 --- a/src/variables.tf +++ b/src/variables.tf @@ -125,8 +125,8 @@ variable "admin_password" { variable "manage_admin_user_password" { type = bool default = false - nullable = false description = "Set to true to allow RDS to manage the master user password in Secrets Manager. Cannot be set if admin_password is provided" + nullable = false } # https://aws.amazon.com/rds/aurora/pricing From 6b38df42514b2b7b943ea998eb644d173881f5dc Mon Sep 17 00:00:00 2001 From: RoseSecurity <72598486+RoseSecurity@users.noreply.github.com> Date: Mon, 13 Oct 2025 12:01:42 -0400 Subject: [PATCH 5/7] fix: update logic Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.tf b/src/main.tf index 32d4a7c..148d8f9 100644 --- a/src/main.tf +++ b/src/main.tf @@ -18,7 +18,7 @@ locals { # 2. If admin_password is provided, that value is used (manage_admin_user_password must be false) # 3. If both are unset/false/empty, the module creates a random password create_password = local.enabled && var.admin_password == "" && !var.manage_admin_user_password - admin_password = local.create_password ? one(random_password.admin_password[*].result) : var.admin_password + admin_password = var.manage_admin_user_password ? null : (local.create_password ? one(random_password.admin_password[*].result) : var.admin_password) admin_user = length(var.admin_user) > 0 ? var.admin_user : join("", random_pet.admin_user[*].id) database_name = length(var.database_name) > 0 ? var.database_name : join("", random_pet.database_name[*].id) From bc42f257f5da7d695ee8217b4e393ce47712b13a Mon Sep 17 00:00:00 2001 From: RoseSecurity Date: Mon, 13 Oct 2025 13:00:41 -0400 Subject: [PATCH 6/7] fix(terraform): use one() instead of join() for pet IDs Replaces join() with one() for random_pet admin_user and database_name IDs to ensure correct value selection. This prevents potential issues with unexpected list handling and aligns with Terraform's best practices for single value extraction. --- src/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.tf b/src/main.tf index 148d8f9..dd2aa15 100644 --- a/src/main.tf +++ b/src/main.tf @@ -20,8 +20,8 @@ locals { create_password = local.enabled && var.admin_password == "" && !var.manage_admin_user_password admin_password = var.manage_admin_user_password ? null : (local.create_password ? one(random_password.admin_password[*].result) : var.admin_password) - admin_user = length(var.admin_user) > 0 ? var.admin_user : join("", random_pet.admin_user[*].id) - database_name = length(var.database_name) > 0 ? var.database_name : join("", random_pet.database_name[*].id) + admin_user = length(var.admin_user) > 0 ? var.admin_user : one(random_pet.admin_user[*].id) + database_name = length(var.database_name) > 0 ? var.database_name : one(random_pet.database_name[*].id) cluster_dns_name_prefix = format("%v%v%v%v", module.this.name, module.this.delimiter, var.cluster_name, module.this.delimiter) cluster_dns_name = format("%v%v", local.cluster_dns_name_prefix, var.cluster_dns_name_part) From 8eedabd92924b1bb229f3da29f5143db869dbd28 Mon Sep 17 00:00:00 2001 From: RoseSecurity <72598486+RoseSecurity@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:32:45 -0400 Subject: [PATCH 7/7] fix: deduplicate logic Co-authored-by: Igor Rodionov --- src/cluster-regional.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cluster-regional.tf b/src/cluster-regional.tf index 292c70c..080e7e8 100644 --- a/src/cluster-regional.tf +++ b/src/cluster-regional.tf @@ -16,7 +16,7 @@ module "aurora_postgres_cluster" { cluster_size = var.cluster_size promotion_tier = var.promotion_tier admin_user = local.admin_user - admin_password = var.manage_admin_user_password ? null : local.admin_password + admin_password = local.admin_password manage_admin_user_password = var.manage_admin_user_password db_name = local.database_name