Added CMEK for Secret auto managed (#1739)

Allow to specify custom KMS keys for Secret Manager secrets
This commit is contained in:
luigi-bitonti 2023-11-10 16:45:47 +01:00 committed by GitHub
parent 0f446e89d4
commit d07f8fd33d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 46 deletions

View File

@ -19,7 +19,9 @@ module "secret-manager" {
source = "../../../modules/secret-manager" source = "../../../modules/secret-manager"
project_id = var.project_id project_id = var.project_id
secrets = { secrets = {
(local.ad_user_password_secret) = null (local.ad_user_password_secret) = {
locations = null
}
} }
versions = { versions = {
(local.ad_user_password_secret) = { (local.ad_user_password_secret) = {

View File

@ -57,10 +57,12 @@ module "secret-manager" {
project_id = module.project.project_id project_id = module.project.project_id
source = "../../../modules/secret-manager" source = "../../../modules/secret-manager"
secrets = { secrets = {
github-key = [var.region] github-key = {
} locations = [var.region]
encryption_key = { keys = {
"${var.region}" = var.service_encryption_keys.secretmanager "${var.region}" = var.service_encryption_keys.secretmanager
}
}
} }
iam = { iam = {
github-key = { github-key = {

View File

@ -17,8 +17,10 @@ module "secret-manager" {
source = "./fabric/modules/secret-manager" source = "./fabric/modules/secret-manager"
project_id = "my-project" project_id = "my-project"
secrets = { secrets = {
test-auto = null test-auto = {}
test-manual = ["europe-west1", "europe-west4"] test-manual = {
locations = ["europe-west1", "europe-west4"]
}
} }
} }
# tftest modules=1 resources=2 # tftest modules=1 resources=2
@ -33,8 +35,10 @@ module "secret-manager" {
source = "./fabric/modules/secret-manager" source = "./fabric/modules/secret-manager"
project_id = "my-project" project_id = "my-project"
secrets = { secrets = {
test-auto = null test-auto = {}
test-manual = ["europe-west1", "europe-west4"] test-manual = {
locations = ["europe-west1", "europe-west4"]
}
} }
iam = { iam = {
test-auto = { test-auto = {
@ -57,8 +61,10 @@ module "secret-manager" {
source = "./fabric/modules/secret-manager" source = "./fabric/modules/secret-manager"
project_id = "my-project" project_id = "my-project"
secrets = { secrets = {
test-auto = null test-auto = {}
test-manual = ["europe-west1", "europe-west4"] test-manual = {
locations = ["europe-west1", "europe-west4"]
}
} }
versions = { versions = {
test-auto = { test-auto = {
@ -75,34 +81,40 @@ module "secret-manager" {
### Secret with customer managed encryption key ### Secret with customer managed encryption key
Secrets will be used if an encryption key is set in the `encryption_key` variable for the secret region. 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.
```hcl ```hcl
module "secret-manager" { module "secret-manager" {
source = "./fabric/modules/secret-manager" source = "./fabric/modules/secret-manager"
project_id = "my-project" project_id = "my-project"
secrets = { secrets = {
test-encryption = ["europe-west1", "europe-west4"] test-auto = {
} keys = {
encryption_key = { global = "projects/PROJECT_ID/locations/global/keyRings/KEYRING/cryptoKeys/KEY"
europe-west1 = "projects/PROJECT_ID/locations/europe-west1/keyRings/KEYRING/cryptoKeys/KEY" }
europe-west4 = "projects/PROJECT_ID/locations/europe-west4/keyRings/KEYRING/cryptoKeys/KEY" }
test-auto-nokeys = {}
test-manual = {
locations = ["europe-west1", "europe-west4"]
keys = {
europe-west1 = "projects/PROJECT_ID/locations/europe-west1/keyRings/KEYRING/cryptoKeys/KEY"
europe-west4 = "projects/PROJECT_ID/locations/europe-west4/keyRings/KEYRING/cryptoKeys/KEY"
}
}
} }
} }
# tftest modules=1 resources=1 # tftest modules=1 resources=3
``` ```
<!-- BEGIN TFDOC --> <!-- BEGIN TFDOC -->
## Variables ## Variables
| name | description | type | required | default | | name | description | type | required | default |
|---|---|:---:|:---:|:---:| |---|---|:---:|:---:|:---:|
| [project_id](variables.tf#L35) | Project id where the keyring will be created. | <code>string</code> | ✓ | | | [project_id](variables.tf#L29) | Project id where the keyring will be created. | <code>string</code> | ✓ | |
| [encryption_key](variables.tf#L17) | Self link of the KMS keys in {LOCATION => KEY} format. A key must be provided for all replica locations. | <code>map&#40;string&#41;</code> | | <code>null</code> | | [iam](variables.tf#L17) | IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam](variables.tf#L23) | IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> | | [labels](variables.tf#L23) | Optional labels for each secret. | <code>map&#40;map&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [labels](variables.tf#L29) | Optional labels for each secret. | <code>map&#40;map&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> | | [secrets](variables.tf#L34) | 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. | <code title="map&#40;object&#40;&#123;&#10; locations &#61; optional&#40;list&#40;string&#41;, null&#41;&#10; keys &#61; optional&#40;map&#40;string&#41;, null&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [secrets](variables.tf#L40) | Map of secrets to manage and their locations. If locations is null, automatic management will be set. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> | | [versions](variables.tf#L43) | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | <code title="map&#40;map&#40;object&#40;&#123;&#10; enabled &#61; bool&#10; data &#61; string&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [versions](variables.tf#L46) | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | <code title="map&#40;map&#40;object&#40;&#123;&#10; enabled &#61; bool&#10; data &#61; string&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs ## Outputs
@ -112,7 +124,6 @@ module "secret-manager" {
| [secrets](outputs.tf#L24) | Secret resources. | | | [secrets](outputs.tf#L24) | Secret resources. | |
| [version_ids](outputs.tf#L29) | Version ids keyed by secret name : version name. | | | [version_ids](outputs.tf#L29) | Version ids keyed by secret name : version name. | |
| [versions](outputs.tf#L36) | Secret versions. | ✓ | | [versions](outputs.tf#L36) | Secret versions. | ✓ |
<!-- END TFDOC --> <!-- END TFDOC -->
## Requirements ## Requirements

View File

@ -42,27 +42,32 @@ resource "google_secret_manager_secret" "default" {
labels = lookup(var.labels, each.key, null) labels = lookup(var.labels, each.key, null)
dynamic "replication" { dynamic "replication" {
for_each = each.value == null ? [""] : [] for_each = each.value.locations == null ? [""] : []
content { content {
# TODO(jccb): support custom keys inside auto auto {
auto {} dynamic "customer_managed_encryption" {
for_each = try(lookup(each.value.keys, "global", null) == null ? [] : [""], [])
content {
kms_key_name = each.value.keys["global"]
}
}
}
} }
} }
dynamic "replication" { dynamic "replication" {
for_each = each.value == null ? [] : [each.value] for_each = each.value.locations == null ? [] : [""]
iterator = locations
content { content {
user_managed { user_managed {
dynamic "replicas" { dynamic "replicas" {
for_each = locations.value for_each = each.value.locations
iterator = location iterator = location
content { content {
location = location.value location = location.value
dynamic "customer_managed_encryption" { dynamic "customer_managed_encryption" {
for_each = try(var.encryption_key[location.value] != null ? [""] : [], []) for_each = try(lookup(each.value.keys, location.value, null) == null ? [] : [""], [])
content { content {
kms_key_name = var.encryption_key[location.value] kms_key_name = each.value.keys[location.value]
} }
} }
} }
@ -88,4 +93,4 @@ resource "google_secret_manager_secret_iam_binding" "default" {
role = each.value.role role = each.value.role
secret_id = google_secret_manager_secret.default[each.value.secret].id secret_id = google_secret_manager_secret.default[each.value.secret].id
members = each.value.members members = each.value.members
} }

View File

@ -1,5 +1,5 @@
/** /**
* Copyright 2022 Google LLC * Copyright 2023 Google LLC
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,12 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
variable "encryption_key" {
description = "Self link of the KMS keys in {LOCATION => KEY} format. A key must be provided for all replica locations."
type = map(string)
default = null
}
variable "iam" { variable "iam" {
description = "IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format." description = "IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format."
type = map(map(list(string))) type = map(map(list(string)))
@ -38,9 +32,12 @@ variable "project_id" {
} }
variable "secrets" { variable "secrets" {
description = "Map of secrets to manage and their locations. If locations is null, automatic management will be set." 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."
type = map(list(string)) type = map(object({
default = {} locations = optional(list(string), null)
keys = optional(map(string), null)
}))
default = {}
} }
variable "versions" { variable "versions" {
@ -50,4 +47,4 @@ variable "versions" {
data = string data = string
}))) })))
default = {} default = {}
} }