Skip to content

Commit

Permalink
feat: Secretsmanager secret rotation for master user password (#433)
Browse files Browse the repository at this point in the history
  • Loading branch information
magreenbaum authored Mar 5, 2024
1 parent 17ddf72 commit ae752de
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 0 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ No modules.
| [aws_rds_cluster_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | resource |
| [aws_rds_cluster_parameter_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource |
| [aws_rds_cluster_role_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_role_association) | resource |
| [aws_secretsmanager_secret_rotation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_rotation) | resource |
| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_iam_policy_document.monitoring_rds_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
Expand Down Expand Up @@ -341,7 +342,12 @@ No modules.
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
Expand Down Expand Up @@ -401,6 +407,7 @@ No modules.
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <a name="output_db_subnet_group_name"></a> [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name |
Expand Down
1 change: 1 addition & 0 deletions examples/multi-az/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ No inputs.
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <a name="output_db_subnet_group_name"></a> [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name |
Expand Down
3 changes: 3 additions & 0 deletions examples/multi-az/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ module "aurora" {
vpc_id = module.vpc.vpc_id
db_subnet_group_name = module.vpc.database_subnet_group_name

manage_master_user_password_rotation = true
master_user_password_rotation_automatically_after_days = 30

enabled_cloudwatch_logs_exports = ["postgresql"]

# Multi-AZ
Expand Down
9 changes: 9 additions & 0 deletions examples/multi-az/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,12 @@ output "db_cluster_cloudwatch_log_groups" {
description = "Map of CloudWatch log groups created and their attributes"
value = module.aurora.db_cluster_cloudwatch_log_groups
}

################################################################################
# Managed Secret Rotation
################################################################################

output "db_cluster_secretsmanager_secret_rotation_enabled" {
description = "Specifies whether automatic rotation is enabled for the secret"
value = module.aurora.db_cluster_secretsmanager_secret_rotation_enabled
}
1 change: 1 addition & 0 deletions examples/mysql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ No inputs.
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <a name="output_db_subnet_group_name"></a> [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name |
Expand Down
3 changes: 3 additions & 0 deletions examples/mysql/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ module "aurora" {
create_db_cluster_activity_stream = true
db_cluster_activity_stream_kms_key_id = module.kms.key_id

manage_master_user_password_rotation = true
master_user_password_rotation_schedule_expression = "rate(15 days)"

# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/DBActivityStreams.Overview.html#DBActivityStreams.Overview.sync-mode
db_cluster_activity_stream_mode = "async"

Expand Down
9 changes: 9 additions & 0 deletions examples/mysql/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,12 @@ output "db_cluster_activity_stream_kinesis_stream_name" {
description = "The name of the Amazon Kinesis data stream to be used for the database activity stream"
value = module.aurora.db_cluster_activity_stream_kinesis_stream_name
}

################################################################################
# Managed Secret Rotation
################################################################################

output "db_cluster_secretsmanager_secret_rotation_enabled" {
description = "Specifies whether automatic rotation is enabled for the secret"
value = module.aurora.db_cluster_secretsmanager_secret_rotation_enabled
}
17 changes: 17 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -436,3 +436,20 @@ resource "aws_rds_cluster_activity_stream" "this" {

depends_on = [aws_rds_cluster_instance.this]
}

################################################################################
# Managed Secret Rotation
################################################################################

resource "aws_secretsmanager_secret_rotation" "this" {
count = local.create && var.manage_master_user_password && var.manage_master_user_password_rotation ? 1 : 0

secret_id = aws_rds_cluster.this[0].master_user_secret[0].secret_arn
rotate_immediately = var.master_user_password_rotate_immediately

rotation_rules {
automatically_after_days = var.master_user_password_rotation_automatically_after_days
duration = var.master_user_password_rotation_duration
schedule_expression = var.master_user_password_rotation_schedule_expression
}
}
9 changes: 9 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,12 @@ output "db_cluster_activity_stream_kinesis_stream_name" {
description = "The name of the Amazon Kinesis data stream to be used for the database activity stream"
value = try(aws_rds_cluster_activity_stream.this[0].kinesis_stream_name, null)
}

################################################################################
# Managed Secret Rotation
################################################################################

output "db_cluster_secretsmanager_secret_rotation_enabled" {
description = "Specifies whether automatic rotation is enabled for the secret"
value = try(aws_secretsmanager_secret_rotation.this[0].rotation_enabled, null)
}
34 changes: 34 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -729,3 +729,37 @@ variable "engine_native_audit_fields_included" {
type = bool
default = false
}

################################################################################
# Managed Secret Rotation
################################################################################

variable "manage_master_user_password_rotation" {
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."
type = bool
default = false
}

variable "master_user_password_rotate_immediately" {
description = "Specifies whether to rotate the secret immediately or wait until the next scheduled rotation window."
type = bool
default = null
}

variable "master_user_password_rotation_automatically_after_days" {
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"
type = number
default = null
}

variable "master_user_password_rotation_duration" {
description = "The length of the rotation window in hours. For example, 3h for a three hour window."
type = string
default = null
}

variable "master_user_password_rotation_schedule_expression" {
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"
type = string
default = null
}

0 comments on commit ae752de

Please sign in to comment.