From 93c85efddeac23ce1dbf96f7e53d8326bca71e25 Mon Sep 17 00:00:00 2001 From: Melissa Greenbaum <69476188+magreenbaum@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:18:18 -0500 Subject: [PATCH] feat: Secretsmanager secret rotation for master user password (#537) Co-authored-by: Anton Babenko Co-authored-by: magreenbaum --- README.md | 8 ++++- examples/blue-green-deployment/README.md | 4 +-- examples/blue-green-deployment/versions.tf | 2 +- examples/complete-mssql/README.md | 4 +-- examples/complete-mssql/versions.tf | 2 +- examples/complete-mysql/README.md | 4 +-- examples/complete-mysql/versions.tf | 2 +- examples/complete-oracle/README.md | 4 +-- examples/complete-oracle/versions.tf | 2 +- examples/complete-postgres/README.md | 6 ++-- examples/complete-postgres/main.tf | 6 ++++ examples/complete-postgres/outputs.tf | 10 ++++++ examples/complete-postgres/versions.tf | 2 +- .../cross-region-replica-postgres/README.md | 4 +-- .../cross-region-replica-postgres/versions.tf | 2 +- examples/enhanced-monitoring/README.md | 4 +-- examples/enhanced-monitoring/versions.tf | 2 +- examples/groups/README.md | 2 +- examples/groups/versions.tf | 2 +- examples/replica-mysql/README.md | 4 +-- examples/replica-mysql/versions.tf | 2 +- examples/replica-postgres/README.md | 4 +-- examples/replica-postgres/versions.tf | 2 +- examples/role-association-postgres/README.md | 4 +-- .../role-association-postgres/versions.tf | 2 +- examples/s3-import-mysql/README.md | 4 +-- examples/s3-import-mysql/versions.tf | 2 +- main.tf | 6 ++++ modules/db_instance/README.md | 11 ++++-- modules/db_instance/main.tf | 17 ++++++++++ modules/db_instance/outputs.tf | 9 +++++ modules/db_instance/variables.tf | 34 +++++++++++++++++++ modules/db_instance/versions.tf | 2 +- .../versions.tf | 2 +- .../db_instance_role_association/README.md | 4 +-- .../db_instance_role_association/versions.tf | 2 +- modules/db_option_group/README.md | 4 +-- modules/db_option_group/versions.tf | 2 +- modules/db_parameter_group/README.md | 4 +-- modules/db_parameter_group/versions.tf | 2 +- modules/db_subnet_group/README.md | 4 +-- modules/db_subnet_group/versions.tf | 2 +- outputs.tf | 9 +++++ variables.tf | 34 +++++++++++++++++++ versions.tf | 2 +- 45 files changed, 193 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index fb955332..c6177f63 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ Users have the ability to: | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers @@ -282,6 +282,11 @@ No resources. | [maintenance\_window](#input\_maintenance\_window) | The window to perform maintenance in. Syntax: 'ddd:hh24:mi-ddd:hh24:mi'. Eg: 'Mon:00:00-Mon:03:00' | `string` | `null` | no | | [major\_engine\_version](#input\_major\_engine\_version) | Specifies the major version of the engine that this option group should be associated with | `string` | `null` | no | | [manage\_master\_user\_password](#input\_manage\_master\_user\_password) | Set to true to allow RDS to manage the master user password in Secrets Manager | `bool` | `true` | no | +| [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 | +| [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 | +| [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 automatically\_after\_days or schedule\_expression must be specified. | `number` | `null` | no | +| [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 | +| [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 automatically\_after\_days or schedule\_expression must be specified. | `string` | `null` | no | | [master\_user\_secret\_kms\_key\_id](#input\_master\_user\_secret\_kms\_key\_id) | The key ARN, key ID, alias ARN or alias name for the KMS key to encrypt the master user password secret in Secrets Manager.
If not specified, the default KMS key for your Amazon Web Services account is used. | `string` | `null` | no | | [max\_allocated\_storage](#input\_max\_allocated\_storage) | Specifies the value for Storage Autoscaling | `number` | `0` | no | | [monitoring\_interval](#input\_monitoring\_interval) | The interval, in seconds, between points when Enhanced Monitoring metrics are collected for the DB instance. To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60 | `number` | `0` | no | @@ -346,6 +351,7 @@ No resources. | [db\_instance\_port](#output\_db\_instance\_port) | The database port | | [db\_instance\_resource\_id](#output\_db\_instance\_resource\_id) | The RDS Resource ID of this instance | | [db\_instance\_role\_associations](#output\_db\_instance\_role\_associations) | A map of DB Instance Identifiers and IAM Role ARNs separated by a comma | +| [db\_instance\_secretsmanager\_secret\_rotation\_enabled](#output\_db\_instance\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret | | [db\_instance\_status](#output\_db\_instance\_status) | The RDS instance status | | [db\_instance\_username](#output\_db\_instance\_username) | The master username for the database | | [db\_listener\_endpoint](#output\_db\_listener\_endpoint) | Specifies the listener connection endpoint for SQL Server Always On | diff --git a/examples/blue-green-deployment/README.md b/examples/blue-green-deployment/README.md index 5695af7d..ecb73d5e 100644 --- a/examples/blue-green-deployment/README.md +++ b/examples/blue-green-deployment/README.md @@ -27,13 +27,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/blue-green-deployment/versions.tf b/examples/blue-green-deployment/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/blue-green-deployment/versions.tf +++ b/examples/blue-green-deployment/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/complete-mssql/README.md b/examples/complete-mssql/README.md index d09af5a8..1eb795dc 100644 --- a/examples/complete-mssql/README.md +++ b/examples/complete-mssql/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/complete-mssql/versions.tf b/examples/complete-mssql/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/complete-mssql/versions.tf +++ b/examples/complete-mssql/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/complete-mysql/README.md b/examples/complete-mysql/README.md index cf97ba6b..b839444b 100644 --- a/examples/complete-mysql/README.md +++ b/examples/complete-mysql/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/complete-mysql/versions.tf b/examples/complete-mysql/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/complete-mysql/versions.tf +++ b/examples/complete-mysql/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/complete-oracle/README.md b/examples/complete-oracle/README.md index 4141f674..8fa07b7e 100644 --- a/examples/complete-oracle/README.md +++ b/examples/complete-oracle/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/complete-oracle/versions.tf b/examples/complete-oracle/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/complete-oracle/versions.tf +++ b/examples/complete-oracle/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/complete-postgres/README.md b/examples/complete-postgres/README.md index b9f0c637..2f31452b 100644 --- a/examples/complete-postgres/README.md +++ b/examples/complete-postgres/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules @@ -72,6 +72,7 @@ No inputs. | [db\_default\_master\_user\_secret\_arn](#output\_db\_default\_master\_user\_secret\_arn) | The ARN of the master user secret (Only available when manage\_master\_user\_password is set to true) | | [db\_default\_parameter\_group\_arn](#output\_db\_default\_parameter\_group\_arn) | The ARN of the db parameter group | | [db\_default\_parameter\_group\_id](#output\_db\_default\_parameter\_group\_id) | The db parameter group id | +| [db\_default\_secretsmanager\_secret\_rotation\_enabled](#output\_db\_default\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret | | [db\_default\_subnet\_group\_arn](#output\_db\_default\_subnet\_group\_arn) | The ARN of the db subnet group | | [db\_default\_subnet\_group\_id](#output\_db\_default\_subnet\_group\_id) | The db subnet group name | | [db\_enhanced\_monitoring\_iam\_role\_arn](#output\_db\_enhanced\_monitoring\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the monitoring role | @@ -88,6 +89,7 @@ No inputs. | [db\_instance\_name](#output\_db\_instance\_name) | The database name | | [db\_instance\_port](#output\_db\_instance\_port) | The database port | | [db\_instance\_resource\_id](#output\_db\_instance\_resource\_id) | The RDS Resource ID of this instance | +| [db\_instance\_secretsmanager\_secret\_rotation\_enabled](#output\_db\_instance\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret | | [db\_instance\_status](#output\_db\_instance\_status) | The RDS instance status | | [db\_instance\_username](#output\_db\_instance\_username) | The master username for the database | | [db\_parameter\_group\_arn](#output\_db\_parameter\_group\_arn) | The ARN of the db parameter group | diff --git a/examples/complete-postgres/main.tf b/examples/complete-postgres/main.tf index 8e9967ca..0b8ba8e2 100644 --- a/examples/complete-postgres/main.tf +++ b/examples/complete-postgres/main.tf @@ -46,6 +46,12 @@ module "db" { username = "complete_postgresql" port = 5432 + # setting manage_master_user_password_rotation to false after it + # has been set to true previously disables automatic rotation + manage_master_user_password_rotation = true + master_user_password_rotate_immediately = false + master_user_password_rotation_schedule_expression = "rate(15 days)" + multi_az = true db_subnet_group_name = module.vpc.database_subnet_group vpc_security_group_ids = [module.security_group.security_group_id] diff --git a/examples/complete-postgres/outputs.tf b/examples/complete-postgres/outputs.tf index b43f8aae..2b7c3027 100644 --- a/examples/complete-postgres/outputs.tf +++ b/examples/complete-postgres/outputs.tf @@ -99,6 +99,11 @@ output "db_instance_master_user_secret_arn" { value = module.db.db_instance_master_user_secret_arn } +output "db_instance_secretsmanager_secret_rotation_enabled" { + description = "Specifies whether automatic rotation is enabled for the secret" + value = module.db.db_instance_secretsmanager_secret_rotation_enabled +} + # Default output "db_default_instance_address" { description = "The address of the RDS instance" @@ -195,3 +200,8 @@ output "db_default_master_user_secret_arn" { description = "The ARN of the master user secret (Only available when manage_master_user_password is set to true)" value = module.db_default.db_instance_master_user_secret_arn } + +output "db_default_secretsmanager_secret_rotation_enabled" { + description = "Specifies whether automatic rotation is enabled for the secret" + value = module.db_default.db_instance_secretsmanager_secret_rotation_enabled +} diff --git a/examples/complete-postgres/versions.tf b/examples/complete-postgres/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/complete-postgres/versions.tf +++ b/examples/complete-postgres/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/cross-region-replica-postgres/README.md b/examples/cross-region-replica-postgres/README.md index 40bb6c1b..1c82047a 100644 --- a/examples/cross-region-replica-postgres/README.md +++ b/examples/cross-region-replica-postgres/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/cross-region-replica-postgres/versions.tf b/examples/cross-region-replica-postgres/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/cross-region-replica-postgres/versions.tf +++ b/examples/cross-region-replica-postgres/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/enhanced-monitoring/README.md b/examples/enhanced-monitoring/README.md index b015deab..69cffb64 100644 --- a/examples/enhanced-monitoring/README.md +++ b/examples/enhanced-monitoring/README.md @@ -22,13 +22,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/enhanced-monitoring/versions.tf b/examples/enhanced-monitoring/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/enhanced-monitoring/versions.tf +++ b/examples/enhanced-monitoring/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/groups/README.md b/examples/groups/README.md index eaa915ae..bd36dc72 100644 --- a/examples/groups/README.md +++ b/examples/groups/README.md @@ -20,7 +20,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers diff --git a/examples/groups/versions.tf b/examples/groups/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/groups/versions.tf +++ b/examples/groups/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/replica-mysql/README.md b/examples/replica-mysql/README.md index 3ec8a0eb..d8fbd865 100644 --- a/examples/replica-mysql/README.md +++ b/examples/replica-mysql/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/replica-mysql/versions.tf b/examples/replica-mysql/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/replica-mysql/versions.tf +++ b/examples/replica-mysql/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/replica-postgres/README.md b/examples/replica-postgres/README.md index 9e834301..ec3b98b2 100644 --- a/examples/replica-postgres/README.md +++ b/examples/replica-postgres/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/replica-postgres/versions.tf b/examples/replica-postgres/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/replica-postgres/versions.tf +++ b/examples/replica-postgres/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/role-association-postgres/README.md b/examples/role-association-postgres/README.md index f37eeb73..b5721a46 100644 --- a/examples/role-association-postgres/README.md +++ b/examples/role-association-postgres/README.md @@ -10,13 +10,13 @@ Further database configurations for creating extension and invoking from postgre | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/role-association-postgres/versions.tf b/examples/role-association-postgres/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/role-association-postgres/versions.tf +++ b/examples/role-association-postgres/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/examples/s3-import-mysql/README.md b/examples/s3-import-mysql/README.md index b15d19dd..b125d8c3 100644 --- a/examples/s3-import-mysql/README.md +++ b/examples/s3-import-mysql/README.md @@ -49,13 +49,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/examples/s3-import-mysql/versions.tf b/examples/s3-import-mysql/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/examples/s3-import-mysql/versions.tf +++ b/examples/s3-import-mysql/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/main.tf b/main.tf index 522d6315..7e04815d 100644 --- a/main.tf +++ b/main.tf @@ -83,6 +83,12 @@ module "db_instance" { manage_master_user_password = var.manage_master_user_password master_user_secret_kms_key_id = var.master_user_secret_kms_key_id + manage_master_user_password_rotation = var.manage_master_user_password_rotation + master_user_password_rotate_immediately = var.master_user_password_rotate_immediately + master_user_password_rotation_automatically_after_days = var.master_user_password_rotation_automatically_after_days + master_user_password_rotation_duration = var.master_user_password_rotation_duration + master_user_password_rotation_schedule_expression = var.master_user_password_rotation_schedule_expression + vpc_security_group_ids = var.vpc_security_group_ids db_subnet_group_name = local.db_subnet_group_name parameter_group_name = local.parameter_group_name_id diff --git a/modules/db_instance/README.md b/modules/db_instance/README.md index 31e4dcfc..860e318e 100644 --- a/modules/db_instance/README.md +++ b/modules/db_instance/README.md @@ -6,14 +6,14 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | | [random](#requirement\_random) | >= 3.1 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | | [random](#provider\_random) | >= 3.1 | ## Modules @@ -28,6 +28,7 @@ No modules. | [aws_db_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance) | resource | | [aws_iam_role.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy_attachment.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_secretsmanager_secret_rotation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_rotation) | resource | | [random_id.snapshot_identifier](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | | [aws_iam_policy_document.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | @@ -71,6 +72,11 @@ No modules. | [license\_model](#input\_license\_model) | License model information for this DB instance. Optional, but required for some DB engines, i.e. Oracle SE1 | `string` | `null` | no | | [maintenance\_window](#input\_maintenance\_window) | The window to perform maintenance in. Syntax: 'ddd:hh24:mi-ddd:hh24:mi'. Eg: 'Mon:00:00-Mon:03:00' | `string` | `null` | no | | [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 password is provided | `bool` | `true` | no | +| [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 | +| [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 | +| [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 automatically\_after\_days or schedule\_expression must be specified. | `number` | `null` | no | +| [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 | +| [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 automatically\_after\_days or schedule\_expression must be specified. | `string` | `null` | no | | [master\_user\_secret\_kms\_key\_id](#input\_master\_user\_secret\_kms\_key\_id) | The key ARN, key ID, alias ARN or alias name for the KMS key to encrypt the master user password secret in Secrets Manager.
If not specified, the default KMS key for your Amazon Web Services account is used. | `string` | `null` | no | | [max\_allocated\_storage](#input\_max\_allocated\_storage) | Specifies the value for Storage Autoscaling | `number` | `0` | no | | [monitoring\_interval](#input\_monitoring\_interval) | The interval, in seconds, between points when Enhanced Monitoring metrics are collected for the DB instance. To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60. | `number` | `0` | no | @@ -126,6 +132,7 @@ No modules. | [db\_instance\_name](#output\_db\_instance\_name) | The database name | | [db\_instance\_port](#output\_db\_instance\_port) | The database port | | [db\_instance\_resource\_id](#output\_db\_instance\_resource\_id) | The RDS Resource ID of this instance | +| [db\_instance\_secretsmanager\_secret\_rotation\_enabled](#output\_db\_instance\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret | | [db\_instance\_status](#output\_db\_instance\_status) | The RDS instance status | | [db\_instance\_username](#output\_db\_instance\_username) | The master username for the database | | [db\_listener\_endpoint](#output\_db\_listener\_endpoint) | Specifies the listener connection endpoint for SQL Server Always On | diff --git a/modules/db_instance/main.tf b/modules/db_instance/main.tf index a2acef12..e3c5bf01 100644 --- a/modules/db_instance/main.tf +++ b/modules/db_instance/main.tf @@ -197,3 +197,20 @@ resource "aws_iam_role_policy_attachment" "enhanced_monitoring" { role = aws_iam_role.enhanced_monitoring[0].name policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" } + +################################################################################ +# Managed Secret Rotation +################################################################################ + +resource "aws_secretsmanager_secret_rotation" "this" { + count = var.create && var.manage_master_user_password && var.manage_master_user_password_rotation ? 1 : 0 + + secret_id = aws_db_instance.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 + } +} diff --git a/modules/db_instance/outputs.tf b/modules/db_instance/outputs.tf index de06eb57..d50d91a9 100644 --- a/modules/db_instance/outputs.tf +++ b/modules/db_instance/outputs.tf @@ -107,3 +107,12 @@ output "db_instance_cloudwatch_log_groups" { description = "Map of CloudWatch log groups created and their attributes" value = aws_cloudwatch_log_group.this } + +################################################################################ +# Managed Secret Rotation +################################################################################ + +output "db_instance_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) +} diff --git a/modules/db_instance/variables.tf b/modules/db_instance/variables.tf index 84e35069..2c1ef3c8 100644 --- a/modules/db_instance/variables.tf +++ b/modules/db_instance/variables.tf @@ -417,3 +417,37 @@ variable "cloudwatch_log_group_kms_key_id" { type = string default = null } + +################################################################################ +# 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 automatically_after_days or 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 automatically_after_days or schedule_expression must be specified." + type = string + default = null +} diff --git a/modules/db_instance/versions.tf b/modules/db_instance/versions.tf index b791729e..ad493262 100644 --- a/modules/db_instance/versions.tf +++ b/modules/db_instance/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } random = { diff --git a/modules/db_instance_automated_backups_replication/versions.tf b/modules/db_instance_automated_backups_replication/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/modules/db_instance_automated_backups_replication/versions.tf +++ b/modules/db_instance_automated_backups_replication/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/modules/db_instance_role_association/README.md b/modules/db_instance_role_association/README.md index be342d62..938ade19 100644 --- a/modules/db_instance_role_association/README.md +++ b/modules/db_instance_role_association/README.md @@ -6,13 +6,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/modules/db_instance_role_association/versions.tf b/modules/db_instance_role_association/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/modules/db_instance_role_association/versions.tf +++ b/modules/db_instance_role_association/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/modules/db_option_group/README.md b/modules/db_option_group/README.md index a48eaf38..8f15702e 100644 --- a/modules/db_option_group/README.md +++ b/modules/db_option_group/README.md @@ -6,13 +6,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/modules/db_option_group/versions.tf b/modules/db_option_group/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/modules/db_option_group/versions.tf +++ b/modules/db_option_group/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/modules/db_parameter_group/README.md b/modules/db_parameter_group/README.md index 8c2ff950..cfb079ff 100644 --- a/modules/db_parameter_group/README.md +++ b/modules/db_parameter_group/README.md @@ -6,13 +6,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/modules/db_parameter_group/versions.tf b/modules/db_parameter_group/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/modules/db_parameter_group/versions.tf +++ b/modules/db_parameter_group/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/modules/db_subnet_group/README.md b/modules/db_subnet_group/README.md index d476046b..2b5c8e94 100644 --- a/modules/db_subnet_group/README.md +++ b/modules/db_subnet_group/README.md @@ -6,13 +6,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.25 | +| [aws](#requirement\_aws) | >= 5.33 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.25 | +| [aws](#provider\_aws) | >= 5.33 | ## Modules diff --git a/modules/db_subnet_group/versions.tf b/modules/db_subnet_group/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/modules/db_subnet_group/versions.tf +++ b/modules/db_subnet_group/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } } diff --git a/outputs.tf b/outputs.tf index cb0ee1cb..9abe42ac 100644 --- a/outputs.tf +++ b/outputs.tf @@ -147,3 +147,12 @@ output "db_instance_role_associations" { description = "A map of DB Instance Identifiers and IAM Role ARNs separated by a comma" value = module.db_instance_role_association } + +################################################################################ +# Managed Secret Rotation +################################################################################ + +output "db_instance_secretsmanager_secret_rotation_enabled" { + description = "Specifies whether automatic rotation is enabled for the secret" + value = module.db_instance.db_instance_secretsmanager_secret_rotation_enabled +} diff --git a/variables.tf b/variables.tf index db9375da..00840b1d 100644 --- a/variables.tf +++ b/variables.tf @@ -554,3 +554,37 @@ variable "db_instance_role_associations" { type = map(any) default = {} } + +################################################################################ +# 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 automatically_after_days or 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 automatically_after_days or schedule_expression must be specified." + type = string + default = null +} diff --git a/versions.tf b/versions.tf index 2c1a62c1..992f1b9a 100644 --- a/versions.tf +++ b/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.25" + version = ">= 5.33" } } }