Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.96.1
rev: v1.100.0
hooks:
- id: terraform_fmt
- id: terraform_wrapper_module_for_each
Expand Down
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,15 @@ Examples codified under the [`examples`](https://github.com/terraform-aws-module

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.0 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.11 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.7 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 3.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.0 |

## Modules

Expand All @@ -147,7 +146,6 @@ No modules.
| [aws_secretsmanager_secret_rotation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_rotation) | resource |
| [aws_secretsmanager_secret_version.ignore_changes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [aws_secretsmanager_secret_version.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |

## Inputs
Expand All @@ -157,7 +155,7 @@ No modules.
| <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 |
| <a name="input_create"></a> [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no |
| <a name="input_create_policy"></a> [create\_policy](#input\_create\_policy) | Determines whether a policy will be created | `bool` | `false` | no |
| <a name="input_create_random_password"></a> [create\_random\_password](#input\_create\_random\_password) | Determines whether a random password will be generated | `bool` | `false` | no |
| <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 |
| <a name="input_description"></a> [description](#input\_description) | A description of the secret | `string` | `null` | no |
| <a name="input_enable_rotation"></a> [enable\_rotation](#input\_enable\_rotation) | Determines whether secret rotation is enabled | `bool` | `false` | no |
| <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 |
Expand All @@ -166,15 +164,19 @@ No modules.
| <a name="input_name"></a> [name](#input\_name) | Friendly name of the new secret. The secret name can consist of uppercase letters, lowercase letters, digits, and any of the following characters: `/_+=.@-` | `string` | `null` | no |
| <a name="input_name_prefix"></a> [name\_prefix](#input\_name\_prefix) | Creates a unique name beginning with the specified prefix | `string` | `null` | no |
| <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 |
| <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 | `map(any)` | `{}` | no |
| <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>map(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 |
| <a name="input_random_password_length"></a> [random\_password\_length](#input\_random\_password\_length) | The length of the generated random password | `number` | `32` | no |
| <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 |
| <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 |
| <a name="input_replica"></a> [replica](#input\_replica) | Configuration block to support secret replication | `map(any)` | `{}` | no |
| <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 |
| <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 |
| <a name="input_rotate_immediately"></a> [rotate\_immediately](#input\_rotate\_immediately) | Specifies whether to rotate the secret immediately or wait until the next scheduled rotation window. The rotation schedule is defined in `rotation_rules` | `bool` | `null` | no |
| <a name="input_rotation_lambda_arn"></a> [rotation\_lambda\_arn](#input\_rotation\_lambda\_arn) | Specifies the ARN of the Lambda function that can rotate the secret | `string` | `""` | no |
| <a name="input_rotation_rules"></a> [rotation\_rules](#input\_rotation\_rules) | A structure that defines the rotation configuration for this secret | `map(any)` | `{}` | no |
| <a name="input_secret_binary"></a> [secret\_binary](#input\_secret\_binary) | Specifies binary data that you want to encrypt and store in this version of the secret. This is required if `secret_string` is not set. Needs to be encoded to base64 | `string` | `null` | no |
| <a name="input_secret_string"></a> [secret\_string](#input\_secret\_string) | Specifies text data that you want to encrypt and store in this version of the secret. This is required if `secret_binary` is not set | `string` | `null` | no |
| <a name="input_rotation_rules"></a> [rotation\_rules](#input\_rotation\_rules) | A structure that defines the rotation configuration for this secret | <pre>object({<br/> automatically_after_days = optional(number)<br/> duration = optional(string)<br/> schedule_expression = optional(string)<br/> })</pre> | `null` | no |
| <a name="input_secret_binary"></a> [secret\_binary](#input\_secret\_binary) | Specifies binary data that you want to encrypt and store in this version of the secret. This is required if `secret_string` or `secret_string_wo` is not set. Needs to be encoded to base64 | `string` | `null` | no |
| <a name="input_secret_string"></a> [secret\_string](#input\_secret\_string) | Specifies text data that you want to encrypt and store in this version of the secret. This is required if `secret_binary` or `secret_string_wo` is not set | `string` | `null` | no |
| <a name="input_secret_string_wo"></a> [secret\_string\_wo](#input\_secret\_string\_wo) | Specifies text data that you want to encrypt and store in this version of the secret. This is required if `secret_binary` or `secret_string` is not set | `string` | `null` | no |
| <a name="input_secret_string_wo_version"></a> [secret\_string\_wo\_version](#input\_secret\_string\_wo\_version) | Used together with `secret_string_wo` to trigger an update. Increment this value when an update to `secret_string_wo` is required | `string` | `null` | no |
| <a name="input_source_policy_documents"></a> [source\_policy\_documents](#input\_source\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
| <a name="input_version_stages"></a> [version\_stages](#input\_version\_stages) | Specifies a list of staging labels that are attached to this version of the secret. A staging label must be unique to a single version of the secret | `list(string)` | `null` | no |
Expand Down
9 changes: 5 additions & 4 deletions examples/complete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,21 @@ Note that this example may create resources which will incur monetary charges on

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.11 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.7 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.0 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_lambda"></a> [lambda](#module\_lambda) | terraform-aws-modules/lambda/aws | ~> 6.0 |
| <a name="module_lambda"></a> [lambda](#module\_lambda) | terraform-aws-modules/lambda/aws | ~> 8.0 |
| <a name="module_secrets_manager"></a> [secrets\_manager](#module\_secrets\_manager) | ../.. | n/a |
| <a name="module_secrets_manager_disabled"></a> [secrets\_manager\_disabled](#module\_secrets\_manager\_disabled) | ../.. | n/a |
| <a name="module_secrets_manager_rotate"></a> [secrets\_manager\_rotate](#module\_secrets\_manager\_rotate) | ../.. | n/a |
Expand Down
6 changes: 3 additions & 3 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ module "secrets_manager_rotate" {
engine = "mariadb",
host = "mydb.cluster-123456789012.us-east-1.rds.amazonaws.com",
username = "Bill",
password = "ThisIsMySuperSecretString12356!"
password = "ThisIsMySuperSecretString12356!",
dbname = "mydb",
port = 3306
})
Expand Down Expand Up @@ -152,13 +152,13 @@ data "aws_iam_policy_document" "this" {

module "lambda" {
source = "terraform-aws-modules/lambda/aws"
version = "~> 6.0"
version = "~> 8.0"

function_name = local.name
description = "Example Secrets Manager secret rotation lambda function"

handler = "function.lambda_handler"
runtime = "python3.10"
runtime = "python3.13"
timeout = 60
memory_size = 512
source_path = "${path.module}/function.py"
Expand Down
8 changes: 6 additions & 2 deletions examples/complete/versions.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
terraform {
required_version = ">= 1.0"
required_version = ">= 1.11"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
version = ">= 6.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.7"
}
}
}
71 changes: 43 additions & 28 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
resource "aws_secretsmanager_secret" "this" {
count = var.create ? 1 : 0

region = var.region

description = var.description
force_overwrite_replica_secret = var.force_overwrite_replica_secret
kms_key_id = var.kms_key_id
Expand All @@ -14,11 +16,11 @@ resource "aws_secretsmanager_secret" "this" {
recovery_window_in_days = var.recovery_window_in_days

dynamic "replica" {
for_each = var.replica
for_each = var.replica != null ? var.replica : {}

content {
kms_key_id = try(replica.value.kms_key_id, null)
region = try(replica.value.region, replica.key)
kms_key_id = replica.value.kms_key_id
region = coalesce(replica.value.region, replica.key)
}
}

Expand All @@ -36,18 +38,18 @@ data "aws_iam_policy_document" "this" {
override_policy_documents = var.override_policy_documents

dynamic "statement" {
for_each = var.policy_statements
for_each = var.policy_statements != null ? var.policy_statements : {}

content {
sid = try(statement.value.sid, null)
actions = try(statement.value.actions, null)
not_actions = try(statement.value.not_actions, null)
effect = try(statement.value.effect, null)
resources = try(statement.value.resources, null)
not_resources = try(statement.value.not_resources, null)
sid = statement.value.sid
actions = statement.value.actions
not_actions = statement.value.not_actions
effect = statement.value.effect
resources = statement.value.resources
not_resources = statement.value.not_resources

dynamic "principals" {
for_each = try(statement.value.principals, [])
for_each = statement.value.principals != null ? statement.value.principals : []

content {
type = principals.value.type
Expand All @@ -56,7 +58,7 @@ data "aws_iam_policy_document" "this" {
}

dynamic "not_principals" {
for_each = try(statement.value.not_principals, [])
for_each = statement.value.not_principals != null ? statement.value.not_principals : []

content {
type = not_principals.value.type
Expand All @@ -65,7 +67,7 @@ data "aws_iam_policy_document" "this" {
}

dynamic "condition" {
for_each = try(statement.value.conditions, [])
for_each = statement.value.condition != null ? statement.value.condition : []

content {
test = condition.value.test
Expand All @@ -80,9 +82,11 @@ data "aws_iam_policy_document" "this" {
resource "aws_secretsmanager_secret_policy" "this" {
count = var.create && var.create_policy ? 1 : 0

secret_arn = aws_secretsmanager_secret.this[0].arn
policy = data.aws_iam_policy_document.this[0].json
region = var.region

block_public_policy = var.block_public_policy
policy = data.aws_iam_policy_document.this[0].json
secret_arn = aws_secretsmanager_secret.this[0].arn
}

################################################################################
Expand All @@ -92,19 +96,27 @@ resource "aws_secretsmanager_secret_policy" "this" {
resource "aws_secretsmanager_secret_version" "this" {
count = var.create && !(var.enable_rotation || var.ignore_secret_changes) ? 1 : 0

secret_id = aws_secretsmanager_secret.this[0].id
secret_string = var.create_random_password ? random_password.this[0].result : var.secret_string
secret_binary = var.secret_binary
version_stages = var.version_stages
region = var.region

secret_id = aws_secretsmanager_secret.this[0].id
secret_binary = var.secret_binary
secret_string = var.secret_string
secret_string_wo = var.create_random_password ? ephemeral.random_password.this[0].result : var.secret_string_wo
secret_string_wo_version = var.create_random_password ? coalesce(var.secret_string_wo_version, 0) : var.secret_string_wo_version
version_stages = var.version_stages
}

resource "aws_secretsmanager_secret_version" "ignore_changes" {
count = var.create && (var.enable_rotation || var.ignore_secret_changes) ? 1 : 0

secret_id = aws_secretsmanager_secret.this[0].id
secret_string = var.create_random_password ? random_password.this[0].result : var.secret_string
secret_binary = var.secret_binary
version_stages = var.version_stages
region = var.region

secret_id = aws_secretsmanager_secret.this[0].id
secret_binary = var.secret_binary
secret_string = var.secret_string
secret_string_wo = var.create_random_password ? ephemeral.random_password.this[0].result : var.secret_string_wo
secret_string_wo_version = var.create_random_password ? coalesce(var.secret_string_wo_version, 0) : var.secret_string_wo_version
version_stages = var.version_stages

lifecycle {
ignore_changes = [
Expand All @@ -115,7 +127,7 @@ resource "aws_secretsmanager_secret_version" "ignore_changes" {
}
}

resource "random_password" "this" {
ephemeral "random_password" "this" {
count = var.create && var.create_random_password ? 1 : 0

length = var.random_password_length
Expand All @@ -130,15 +142,18 @@ resource "random_password" "this" {
resource "aws_secretsmanager_secret_rotation" "this" {
count = var.create && var.enable_rotation ? 1 : 0

region = var.region

rotate_immediately = var.rotate_immediately
rotation_lambda_arn = var.rotation_lambda_arn

dynamic "rotation_rules" {
for_each = [var.rotation_rules]
for_each = var.rotation_rules != null ? [var.rotation_rules] : []

content {
automatically_after_days = try(rotation_rules.value.automatically_after_days, null)
duration = try(rotation_rules.value.duration, null)
schedule_expression = try(rotation_rules.value.schedule_expression, null)
automatically_after_days = rotation_rules.value.automatically_after_days
duration = rotation_rules.value.duration
schedule_expression = rotation_rules.value.schedule_expression
}
}

Expand Down
Loading