Skip to content

Commit

Permalink
feat: Secretsmanager secret rotation for master user password (#97)
Browse files Browse the repository at this point in the history
* manage master password rotation

* update example

* update variable description

* update variable description
  • Loading branch information
magreenbaum committed Mar 26, 2024
1 parent 1d7b385 commit e542e41
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 0 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ No modules.
| [aws_redshift_snapshot_schedule_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/redshift_snapshot_schedule_association) | resource |
| [aws_redshift_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/redshift_subnet_group) | resource |
| [aws_redshift_usage_limit.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/redshift_usage_limit) | resource |
| [aws_secretsmanager_secret_rotation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_rotation) | resource |
| [random_password.master_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [aws_iam_policy_document.scheduled_action](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.scheduled_action_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
Expand Down Expand Up @@ -262,8 +263,13 @@ No modules.
| <a name="input_logging"></a> [logging](#input\_logging) | Logging configuration for the cluster | `any` | `{}` | no |
| <a name="input_maintenance_track_name"></a> [maintenance\_track\_name](#input\_maintenance\_track\_name) | The name of the maintenance track for the restored cluster. When you take a snapshot, the snapshot inherits the MaintenanceTrack value from the cluster. The snapshot might be on a different track than the cluster that was the source for the snapshot. Default value is `current` | `string` | `null` | no |
| <a name="input_manage_master_password"></a> [manage\_master\_password](#input\_manage\_master\_password) | Whether to use AWS SecretsManager to manage the cluster admin credentials. Conflicts with `master_password`. One of `master_password` or `manage_master_password` is required unless `snapshot_identifier` is provided | `bool` | `false` | no |
| <a name="input_manage_master_password_rotation"></a> [manage\_master\_password\_rotation](#input\_manage\_master\_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_manual_snapshot_retention_period"></a> [manual\_snapshot\_retention\_period](#input\_manual\_snapshot\_retention\_period) | The default number of days to retain a manual snapshot. If the value is -1, the snapshot is retained indefinitely. This setting doesn't change the retention period of existing snapshots. Valid values are between `-1` and `3653`. Default value is `-1` | `number` | `null` | no |
| <a name="input_master_password"></a> [master\_password](#input\_master\_password) | Password for the master DB user. (Required unless a `snapshot_identifier` is provided). Must contain at least 8 chars, one uppercase letter, one lowercase letter, and one number | `string` | `null` | no |
| <a name="input_master_password_rotate_immediately"></a> [master\_password\_rotate\_immediately](#input\_master\_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_password_rotation_automatically_after_days"></a> [master\_password\_rotation\_automatically\_after\_days](#input\_master\_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_password_rotation_duration"></a> [master\_password\_rotation\_duration](#input\_master\_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_password_rotation_schedule_expression"></a> [master\_password\_rotation\_schedule\_expression](#input\_master\_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_password_secret_kms_key_id"></a> [master\_password\_secret\_kms\_key\_id](#input\_master\_password\_secret\_kms\_key\_id) | ID of the KMS key used to encrypt the cluster admin credentials secret | `string` | `null` | no |
| <a name="input_master_username"></a> [master\_username](#input\_master\_username) | Username for the master DB user (Required unless a `snapshot_identifier` is provided). Defaults to `awsuser` | `string` | `"awsuser"` | no |
| <a name="input_multi_az"></a> [multi\_az](#input\_multi\_az) | Specifies if the Redshift cluster is multi-AZ | `bool` | `null` | no |
Expand Down Expand Up @@ -320,6 +326,7 @@ No modules.
| <a name="output_cluster_preferred_maintenance_window"></a> [cluster\_preferred\_maintenance\_window](#output\_cluster\_preferred\_maintenance\_window) | The backup window |
| <a name="output_cluster_public_key"></a> [cluster\_public\_key](#output\_cluster\_public\_key) | The public key for the cluster |
| <a name="output_cluster_revision_number"></a> [cluster\_revision\_number](#output\_cluster\_revision\_number) | The specific revision number of the database in the cluster |
| <a name="output_cluster_secretsmanager_secret_rotation_enabled"></a> [cluster\_secretsmanager\_secret\_rotation\_enabled](#output\_cluster\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret |
| <a name="output_cluster_subnet_group_name"></a> [cluster\_subnet\_group\_name](#output\_cluster\_subnet\_group\_name) | The name of a cluster subnet group to be associated with this cluster |
| <a name="output_cluster_type"></a> [cluster\_type](#output\_cluster\_type) | The Redshift cluster type |
| <a name="output_cluster_version"></a> [cluster\_version](#output\_cluster\_version) | The version of Redshift engine software |
Expand Down
1 change: 1 addition & 0 deletions examples/complete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ No inputs.
| <a name="output_endpoint_access_port"></a> [endpoint\_access\_port](#output\_endpoint\_access\_port) | The port number on which the cluster accepts incoming connections |
| <a name="output_endpoint_access_vpc_endpoint"></a> [endpoint\_access\_vpc\_endpoint](#output\_endpoint\_access\_vpc\_endpoint) | The connection endpoint for connecting to an Amazon Redshift cluster through the proxy. See details below |
| <a name="output_master_password_secret_arn"></a> [master\_password\_secret\_arn](#output\_master\_password\_secret\_arn) | ARN of managed master password secret |
| <a name="output_master_password_secretsmanager_secret_rotation_enabled"></a> [master\_password\_secretsmanager\_secret\_rotation\_enabled](#output\_master\_password\_secretsmanager\_secret\_rotation\_enabled) | Specifies whether automatic rotation is enabled for the secret |
| <a name="output_parameter_group_arn"></a> [parameter\_group\_arn](#output\_parameter\_group\_arn) | Amazon Resource Name (ARN) of the parameter group created |
| <a name="output_parameter_group_id"></a> [parameter\_group\_id](#output\_parameter\_group\_id) | The name of the Redshift parameter group created |
| <a name="output_scheduled_action_iam_role_arn"></a> [scheduled\_action\_iam\_role\_arn](#output\_scheduled\_action\_iam\_role\_arn) | Scheduled actions IAM role ARN |
Expand Down
3 changes: 3 additions & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ module "redshift" {
# Or make Redshift manage it in secrets manager
manage_master_password = true

manage_master_password_rotation = true
master_password_rotation_schedule_expression = "rate(90 days)"

encrypted = true
kms_key_arn = aws_kms_key.redshift.arn

Expand Down
5 changes: 5 additions & 0 deletions examples/complete/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,8 @@ output "master_password_secret_arn" {
description = "ARN of managed master password secret"
value = module.redshift.master_password_secret_arn
}

output "master_password_secretsmanager_secret_rotation_enabled" {
description = "Specifies whether automatic rotation is enabled for the secret"
value = module.redshift.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 @@ -336,3 +336,20 @@ resource "aws_cloudwatch_log_group" "this" {

tags = merge(var.tags, var.cloudwatch_log_group_tags)
}

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

resource "aws_secretsmanager_secret_rotation" "this" {
count = var.create && var.manage_master_password && var.manage_master_password_rotation ? 1 : 0

secret_id = aws_redshift_cluster.this[0].master_password_secret_arn
rotate_immediately = var.master_password_rotate_immediately

rotation_rules {
automatically_after_days = var.master_password_rotation_automatically_after_days
duration = var.master_password_rotation_duration
schedule_expression = var.master_password_rotation_schedule_expression
}
}
9 changes: 9 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,12 @@ output "master_password_secret_arn" {
description = "ARN of managed master password secret"
value = try(aws_redshift_cluster.this[0].master_password_secret_arn, null)
}

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

output "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 @@ -508,3 +508,37 @@ variable "cloudwatch_log_group_tags" {
type = map(string)
default = {}
}

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

variable "manage_master_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_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_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_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_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 e542e41

Please sign in to comment.