Skip to content

Commit ae752de

Browse files
authored
feat: Secretsmanager secret rotation for master user password (terraform-aws-modules#433)
1 parent 17ddf72 commit ae752de

File tree

10 files changed

+93
-0
lines changed

10 files changed

+93
-0
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ No modules.
253253
| [aws_rds_cluster_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | resource |
254254
| [aws_rds_cluster_parameter_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource |
255255
| [aws_rds_cluster_role_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_role_association) | resource |
256+
| [aws_secretsmanager_secret_rotation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_rotation) | resource |
256257
| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
257258
| [aws_security_group_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
258259
| [aws_iam_policy_document.monitoring_rds_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
@@ -341,7 +342,12 @@ No modules.
341342
| <a name="input_is_primary_cluster"></a> [is\_primary\_cluster](#input\_is\_primary\_cluster) | Determines whether cluster is primary cluster with writer instance (set to `false` for global cluster and replica clusters) | `bool` | `true` | no |
342343
| <a name="input_kms_key_id"></a> [kms\_key\_id](#input\_kms\_key\_id) | The ARN for the KMS encryption key. When specifying `kms_key_id`, `storage_encrypted` needs to be set to `true` | `string` | `null` | no |
343344
| <a name="input_manage_master_user_password"></a> [manage\_master\_user\_password](#input\_manage\_master\_user\_password) | Set to true to allow RDS to manage the master user password in Secrets Manager. Cannot be set if `master_password` is provided | `bool` | `true` | no |
345+
| <a name="input_manage_master_user_password_rotation"></a> [manage\_master\_user\_password\_rotation](#input\_manage\_master\_user\_password\_rotation) | Whether to manage the master user password rotation. Setting this value to false after previously having been set to true will disable automatic rotation. | `bool` | `false` | no |
344346
| <a name="input_master_password"></a> [master\_password](#input\_master\_password) | Password for the master DB user. Note that this may show up in logs, and it will be stored in the state file. Required unless `manage_master_user_password` is set to `true` or unless `snapshot_identifier` or `replication_source_identifier` is provided or unless a `global_cluster_identifier` is provided when the cluster is the secondary cluster of a global database | `string` | `null` | no |
347+
| <a name="input_master_user_password_rotate_immediately"></a> [master\_user\_password\_rotate\_immediately](#input\_master\_user\_password\_rotate\_immediately) | Specifies whether to rotate the secret immediately or wait until the next scheduled rotation window. | `bool` | `null` | no |
348+
| <a name="input_master_user_password_rotation_automatically_after_days"></a> [master\_user\_password\_rotation\_automatically\_after\_days](#input\_master\_user\_password\_rotation\_automatically\_after\_days) | Specifies the number of days between automatic scheduled rotations of the secret. Either `master_user_password_rotation_automatically_after_days` or `master_user_password_rotation_schedule_expression` must be specified | `number` | `null` | no |
349+
| <a name="input_master_user_password_rotation_duration"></a> [master\_user\_password\_rotation\_duration](#input\_master\_user\_password\_rotation\_duration) | The length of the rotation window in hours. For example, 3h for a three hour window. | `string` | `null` | no |
350+
| <a name="input_master_user_password_rotation_schedule_expression"></a> [master\_user\_password\_rotation\_schedule\_expression](#input\_master\_user\_password\_rotation\_schedule\_expression) | A cron() or rate() expression that defines the schedule for rotating your secret. Either `master_user_password_rotation_automatically_after_days` or `master_user_password_rotation_schedule_expression` must be specified | `string` | `null` | no |
345351
| <a name="input_master_user_secret_kms_key_id"></a> [master\_user\_secret\_kms\_key\_id](#input\_master\_user\_secret\_kms\_key\_id) | The Amazon Web Services KMS key identifier is the key ARN, key ID, alias ARN, or alias name for the KMS key | `string` | `null` | no |
346352
| <a name="input_master_username"></a> [master\_username](#input\_master\_username) | Username for the master DB user. Required unless `snapshot_identifier` or `replication_source_identifier` is provided or unless a `global_cluster_identifier` is provided when the cluster is the secondary cluster of a global database | `string` | `null` | no |
347353
| <a name="input_monitoring_interval"></a> [monitoring\_interval](#input\_monitoring\_interval) | The interval, in seconds, between points when Enhanced Monitoring metrics are collected for instances. Set to `0` to disable. Default is `0` | `number` | `0` | no |
@@ -401,6 +407,7 @@ No modules.
401407
| <a name="output_db_cluster_cloudwatch_log_groups"></a> [db\_cluster\_cloudwatch\_log\_groups](#output\_db\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes |
402408
| <a name="output_db_cluster_parameter_group_arn"></a> [db\_cluster\_parameter\_group\_arn](#output\_db\_cluster\_parameter\_group\_arn) | The ARN of the DB cluster parameter group created |
403409
| <a name="output_db_cluster_parameter_group_id"></a> [db\_cluster\_parameter\_group\_id](#output\_db\_cluster\_parameter\_group\_id) | The ID of the DB cluster parameter group created |
410+
| <a name="output_db_cluster_secretsmanager_secret_rotation_enabled"></a> [db\_cluster\_secretsmanager\_secret\_rotation\_enabled](#output\_db\_cluster\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret |
404411
| <a name="output_db_parameter_group_arn"></a> [db\_parameter\_group\_arn](#output\_db\_parameter\_group\_arn) | The ARN of the DB parameter group created |
405412
| <a name="output_db_parameter_group_id"></a> [db\_parameter\_group\_id](#output\_db\_parameter\_group\_id) | The ID of the DB parameter group created |
406413
| <a name="output_db_subnet_group_name"></a> [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name |

examples/multi-az/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ No inputs.
6666
| <a name="output_db_cluster_cloudwatch_log_groups"></a> [db\_cluster\_cloudwatch\_log\_groups](#output\_db\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes |
6767
| <a name="output_db_cluster_parameter_group_arn"></a> [db\_cluster\_parameter\_group\_arn](#output\_db\_cluster\_parameter\_group\_arn) | The ARN of the DB cluster parameter group created |
6868
| <a name="output_db_cluster_parameter_group_id"></a> [db\_cluster\_parameter\_group\_id](#output\_db\_cluster\_parameter\_group\_id) | The ID of the DB cluster parameter group created |
69+
| <a name="output_db_cluster_secretsmanager_secret_rotation_enabled"></a> [db\_cluster\_secretsmanager\_secret\_rotation\_enabled](#output\_db\_cluster\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret |
6970
| <a name="output_db_parameter_group_arn"></a> [db\_parameter\_group\_arn](#output\_db\_parameter\_group\_arn) | The ARN of the DB parameter group created |
7071
| <a name="output_db_parameter_group_id"></a> [db\_parameter\_group\_id](#output\_db\_parameter\_group\_id) | The ID of the DB parameter group created |
7172
| <a name="output_db_subnet_group_name"></a> [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name |

examples/multi-az/main.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ module "aurora" {
3333
vpc_id = module.vpc.vpc_id
3434
db_subnet_group_name = module.vpc.database_subnet_group_name
3535

36+
manage_master_user_password_rotation = true
37+
master_user_password_rotation_automatically_after_days = 30
38+
3639
enabled_cloudwatch_logs_exports = ["postgresql"]
3740

3841
# Multi-AZ

examples/multi-az/outputs.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,12 @@ output "db_cluster_cloudwatch_log_groups" {
157157
description = "Map of CloudWatch log groups created and their attributes"
158158
value = module.aurora.db_cluster_cloudwatch_log_groups
159159
}
160+
161+
################################################################################
162+
# Managed Secret Rotation
163+
################################################################################
164+
165+
output "db_cluster_secretsmanager_secret_rotation_enabled" {
166+
description = "Specifies whether automatic rotation is enabled for the secret"
167+
value = module.aurora.db_cluster_secretsmanager_secret_rotation_enabled
168+
}

examples/mysql/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ No inputs.
6969
| <a name="output_db_cluster_cloudwatch_log_groups"></a> [db\_cluster\_cloudwatch\_log\_groups](#output\_db\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes |
7070
| <a name="output_db_cluster_parameter_group_arn"></a> [db\_cluster\_parameter\_group\_arn](#output\_db\_cluster\_parameter\_group\_arn) | The ARN of the DB cluster parameter group created |
7171
| <a name="output_db_cluster_parameter_group_id"></a> [db\_cluster\_parameter\_group\_id](#output\_db\_cluster\_parameter\_group\_id) | The ID of the DB cluster parameter group created |
72+
| <a name="output_db_cluster_secretsmanager_secret_rotation_enabled"></a> [db\_cluster\_secretsmanager\_secret\_rotation\_enabled](#output\_db\_cluster\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret |
7273
| <a name="output_db_parameter_group_arn"></a> [db\_parameter\_group\_arn](#output\_db\_parameter\_group\_arn) | The ARN of the DB parameter group created |
7374
| <a name="output_db_parameter_group_id"></a> [db\_parameter\_group\_id](#output\_db\_parameter\_group\_id) | The ID of the DB parameter group created |
7475
| <a name="output_db_subnet_group_name"></a> [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name |

examples/mysql/main.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ module "aurora" {
151151
create_db_cluster_activity_stream = true
152152
db_cluster_activity_stream_kms_key_id = module.kms.key_id
153153

154+
manage_master_user_password_rotation = true
155+
master_user_password_rotation_schedule_expression = "rate(15 days)"
156+
154157
# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/DBActivityStreams.Overview.html#DBActivityStreams.Overview.sync-mode
155158
db_cluster_activity_stream_mode = "async"
156159

examples/mysql/outputs.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,12 @@ output "db_cluster_activity_stream_kinesis_stream_name" {
166166
description = "The name of the Amazon Kinesis data stream to be used for the database activity stream"
167167
value = module.aurora.db_cluster_activity_stream_kinesis_stream_name
168168
}
169+
170+
################################################################################
171+
# Managed Secret Rotation
172+
################################################################################
173+
174+
output "db_cluster_secretsmanager_secret_rotation_enabled" {
175+
description = "Specifies whether automatic rotation is enabled for the secret"
176+
value = module.aurora.db_cluster_secretsmanager_secret_rotation_enabled
177+
}

main.tf

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,20 @@ resource "aws_rds_cluster_activity_stream" "this" {
436436

437437
depends_on = [aws_rds_cluster_instance.this]
438438
}
439+
440+
################################################################################
441+
# Managed Secret Rotation
442+
################################################################################
443+
444+
resource "aws_secretsmanager_secret_rotation" "this" {
445+
count = local.create && var.manage_master_user_password && var.manage_master_user_password_rotation ? 1 : 0
446+
447+
secret_id = aws_rds_cluster.this[0].master_user_secret[0].secret_arn
448+
rotate_immediately = var.master_user_password_rotate_immediately
449+
450+
rotation_rules {
451+
automatically_after_days = var.master_user_password_rotation_automatically_after_days
452+
duration = var.master_user_password_rotation_duration
453+
schedule_expression = var.master_user_password_rotation_schedule_expression
454+
}
455+
}

outputs.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,12 @@ output "db_cluster_activity_stream_kinesis_stream_name" {
179179
description = "The name of the Amazon Kinesis data stream to be used for the database activity stream"
180180
value = try(aws_rds_cluster_activity_stream.this[0].kinesis_stream_name, null)
181181
}
182+
183+
################################################################################
184+
# Managed Secret Rotation
185+
################################################################################
186+
187+
output "db_cluster_secretsmanager_secret_rotation_enabled" {
188+
description = "Specifies whether automatic rotation is enabled for the secret"
189+
value = try(aws_secretsmanager_secret_rotation.this[0].rotation_enabled, null)
190+
}

variables.tf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,3 +729,37 @@ variable "engine_native_audit_fields_included" {
729729
type = bool
730730
default = false
731731
}
732+
733+
################################################################################
734+
# Managed Secret Rotation
735+
################################################################################
736+
737+
variable "manage_master_user_password_rotation" {
738+
description = "Whether to manage the master user password rotation. Setting this value to false after previously having been set to true will disable automatic rotation."
739+
type = bool
740+
default = false
741+
}
742+
743+
variable "master_user_password_rotate_immediately" {
744+
description = "Specifies whether to rotate the secret immediately or wait until the next scheduled rotation window."
745+
type = bool
746+
default = null
747+
}
748+
749+
variable "master_user_password_rotation_automatically_after_days" {
750+
description = "Specifies the number of days between automatic scheduled rotations of the secret. Either `master_user_password_rotation_automatically_after_days` or `master_user_password_rotation_schedule_expression` must be specified"
751+
type = number
752+
default = null
753+
}
754+
755+
variable "master_user_password_rotation_duration" {
756+
description = "The length of the rotation window in hours. For example, 3h for a three hour window."
757+
type = string
758+
default = null
759+
}
760+
761+
variable "master_user_password_rotation_schedule_expression" {
762+
description = "A cron() or rate() expression that defines the schedule for rotating your secret. Either `master_user_password_rotation_automatically_after_days` or `master_user_password_rotation_schedule_expression` must be specified"
763+
type = string
764+
default = null
765+
}

0 commit comments

Comments
 (0)