Skip to content

Commit

Permalink
fix: Make variables more robust
Browse files Browse the repository at this point in the history
Since the module has to support Terraform 0.14+ the option to mark input
variables as `nullable = false` is not an option. Add support to treat
null where appropriate, and add validation rules to all variables.
  • Loading branch information
memes committed Oct 26, 2023
1 parent bd27278 commit 27b9324
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fileignoreconfig:
- filename: examples/simple/main.tf
checksum: b26086277af49d853473caea9f0bbbb62ebb6b7fd16ccde74f57f9d0d9b63444
- filename: variables.tf
checksum: 95224f6924751d18b26f6def930ab78a0e15ecc34fa7f0802a6a1c13bb2b8e59
checksum: 83e1f659c2fed1feacd49f7a1bb6af8c46d4770ec37fe805bc607997ffe60640
- filename: examples/user-managed-replication-accessors/main.tf
checksum: af29e994e68a7587c981ac1dc962a402e604caecf1942098272266706ee42d15
- filename: modules/random/README.md
Expand Down
8 changes: 4 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ resource "google_secret_manager_secret" "secret" {

replication {
dynamic "user_managed" {
for_each = length(var.replication) > 0 ? [1] : []
for_each = try(length(var.replication), 0) > 0 ? [1] : []
content {
dynamic "replicas" {
for_each = var.replication
Expand All @@ -34,7 +34,7 @@ resource "google_secret_manager_secret" "secret" {
}
}
dynamic "auto" {
for_each = length(var.replication) > 0 ? [] : [1]
for_each = try(length(var.replication), 0) > 0 ? [] : [1]
content {
dynamic "customer_managed_encryption" {
for_each = toset(compact([var.auto_replication_kms_key_name]))
Expand All @@ -47,7 +47,7 @@ resource "google_secret_manager_secret" "secret" {
}

dynamic "topics" {
for_each = toset(var.topics)
for_each = var.topics != null ? toset(var.topics) : []
content {
name = topics.value
}
Expand All @@ -74,7 +74,7 @@ resource "google_secret_manager_secret_version" "secret" {
# Note: this module is non-authoritative and will not remove or modify this role
# from accounts that were granted the role outside this module.
resource "google_secret_manager_secret_iam_member" "secret" {
for_each = toset(var.accessors)
for_each = var.accessors != null ? toset(var.accessors) : []
project = var.project_id
secret_id = google_secret_manager_secret.secret.secret_id
role = "roles/secretmanager.secretAccessor"
Expand Down
33 changes: 27 additions & 6 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ EOD
}

variable "auto_replication_kms_key_name" {
type = string
type = string
validation {
condition = coalesce(var.auto_replication_kms_key_name, "unspecified") == "unspecified" ? true : can(regex("^projects/[a-z][a-z0-9-]{4,28}[a-z0-9]/locations/global/keyRings/[a-zA-Z0-9_-]{1,63}/cryptoKeys/[a-zA-Z0-9_-]{1,63}$", var.auto_replication_kms_key_name))
error_message = "The auto_replication_kms_key_name must be null, empty, or a valid global KMS key identifier."
}
default = ""
description = <<EOD
An optional Cloud KMS key name to use with Google managed replication. If the value is empty (default), then a Google
Expand All @@ -34,7 +38,7 @@ variable "replication" {
kms_key_name = string
}))
validation {
condition = length(var.replication) == 0 || length(distinct([for k, v in var.replication : v == null ? "x" : coalesce(lookup(v, "kms_key_name"), "unspecified") == "unspecified" ? "x" : "y"])) == 1
condition = var.replication == null ? true : length(var.replication) == 0 || length(distinct([for k, v in var.replication : v == null ? "x" : coalesce(lookup(v, "kms_key_name"), "unspecified") == "unspecified" ? "x" : "y"])) == 1
error_message = "The replication must contain a Cloud KMS key for all regions, or an empty string/null for all regions."
}
default = {}
Expand Down Expand Up @@ -84,7 +88,7 @@ variable "accessors" {
type = list(string)
default = []
validation {
condition = length(join("", [for acct in var.accessors : can(regex("^(?:group|serviceAccount|user):[^@]+@[^@]*$", acct)) ? "x" : ""])) == length(var.accessors)
condition = var.accessors == null ? true : length(join("", [for acct in var.accessors : can(regex("^(?:group|serviceAccount|user):[^@]+@[^@]*$", acct)) ? "x" : ""])) == length(var.accessors)
error_message = "Each accessors value must be a valid IAM account identifier; e.g. user:[email protected], group:[email protected], serviceAccount:[email protected]."
}
description = <<EOD
Expand All @@ -94,7 +98,13 @@ EOD
}

variable "labels" {
type = map(string)
type = map(string)
validation {
# GCP resource labels must be lowercase alphanumeric, underscore or hyphen,
# and the key must be <= 63 characters in length
condition = var.labels == null ? true : length(compact([for k, v in var.labels : can(regex("^[a-z][a-z0-9_-]{0,62}$", k)) && can(regex("^[a-z0-9_-]{0,63}$", v)) ? "x" : ""])) == length(keys(var.labels))
error_message = "Each label key:value pair must match GCP requirements."
}
default = {}
description = <<EOD
An optional map of label key:value pairs to assign to the secret resources.
Expand All @@ -103,7 +113,14 @@ EOD
}

variable "annotations" {
type = map(string)
type = map(string)
validation {
# GCP resource annotations keys must begin and end with a lowercase alphanumeric character,
# and period, underscore, or hyphen characters; the key must be <= 63 characters in length.
# The values have only a size constraint, which is unenforceable here.
condition = var.annotations == null ? true : length(compact([for k, v in var.annotations : can(regex("^[a-z0-9][a-z0-9._-]{0,61}[a-z0-9]?$", k)) ? "x" : ""])) == length(keys(var.annotations))
error_message = "Each label key:value pair must match GCP requirements."
}
default = {}
description = <<EOD
An optional map of annotation key:value pairs to assign to the secret resources.
Expand All @@ -112,7 +129,11 @@ EOD
}

variable "topics" {
type = list(string)
type = list(string)
validation {
condition = var.topics == null ? true : length(join("", [for topic in var.topics : can(regex("^projects/[a-z][a-z0-9-]{4,28}[a-z0-9]/topics/[^/]+$", topic)) ? "x" : ""])) == length(var.topics)
error_message = "Each topics value must be a valid Pub/Sub Topic id."
}
default = []
description = <<EOD
An optional list of Cloud Pub/Sub topics that will receive control-plane events for the secret.
Expand Down

0 comments on commit 27b9324

Please sign in to comment.