Skip to content

Commit 5ca5ef7

Browse files
committed
Refine rotation configuration in secrets-manager-secret
1 parent b5a06a4 commit 5ca5ef7

File tree

5 files changed

+76
-34
lines changed

5 files changed

+76
-34
lines changed

modules/secrets-manager-secret/README.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ This module creates following resources.
1212

1313
| Name | Version |
1414
|------|---------|
15-
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5 |
16-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.22 |
15+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6 |
16+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.43 |
1717

1818
## Providers
1919

2020
| Name | Version |
2121
|------|---------|
22-
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.19.0 |
22+
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.50.0 |
2323

2424
## Modules
2525

@@ -42,19 +42,18 @@ This module creates following resources.
4242
| Name | Description | Type | Default | Required |
4343
|------|-------------|------|---------|:--------:|
4444
| <a name="input_name"></a> [name](#input\_name) | (Required) Friendly name of the new secret. The secret name can consist of uppercase letters, lowercase letters, digits, and any of the following characters: `/_+=.@-`. | `string` | n/a | yes |
45-
| <a name="input_block_public_policy"></a> [block\_public\_policy](#input\_block\_public\_policy) | (Optional) Whether to reject calls to PUT a resource policy if the policy allows public access. | `bool` | `false` | no |
45+
| <a name="input_block_public_policy"></a> [block\_public\_policy](#input\_block\_public\_policy) | (Optional) Whether to reject calls to PUT a resource policy if the policy allows public access. Defaults to `true`. | `bool` | `true` | no |
4646
| <a name="input_deletion_window_in_days"></a> [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | (Optional) Duration in days after which the secret is deleted after destruction of the resource. Valid value is between `7` and `30` days. Defaults to `30`. | `number` | `30` | no |
4747
| <a name="input_description"></a> [description](#input\_description) | (Optional) The description of the secret. | `string` | `"Managed by Terraform."` | no |
4848
| <a name="input_kms_key"></a> [kms\_key](#input\_kms\_key) | (Optional) The ARN or Id of the AWS KMS key to be used to encrypt the secret values in this secret. If you don't specify this value, then Secrets Manager defaults to using the AWS account's default KMS key named `aws/secretsmanager`. If the default KMS key with that name doesn't yet exist, then AWS Secrets Manager creates it for you automatically the first time. | `string` | `null` | no |
4949
| <a name="input_module_tags_enabled"></a> [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no |
50-
| <a name="input_overwrite_in_replicas"></a> [overwrite\_in\_replicas](#input\_overwrite\_in\_replicas) | (Optional) Whether to overwrite a secret with the same name in the destination region during replication. | `bool` | `false` | no |
50+
| <a name="input_overwrite_in_replicas"></a> [overwrite\_in\_replicas](#input\_overwrite\_in\_replicas) | (Optional) Whether to overwrite a secret with the same name in the destination region during replication. Defaults to `false`. | `bool` | `false` | no |
5151
| <a name="input_policy"></a> [policy](#input\_policy) | (Optional) A valid JSON document representing a resource policy. | `string` | `null` | no |
52-
| <a name="input_replicas"></a> [replicas](#input\_replicas) | (Optional) A list of replica configurations of the Secrets Manager secret. Each value of `replicas` block as defined below.<br> (Required) `region` - The region for replicating the secret.<br> (Optional) `kms_key` - The ARN, Key ID, or Alias of the AWS KMS key within the region secret is replicated to. If one is not specified, then Secrets Manager defaults to using the AWS account's default KMS key named `aws/secretsmanager` in the region. If the default KMS key with that name doesn't yet exist, then AWS Secrets Manager creates it for you automatically the first time. | `list(map(string))` | `[]` | no |
52+
| <a name="input_replicas"></a> [replicas](#input\_replicas) | (Optional) A list of replica configurations of the Secrets Manager secret. Each value of `replicas` block as defined below.<br> (Required) `region` - The region for replicating the secret.<br> (Optional) `kms_key` - The ARN, Key ID, or Alias of the AWS KMS key within the region secret is replicated to. If one is not specified, then Secrets Manager defaults to using the AWS account's default KMS key named `aws/secretsmanager` in the region. If the default KMS key with that name doesn't yet exist, then AWS Secrets Manager creates it for you automatically the first time. | <pre>list(object({<br> region = string<br> kms_key = optional(string)<br> }))</pre> | `[]` | no |
5353
| <a name="input_resource_group_description"></a> [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no |
5454
| <a name="input_resource_group_enabled"></a> [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no |
5555
| <a name="input_resource_group_name"></a> [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no |
56-
| <a name="input_rotation_duration_in_days"></a> [rotation\_duration\_in\_days](#input\_rotation\_duration\_in\_days) | (Optional) The number of days between automatic scheduled rotations of the secret. Required if `rotation_lambda_function` is configured. | `number` | `null` | no |
57-
| <a name="input_rotation_lambda_function"></a> [rotation\_lambda\_function](#input\_rotation\_lambda\_function) | (Optional) The ARN of the Lambda function that can rotate the secret. | `string` | `null` | no |
56+
| <a name="input_rotation"></a> [rotation](#input\_rotation) | (Optional) A rotation configurations of the Secrets Manager secret. `rotation` block as defined below.<br> (Optional) `enabled` - Whether to enable automatic rotation of the secret. Defaults to `false`.<br> (Optionial) `rotate_immediately` - Whether to rotate the secret immediately or wait until the next scheduled rotation window. The rotation schedule is defined in rotation\_rules. For secrets that use a Lambda rotation function to rotate, if you don't immediately rotate the secret, Secrets Manager tests the rotation configuration by running the testSecret step. Defaults to `true`.<br> (Optional) `lambda_function` - The ARN of the Lambda function that can rotate the secret.<br> (Optional) `schedule_frequency` - The number of days between automatic scheduled rotations of the secret. Either `schedule_frequency` or `schedule_expression` must be specified.<br> (Optional) `schedule_expression` - A cron expression such as `cron(a b c d e f)` or a rate expression such as `rate(10 days)`. Either `schedule_frequency` or `schedule_expression` must be specified.<br> (Optional) `duration` - The length of the rotation window in hours. | <pre>object({<br> enabled = optional(bool, false)<br> rotate_immediately = optional(bool, true)<br> lambda_function = optional(string)<br> schedule_frequency = optional(number)<br> schedule_expression = optional(string)<br> duration = optional(number)<br> })</pre> | `{}` | no |
5857
| <a name="input_tags"></a> [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no |
5958
| <a name="input_type"></a> [type](#input\_type) | (Optional) The intended type of the secret. Valid values are `TEXT`, `KEY_VALUE` or `BINARY`. | `string` | `"KEY_VALUE"` | no |
6059
| <a name="input_value"></a> [value](#input\_value) | (Optional) The secret value that you want to encrypt and store in the current version of the secret. Specify plaintext data with `string` type if `type` is `TEXT`. Specify key-value data with `map` type if `type` is `KEY_VALUE`. Specify binary data with `string` type if `type` is `BINARY`. The `aws_secretsmanager_secret_version` resource is deleted from Terraform if you set the value to `null`. However, `AWSCURRENT` staging label is still active on the version event after the resource is deleted from Terraform. | `any` | `null` | no |

modules/secrets-manager-secret/main.tf

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ locals {
1919
# Secrets Manager Secret
2020
###################################################
2121

22+
# INFO: Use a separate resource
23+
# - 'policy'
24+
# INFO: Not supported attributes
25+
# - `name_prefix`
2226
resource "aws_secretsmanager_secret" "this" {
2327
name = var.name
2428
description = var.description
2529

26-
# Use `aws_secretsmanager_policy` instead
27-
policy = null
2830
kms_key_id = var.kms_key
2931
recovery_window_in_days = var.deletion_window_in_days
3032
force_overwrite_replica_secret = var.overwrite_in_replicas
@@ -127,12 +129,17 @@ resource "aws_secretsmanager_secret_policy" "this" {
127129
###################################################
128130

129131
resource "aws_secretsmanager_secret_rotation" "this" {
130-
count = var.rotation_lambda_function != null ? 1 : 0
132+
count = var.rotation.enabled ? 1 : 0
131133

132-
secret_id = aws_secretsmanager_secret.this.id
133-
rotation_lambda_arn = var.rotation_lambda_function
134+
secret_id = aws_secretsmanager_secret.this.id
135+
136+
rotate_immediately = var.rotation.rotate_immediately
137+
rotation_lambda_arn = var.rotation.lambda_function
134138

135139
rotation_rules {
136-
automatically_after_days = var.rotation_duration_in_days
140+
automatically_after_days = var.rotation.schedule_frequency
141+
schedule_expression = var.rotation.schedule_expression
142+
143+
duration = var.rotation.duration != null ? "${var.rotation.duration}h" : null
137144
}
138145
}

modules/secrets-manager-secret/outputs.tf

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,12 @@ output "deletion_window_in_days" {
6363
output "rotation" {
6464
description = "The configuration of the automatic rotation for the secret."
6565
value = {
66-
enabled = var.rotation_lambda_function != null
67-
lambda_function = one(aws_secretsmanager_secret_rotation.this[*].rotation_lambda_arn)
68-
duration_in_days = var.rotation_duration_in_days
66+
enabled = var.rotation.enabled
67+
lambda_function = one(aws_secretsmanager_secret_rotation.this[*].rotation_lambda_arn)
68+
69+
schedule_frequency = var.rotation.schedule_frequency
70+
schedule_expression = one(aws_secretsmanager_secret_rotation.this[*].rotation_rules[0].schedule_expression)
71+
duration_in_days = var.rotation.duration
6972
}
7073
}
7174

@@ -86,3 +89,11 @@ output "overwrite_in_replicas" {
8689
description = "Whether to overwrite a secret with the same name in the destination region during replication."
8790
value = aws_secretsmanager_secret.this.force_overwrite_replica_secret
8891
}
92+
93+
# output "debug" {
94+
# value = {
95+
# for k, v in aws_secretsmanager_secret.this :
96+
# k => v
97+
# if !contains(["tags", "tags_all", "policy", "id", "arn", "name", "description", "kms_key_id", "recovery_window_in_days", "force_overwrite_replica_secret", "name_prefix", "replica"], k)
98+
# }
99+
# }

modules/secrets-manager-secret/variables.tf

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
variable "name" {
22
description = "(Required) Friendly name of the new secret. The secret name can consist of uppercase letters, lowercase letters, digits, and any of the following characters: `/_+=.@-`."
33
type = string
4+
nullable = false
45
}
56

67
variable "description" {
@@ -26,6 +27,7 @@ variable "value" {
2627
description = "(Optional) The secret value that you want to encrypt and store in the current version of the secret. Specify plaintext data with `string` type if `type` is `TEXT`. Specify key-value data with `map` type if `type` is `KEY_VALUE`. Specify binary data with `string` type if `type` is `BINARY`. The `aws_secretsmanager_secret_version` resource is deleted from Terraform if you set the value to `null`. However, `AWSCURRENT` staging label is still active on the version event after the resource is deleted from Terraform."
2728
type = any
2829
default = null
30+
nullable = true
2931
}
3032

3133
variable "versions" {
@@ -64,18 +66,20 @@ variable "kms_key" {
6466
description = "(Optional) The ARN or Id of the AWS KMS key to be used to encrypt the secret values in this secret. If you don't specify this value, then Secrets Manager defaults to using the AWS account's default KMS key named `aws/secretsmanager`. If the default KMS key with that name doesn't yet exist, then AWS Secrets Manager creates it for you automatically the first time."
6567
type = string
6668
default = null
69+
nullable = true
6770
}
6871

6972
variable "policy" {
7073
description = "(Optional) A valid JSON document representing a resource policy."
7174
type = string
7275
default = null
76+
nullable = true
7377
}
7478

7579
variable "block_public_policy" {
76-
description = "(Optional) Whether to reject calls to PUT a resource policy if the policy allows public access."
80+
description = "(Optional) Whether to reject calls to PUT a resource policy if the policy allows public access. Defaults to `true`."
7781
type = bool
78-
default = false
82+
default = true
7983
nullable = false
8084
}
8185

@@ -100,28 +104,49 @@ variable "replicas" {
100104
(Required) `region` - The region for replicating the secret.
101105
(Optional) `kms_key` - The ARN, Key ID, or Alias of the AWS KMS key within the region secret is replicated to. If one is not specified, then Secrets Manager defaults to using the AWS account's default KMS key named `aws/secretsmanager` in the region. If the default KMS key with that name doesn't yet exist, then AWS Secrets Manager creates it for you automatically the first time.
102106
EOF
103-
type = list(map(string))
104-
default = []
105-
nullable = false
107+
type = list(object({
108+
region = string
109+
kms_key = optional(string)
110+
}))
111+
default = []
112+
nullable = false
106113
}
107114

108115
variable "overwrite_in_replicas" {
109-
description = "(Optional) Whether to overwrite a secret with the same name in the destination region during replication."
116+
description = "(Optional) Whether to overwrite a secret with the same name in the destination region during replication. Defaults to `false`."
110117
type = bool
111118
default = false
112119
nullable = false
113120
}
114121

115-
variable "rotation_lambda_function" {
116-
description = "(Optional) The ARN of the Lambda function that can rotate the secret."
117-
type = string
118-
default = null
119-
}
122+
variable "rotation" {
123+
description = <<EOF
124+
(Optional) A rotation configurations of the Secrets Manager secret. `rotation` block as defined below.
125+
(Optional) `enabled` - Whether to enable automatic rotation of the secret. Defaults to `false`.
126+
(Optionial) `rotate_immediately` - Whether to rotate the secret immediately or wait until the next scheduled rotation window. The rotation schedule is defined in rotation_rules. For secrets that use a Lambda rotation function to rotate, if you don't immediately rotate the secret, Secrets Manager tests the rotation configuration by running the testSecret step. Defaults to `true`.
127+
(Optional) `lambda_function` - The ARN of the Lambda function that can rotate the secret.
128+
(Optional) `schedule_frequency` - The number of days between automatic scheduled rotations of the secret. Either `schedule_frequency` or `schedule_expression` must be specified.
129+
(Optional) `schedule_expression` - A cron expression such as `cron(a b c d e f)` or a rate expression such as `rate(10 days)`. Either `schedule_frequency` or `schedule_expression` must be specified.
130+
(Optional) `duration` - The length of the rotation window in hours.
131+
EOF
132+
type = object({
133+
enabled = optional(bool, false)
134+
rotate_immediately = optional(bool, true)
135+
lambda_function = optional(string)
136+
schedule_frequency = optional(number)
137+
schedule_expression = optional(string)
138+
duration = optional(number)
139+
})
140+
default = {}
141+
nullable = false
120142

121-
variable "rotation_duration_in_days" {
122-
description = "(Optional) The number of days between automatic scheduled rotations of the secret. Required if `rotation_lambda_function` is configured."
123-
type = number
124-
default = null
143+
validation {
144+
condition = anytrue([
145+
var.rotation.duration == null,
146+
var.rotation.duration != null && coalesce(var.rotation.duration, 0) > 0,
147+
])
148+
error_message = "Valid value for `duration` is greater than `0`."
149+
}
125150
}
126151

127152
variable "tags" {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
terraform {
2-
required_version = ">= 1.5"
2+
required_version = ">= 1.6"
33

44
required_providers {
55
aws = {
66
source = "hashicorp/aws"
7-
version = ">= 4.22"
7+
version = ">= 5.43"
88
}
99
}
1010
}

0 commit comments

Comments
 (0)