diff --git a/modules/secret-manager/README.md b/modules/secret-manager/README.md
index b547f476a..51550b43a 100644
--- a/modules/secret-manager/README.md
+++ b/modules/secret-manager/README.md
@@ -6,9 +6,19 @@ Secret Manager locations are available via the `gcloud secrets locations list` c
**Warning:** managing versions will persist their data (the actual secret you want to protect) in the Terraform state in unencrypted form, accessible to any identity able to read or pull the state file.
-## Examples
+
+- [Secrets](#secrets)
+- [Secret IAM bindings](#secret-iam-bindings)
+- [Secret versions](#secret-versions)
+- [Secret with customer managed encryption key](#secret-with-customer-managed-encryption-key)
+- [Variables](#variables)
+- [Outputs](#outputs)
+- [Requirements](#requirements)
+- [IAM](#iam)
+- [APIs](#apis)
+
-### Secrets
+## Secrets
The secret replication policy is automatically managed if no location is set, or manually managed if a list of locations is passed to the secret.
@@ -19,14 +29,15 @@ module "secret-manager" {
secrets = {
test-auto = {}
test-manual = {
- locations = [var.regions.primary, var.regions.secondary]
+ expire_time = "2025-10-02T15:01:23Z"
+ locations = [var.regions.primary, var.regions.secondary]
}
}
}
# tftest modules=1 resources=2 inventory=secret.yaml e2e
```
-### Secret IAM bindings
+## Secret IAM bindings
IAM bindings can be set per secret in the same way as for most other modules supporting IAM, using the `iam` variable.
@@ -52,7 +63,7 @@ module "secret-manager" {
# tftest modules=1 resources=4 inventory=iam.yaml e2e
```
-### Secret versions
+## Secret versions
As mentioned above, please be aware that **version data will be stored in state in unencrypted form**.
@@ -79,7 +90,7 @@ module "secret-manager" {
# tftest modules=1 resources=5 inventory=versions.yaml e2e
```
-### Secret with customer managed encryption key
+## Secret with customer managed encryption key
CMEK will be used if an encryption key is set in the `keys` field of `secrets` object for the secret region. For secrets with auto-replication, a global key must be specified.
@@ -178,12 +189,11 @@ module "secret-manager" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [project_id](variables.tf#L34) | Project id where the keyring will be created. | string | ✓ | |
-| [expire_time](variables.tf#L16) | Timestamp in UTC when the Secret is scheduled to expire. | string | | null |
-| [iam](variables.tf#L22) | IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} |
-| [labels](variables.tf#L28) | Optional labels for each secret. | map(map(string)) | | {} |
-| [secrets](variables.tf#L39) | Map of secrets to manage, their locations and KMS keys in {LOCATION => KEY} format. {GLOBAL => KEY} format enables CMEK for automatic managed secrets. If locations is null, automatic management will be set. | map(object({…})) | | {} |
-| [versions](variables.tf#L48) | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | map(map(object({…}))) | | {} |
+| [project_id](variables.tf#L29) | Project id where the keyring will be created. | string | ✓ | |
+| [iam](variables.tf#L17) | IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} |
+| [labels](variables.tf#L23) | Optional labels for each secret. | map(map(string)) | | {} |
+| [secrets](variables.tf#L34) | Map of secrets to manage, their optional expire time, locations and KMS keys in {LOCATION => KEY} format. {GLOBAL => KEY} format enables CMEK for automatic managed secrets. If locations is null, automatic management will be set. | map(object({…})) | | {} |
+| [versions](variables.tf#L44) | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | map(map(object({…}))) | | {} |
## Outputs
@@ -199,14 +209,14 @@ module "secret-manager" {
These sections describe requirements for using this module.
-### IAM
+## IAM
The following roles must be used to provision the resources of this module:
- Cloud KMS Admin: `roles/cloudkms.admin` or
- Owner: `roles/owner`
-### APIs
+## APIs
A project with the following APIs enabled must be used to host the
resources of this module:
diff --git a/modules/secret-manager/main.tf b/modules/secret-manager/main.tf
index d5df3730c..5c08b4a8e 100644
--- a/modules/secret-manager/main.tf
+++ b/modules/secret-manager/main.tf
@@ -33,7 +33,6 @@ locals {
version_keypairs = {
for pair in local.version_pairs : "${pair.secret}:${pair.name}" => pair
}
- expire_time = var.expire_time != null ? var.expire_time : ""
}
resource "google_secret_manager_secret" "default" {
@@ -41,7 +40,7 @@ resource "google_secret_manager_secret" "default" {
project = var.project_id
secret_id = each.key
labels = lookup(var.labels, each.key, null)
- expire_time = local.expire_time != "" ? local.expire_time : null
+ expire_time = each.value.expire_time
dynamic "replication" {
for_each = each.value.locations == null ? [""] : []
diff --git a/modules/secret-manager/variables.tf b/modules/secret-manager/variables.tf
index 6fb447239..c74db2e67 100644
--- a/modules/secret-manager/variables.tf
+++ b/modules/secret-manager/variables.tf
@@ -13,11 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-variable "expire_time" {
- description = "Timestamp in UTC when the Secret is scheduled to expire."
- type = string
- default = null
-}
variable "iam" {
description = "IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format."
@@ -37,10 +32,11 @@ variable "project_id" {
}
variable "secrets" {
- description = "Map of secrets to manage, their locations and KMS keys in {LOCATION => KEY} format. {GLOBAL => KEY} format enables CMEK for automatic managed secrets. If locations is null, automatic management will be set."
+ description = "Map of secrets to manage, their optional expire time, locations and KMS keys in {LOCATION => KEY} format. {GLOBAL => KEY} format enables CMEK for automatic managed secrets. If locations is null, automatic management will be set."
type = map(object({
- locations = optional(list(string), null)
- keys = optional(map(string), null)
+ expire_time = optional(string)
+ locations = optional(list(string))
+ keys = optional(map(string))
}))
default = {}
}