Skip to content

Commit 9682e45

Browse files
committed
feat: Re-add support for random passwords using ephemeral random password
1 parent 2b944d0 commit 9682e45

File tree

8 files changed

+75
-39
lines changed

8 files changed

+75
-39
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/antonbabenko/pre-commit-terraform
3-
rev: v1.99.5
3+
rev: v1.100.0
44
hooks:
55
- id: terraform_fmt
66
- id: terraform_wrapper_module_for_each

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ Examples codified under the [`examples`](https://github.com/terraform-aws-module
125125
|------|---------|
126126
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.11 |
127127
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |
128+
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.7 |
128129

129130
## Providers
130131

@@ -154,6 +155,7 @@ No modules.
154155
| <a name="input_block_public_policy"></a> [block\_public\_policy](#input\_block\_public\_policy) | Makes an optional API call to Zelkova to validate the Resource Policy to prevent broad access to your secret | `bool` | `null` | no |
155156
| <a name="input_create"></a> [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no |
156157
| <a name="input_create_policy"></a> [create\_policy](#input\_create\_policy) | Determines whether a policy will be created | `bool` | `false` | no |
158+
| <a name="input_create_random_password"></a> [create\_random\_password](#input\_create\_random\_password) | Determines whether an ephemeral random password will be generated for `secret_string_wo` | `bool` | `false` | no |
157159
| <a name="input_description"></a> [description](#input\_description) | A description of the secret | `string` | `null` | no |
158160
| <a name="input_enable_rotation"></a> [enable\_rotation](#input\_enable\_rotation) | Determines whether secret rotation is enabled | `bool` | `false` | no |
159161
| <a name="input_force_overwrite_replica_secret"></a> [force\_overwrite\_replica\_secret](#input\_force\_overwrite\_replica\_secret) | Accepts boolean value to specify whether to overwrite a secret with the same name in the destination Region | `bool` | `null` | no |
@@ -163,6 +165,8 @@ No modules.
163165
| <a name="input_name_prefix"></a> [name\_prefix](#input\_name\_prefix) | Creates a unique name beginning with the specified prefix | `string` | `null` | no |
164166
| <a name="input_override_policy_documents"></a> [override\_policy\_documents](#input\_override\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid` | `list(string)` | `[]` | no |
165167
| <a name="input_policy_statements"></a> [policy\_statements](#input\_policy\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage | <pre>list(object({<br/> sid = optional(string)<br/> actions = optional(list(string))<br/> not_actions = optional(list(string))<br/> effect = optional(string)<br/> resources = optional(list(string))<br/> not_resources = optional(list(string))<br/> principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> not_principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> condition = optional(list(object({<br/> test = string<br/> values = list(string)<br/> variable = string<br/> })))<br/> }))</pre> | `null` | no |
168+
| <a name="input_random_password_length"></a> [random\_password\_length](#input\_random\_password\_length) | The length of the generated random password | `number` | `32` | no |
169+
| <a name="input_random_password_override_special"></a> [random\_password\_override\_special](#input\_random\_password\_override\_special) | Supply your own list of special characters to use for string generation. This overrides the default character list in the special argument | `string` | `"!@#$%&*()-_=+[]{}<>:?"` | no |
166170
| <a name="input_recovery_window_in_days"></a> [recovery\_window\_in\_days](#input\_recovery\_window\_in\_days) | Number of days that AWS Secrets Manager waits before it can delete the secret. This value can be `0` to force deletion without recovery or range from `7` to `30` days. The default value is `30` | `number` | `null` | no |
167171
| <a name="input_region"></a> [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no |
168172
| <a name="input_replica"></a> [replica](#input\_replica) | Configuration block to support secret replication | <pre>map(object({<br/> kms_key_id = optional(string)<br/> region = optional(string) # will default to the key name<br/> }))</pre> | `null` | no |

examples/complete/main.tf

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ module "secrets_manager" {
5151
]
5252

5353
# Version
54-
secret_string_wo = ephemeral.random_password.password.result
55-
secret_string_wo_version = 1
54+
create_random_password = true
55+
random_password_length = 64
56+
random_password_override_special = "!@#$%^&*()_+"
5657

5758
tags = local.tags
5859
}
@@ -126,12 +127,6 @@ module "secrets_manager_disabled" {
126127
# Supporting Resources
127128
################################################################################
128129

129-
ephemeral "random_password" "password" {
130-
length = 16
131-
special = true
132-
override_special = "!#$%&*()-_=+[]{}<>:?"
133-
}
134-
135130
# https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets-required-permissions-function.html
136131
data "aws_iam_policy_document" "this" {
137132
statement {
@@ -163,7 +158,7 @@ module "lambda" {
163158
description = "Example Secrets Manager secret rotation lambda function"
164159

165160
handler = "function.lambda_handler"
166-
runtime = "python3.12"
161+
runtime = "python3.13"
167162
timeout = 60
168163
memory_size = 512
169164
source_path = "${path.module}/function.py"

main.tf

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ resource "aws_secretsmanager_secret_version" "this" {
101101
secret_id = aws_secretsmanager_secret.this[0].id
102102
secret_binary = var.secret_binary
103103
secret_string = var.secret_string
104-
secret_string_wo = var.secret_string_wo
105-
secret_string_wo_version = var.secret_string_wo_version
104+
secret_string_wo = var.create_random_password ? ephemeral.random_password.this[0].result : var.secret_string_wo
105+
secret_string_wo_version = var.create_random_password ? coalesce(var.secret_string_wo_version, 0) : var.secret_string_wo_version
106106
version_stages = var.version_stages
107107
}
108108

@@ -114,8 +114,8 @@ resource "aws_secretsmanager_secret_version" "ignore_changes" {
114114
secret_id = aws_secretsmanager_secret.this[0].id
115115
secret_binary = var.secret_binary
116116
secret_string = var.secret_string
117-
secret_string_wo = var.secret_string_wo
118-
secret_string_wo_version = var.secret_string_wo_version
117+
secret_string_wo = var.create_random_password ? ephemeral.random_password.this[0].result : var.secret_string_wo
118+
secret_string_wo_version = var.create_random_password ? coalesce(var.secret_string_wo_version, 0) : var.secret_string_wo_version
119119
version_stages = var.version_stages
120120

121121
lifecycle {
@@ -127,6 +127,14 @@ resource "aws_secretsmanager_secret_version" "ignore_changes" {
127127
}
128128
}
129129

130+
ephemeral "random_password" "this" {
131+
count = var.create && var.create_random_password ? 1 : 0
132+
133+
length = var.random_password_length
134+
special = true
135+
override_special = var.random_password_override_special
136+
}
137+
130138
################################################################################
131139
# Rotation
132140
################################################################################

variables.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,24 @@ variable "version_stages" {
160160
default = null
161161
}
162162

163+
variable "create_random_password" {
164+
description = "Determines whether an ephemeral random password will be generated for `secret_string_wo`"
165+
type = bool
166+
default = false
167+
}
168+
169+
variable "random_password_length" {
170+
description = "The length of the generated random password"
171+
type = number
172+
default = 32
173+
}
174+
175+
variable "random_password_override_special" {
176+
description = "Supply your own list of special characters to use for string generation. This overrides the default character list in the special argument"
177+
type = string
178+
default = "!@#$%&*()-_=+[]{}<>:?"
179+
}
180+
163181
################################################################################
164182
# Rotation
165183
################################################################################

versions.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@ terraform {
66
source = "hashicorp/aws"
77
version = ">= 6.0"
88
}
9+
random = {
10+
source = "hashicorp/random"
11+
version = ">= 3.7"
12+
}
913
}
1014
}

wrappers/main.tf

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,32 @@ module "wrapper" {
33

44
for_each = var.items
55

6-
block_public_policy = try(each.value.block_public_policy, var.defaults.block_public_policy, null)
7-
create = try(each.value.create, var.defaults.create, true)
8-
create_policy = try(each.value.create_policy, var.defaults.create_policy, false)
9-
description = try(each.value.description, var.defaults.description, null)
10-
enable_rotation = try(each.value.enable_rotation, var.defaults.enable_rotation, false)
11-
force_overwrite_replica_secret = try(each.value.force_overwrite_replica_secret, var.defaults.force_overwrite_replica_secret, null)
12-
ignore_secret_changes = try(each.value.ignore_secret_changes, var.defaults.ignore_secret_changes, false)
13-
kms_key_id = try(each.value.kms_key_id, var.defaults.kms_key_id, null)
14-
name = try(each.value.name, var.defaults.name, null)
15-
name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null)
16-
override_policy_documents = try(each.value.override_policy_documents, var.defaults.override_policy_documents, [])
17-
policy_statements = try(each.value.policy_statements, var.defaults.policy_statements, null)
18-
recovery_window_in_days = try(each.value.recovery_window_in_days, var.defaults.recovery_window_in_days, null)
19-
region = try(each.value.region, var.defaults.region, null)
20-
replica = try(each.value.replica, var.defaults.replica, null)
21-
rotate_immediately = try(each.value.rotate_immediately, var.defaults.rotate_immediately, null)
22-
rotation_lambda_arn = try(each.value.rotation_lambda_arn, var.defaults.rotation_lambda_arn, "")
23-
rotation_rules = try(each.value.rotation_rules, var.defaults.rotation_rules, null)
24-
secret_binary = try(each.value.secret_binary, var.defaults.secret_binary, null)
25-
secret_string = try(each.value.secret_string, var.defaults.secret_string, null)
26-
secret_string_wo = try(each.value.secret_string_wo, var.defaults.secret_string_wo, null)
27-
secret_string_wo_version = try(each.value.secret_string_wo_version, var.defaults.secret_string_wo_version, null)
28-
source_policy_documents = try(each.value.source_policy_documents, var.defaults.source_policy_documents, [])
29-
tags = try(each.value.tags, var.defaults.tags, {})
30-
version_stages = try(each.value.version_stages, var.defaults.version_stages, null)
6+
block_public_policy = try(each.value.block_public_policy, var.defaults.block_public_policy, null)
7+
create = try(each.value.create, var.defaults.create, true)
8+
create_policy = try(each.value.create_policy, var.defaults.create_policy, false)
9+
create_random_password = try(each.value.create_random_password, var.defaults.create_random_password, false)
10+
description = try(each.value.description, var.defaults.description, null)
11+
enable_rotation = try(each.value.enable_rotation, var.defaults.enable_rotation, false)
12+
force_overwrite_replica_secret = try(each.value.force_overwrite_replica_secret, var.defaults.force_overwrite_replica_secret, null)
13+
ignore_secret_changes = try(each.value.ignore_secret_changes, var.defaults.ignore_secret_changes, false)
14+
kms_key_id = try(each.value.kms_key_id, var.defaults.kms_key_id, null)
15+
name = try(each.value.name, var.defaults.name, null)
16+
name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null)
17+
override_policy_documents = try(each.value.override_policy_documents, var.defaults.override_policy_documents, [])
18+
policy_statements = try(each.value.policy_statements, var.defaults.policy_statements, null)
19+
random_password_length = try(each.value.random_password_length, var.defaults.random_password_length, 32)
20+
random_password_override_special = try(each.value.random_password_override_special, var.defaults.random_password_override_special, "!@#$%&*()-_=+[]{}<>:?")
21+
recovery_window_in_days = try(each.value.recovery_window_in_days, var.defaults.recovery_window_in_days, null)
22+
region = try(each.value.region, var.defaults.region, null)
23+
replica = try(each.value.replica, var.defaults.replica, null)
24+
rotate_immediately = try(each.value.rotate_immediately, var.defaults.rotate_immediately, null)
25+
rotation_lambda_arn = try(each.value.rotation_lambda_arn, var.defaults.rotation_lambda_arn, "")
26+
rotation_rules = try(each.value.rotation_rules, var.defaults.rotation_rules, null)
27+
secret_binary = try(each.value.secret_binary, var.defaults.secret_binary, null)
28+
secret_string = try(each.value.secret_string, var.defaults.secret_string, null)
29+
secret_string_wo = try(each.value.secret_string_wo, var.defaults.secret_string_wo, null)
30+
secret_string_wo_version = try(each.value.secret_string_wo_version, var.defaults.secret_string_wo_version, null)
31+
source_policy_documents = try(each.value.source_policy_documents, var.defaults.source_policy_documents, [])
32+
tags = try(each.value.tags, var.defaults.tags, {})
33+
version_stages = try(each.value.version_stages, var.defaults.version_stages, null)
3134
}

wrappers/versions.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@ terraform {
66
source = "hashicorp/aws"
77
version = ">= 6.0"
88
}
9+
random = {
10+
source = "hashicorp/random"
11+
version = ">= 3.7"
12+
}
913
}
1014
}

0 commit comments

Comments
 (0)