From 3933a747fe250ff10ef289e8db78957cd73638f5 Mon Sep 17 00:00:00 2001 From: apichick Date: Wed, 26 Jun 2024 08:12:26 +0200 Subject: [PATCH] Fixes related to Apigee KMS keys (#2382) * Fixes related to Apigee KMS keys * tfdoc --------- Co-authored-by: Ludo --- .../apigee/apigee-x-foundations/README.md | 34 ++++++---- .../apigee/apigee-x-foundations/apigee.tf | 55 +++++++++++----- blueprints/apigee/apigee-x-foundations/kms.tf | 65 +++++++++++++++++-- .../apigee/apigee-x-foundations/variables.tf | 49 ++++++++++---- 4 files changed, 154 insertions(+), 49 deletions(-) diff --git a/blueprints/apigee/apigee-x-foundations/README.md b/blueprints/apigee/apigee-x-foundations/README.md index 2b9b24b3a2..665ef035c9 100644 --- a/blueprints/apigee/apigee-x-foundations/README.md +++ b/blueprints/apigee/apigee-x-foundations/README.md @@ -41,7 +41,15 @@ module "apigee-x-foundations" { api_security = true } organization = { - analytics_region = "europe-west1" + analytics_region = "europe-west1" + api_consumer_data_location = "europe-west1" + api_consumer_data_encryption_key_config = { + auto_create = true + } + database_encryption_key_config = { + auto_create = true + } + billing_type = "PAYG" } envgroups = { apis = [ @@ -203,7 +211,7 @@ module "apigee-x-foundations" { ] } } -# tftest modules=10 resources=62 +# tftest modules=7 resources=50 ``` ### Apigee X in service project with peering disabled and exposed using Global LB @@ -279,7 +287,7 @@ module "apigee-x-foundations" { } } } -# tftest modules=6 resources=36 +# tftest modules=4 resources=28 ``` ### Apigee X in standalone project with peering enabled and exposed with Regional Internal LB @@ -361,7 +369,7 @@ module "apigee-x-foundations" { } } } -# tftest modules=8 resources=48 +# tftest modules=6 resources=40 ``` ### Apigee X in standalone project with peering disabled and exposed using Global External Application LB @@ -438,7 +446,7 @@ module "apigee-x-foundations" { } enable_monitoring = true } -# tftest modules=8 resources=55 +# tftest modules=6 resources=47 ``` @@ -460,13 +468,13 @@ module "apigee-x-foundations" { | name | description | type | required | default | producer | |---|---|:---:|:---:|:---:|:---:| -| [apigee_config](variables.tf#L17) | Apigee configuration. | object({…}) | ✓ | | | -| [project_config](variables.tf#L276) | Project configuration. | object({…}) | ✓ | | | -| [enable_monitoring](variables.tf#L92) | Boolean flag indicating whether an custom metric to monitor instances should be created in Cloud monitoring. | bool | | false | | -| [ext_lb_config](variables.tf#L98) | External application load balancer configuration. | object({…}) | | null | | -| [int_cross_region_lb_config](variables.tf#L169) | Internal application load balancer configuration. | object({…}) | | null | | -| [int_lb_config](variables.tf#L197) | Internal application load balancer configuration. | object({…}) | | null | | -| [network_config](variables.tf#L233) | Network configuration. | object({…}) | | {} | | +| [apigee_config](variables.tf#L17) | Apigee configuration. | object({…}) | ✓ | | | +| [project_config](variables.tf#L299) | Project configuration. | object({…}) | ✓ | | | +| [enable_monitoring](variables.tf#L115) | Boolean flag indicating whether an custom metric to monitor instances should be created in Cloud monitoring. | bool | | false | | +| [ext_lb_config](variables.tf#L121) | External application load balancer configuration. | object({…}) | | null | | +| [int_cross_region_lb_config](variables.tf#L192) | Internal application load balancer configuration. | object({…}) | | null | | +| [int_lb_config](variables.tf#L220) | Internal application load balancer configuration. | object({…}) | | null | | +| [network_config](variables.tf#L256) | Network configuration. | object({…}) | | {} | | ## Outputs @@ -478,4 +486,4 @@ module "apigee-x-foundations" { | [int_cross_region_lb_ip_addresses](outputs.tf#L32) | Internal IP addresses. | | | | [int_lb_ip_addresses](outputs.tf#L37) | Internal IP addresses. | | | | [project_id](outputs.tf#L42) | Project. | | | - \ No newline at end of file + diff --git a/blueprints/apigee/apigee-x-foundations/apigee.tf b/blueprints/apigee/apigee-x-foundations/apigee.tf index 86c738b859..e7a99bacaa 100644 --- a/blueprints/apigee/apigee-x-foundations/apigee.tf +++ b/blueprints/apigee/apigee-x-foundations/apigee.tf @@ -14,24 +14,45 @@ * limitations under the License. */ -module "apigee" { - source = "../../../modules/apigee" - project_id = module.project.project_id - organization = merge(var.apigee_config.organization, var.network_config.apigee_vpc != null && !var.apigee_config.organization.disable_vpc_peering ? { - authorized_network = module.apigee_vpc[0].id - } : var.network_config.shared_vpc != null && !var.apigee_config.organization.disable_vpc_peering ? { - authorized_network = module.shared_vpc[0].id - } : {}, - var.apigee_config.organization.database_encryption_key == null ? {} : { - database_encryption_key = module.database_kms[0].keys["database-key"].id - }, { +locals { + control_plan_in_eu_or_us = ( + try(contains(["europe", "us"], + split("-", var.apigee_config.organization.api_consumer_data_location)[0]), false) + ) + organization = merge(var.apigee_config.organization, + { + authorized_network = (var.apigee_config.organization.disable_vpc_peering + ? null : + try(module.apigee_vpc[0].id, module.shared_vpc[0].id) + ) + database_encryption_key = try( + module.database_kms[0].key_ids["database-key"], + var.apigee_config.organization.database_encryption_key_config.id) + api_consumer_data_encryption_key = try( + module.api_consumer_data_kms[0].key_ids["api-consumer-data-key"], + var.apigee_config.organization.api_consumer_data_encryption_key_config.id) + control_plane_encryption_key = try( + module.control_plane_kms[0].key_ids["control-plane-key"], + var.apigee_config.organization.control_plane_encryption_key_config.id) runtime_type = "CLOUD" - }) - envgroups = var.apigee_config.envgroups - environments = var.apigee_config.environments - instances = { for k, v in var.apigee_config.instances : k => merge(v, v.disk_encryption_key == null ? { - disk_encryption_key = module.disks_kms[k].key_ids["disk-key"] - } : {}) } + } + ) + instances = { for k, v in var.apigee_config.instances : k => merge(v, { + disk_encryption_key = try( + module.disks_kms[k].key_ids["disk-key"], + v.disk_encryption_key_config.id, + null + ) + }) } +} + +module "apigee" { + source = "../../../modules/apigee" + project_id = module.project.project_id + organization = local.organization + envgroups = var.apigee_config.envgroups + environments = var.apigee_config.environments + instances = local.instances endpoint_attachments = var.apigee_config.endpoint_attachments addons_config = var.apigee_config.addons_config } diff --git a/blueprints/apigee/apigee-x-foundations/kms.tf b/blueprints/apigee/apigee-x-foundations/kms.tf index 120a118ca3..58b1d48d7c 100644 --- a/blueprints/apigee/apigee-x-foundations/kms.tf +++ b/blueprints/apigee/apigee-x-foundations/kms.tf @@ -15,21 +15,33 @@ */ resource "random_id" "database_kms" { + count = var.apigee_config.organization.database_encryption_key_config.auto_create ? 1 : 0 + byte_length = 4 +} + +resource "random_id" "control_plane_kms" { + count = (var.apigee_config.organization.control_plane_encryption_key_config.auto_create && + local.control_plan_in_eu_or_us) ? 1 : 0 + byte_length = 4 +} + +resource "random_id" "api_consumer_data_kms" { + count = var.apigee_config.organization.api_consumer_data_encryption_key_config.auto_create ? 1 : 0 byte_length = 4 } resource "random_id" "disks_kms" { - for_each = var.apigee_config.instances + for_each = toset([for k, v in var.apigee_config.instances : k if v.disk_encryption_key_config.auto_create]) byte_length = 4 } module "database_kms" { - count = try(var.apigee_config.organization.database_encryption_key, null) == null ? 1 : 0 + count = var.apigee_config.organization.database_encryption_key_config.auto_create ? 1 : 0 source = "../../../modules/kms" project_id = module.project.project_id keyring = { - location = "global" - name = "apigee-${random_id.database_kms.hex}" + location = var.apigee_config.organization.api_consumer_data_location == null ? "global" : var.apigee_config.organization.api_consumer_data_location + name = "apigee-database-${random_id.database_kms[0].hex}" } keys = { database-key = { @@ -43,13 +55,54 @@ module "database_kms" { } } +module "api_consumer_data_kms" { + count = var.apigee_config.organization.api_consumer_data_encryption_key_config.auto_create ? 1 : 0 + source = "../../../modules/kms" + project_id = module.project.project_id + keyring = { + location = var.apigee_config.organization.api_consumer_data_location + name = "apigee-api-consumer-data-${random_id.api_consumer_data_kms[0].hex}" + } + keys = { + api-consumer-data-key = { + purpose = "ENCRYPT_DECRYPT" + rotation_period = "2592000s" + labels = null + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = ["serviceAccount:${module.project.service_accounts.robots.apigee}"] + } + } + } +} + +module "control_plane_kms" { + count = (var.apigee_config.organization.control_plane_encryption_key_config.auto_create + && local.control_plan_in_eu_or_us ? 1 : 0) + source = "../../../modules/kms" + project_id = module.project.project_id + keyring = { + location = var.apigee_config.organization.api_consumer_data_location + name = "apigee-control-plane-${random_id.control_plane_kms[0].hex}" + } + keys = { + control-plane-key = { + purpose = "ENCRYPT_DECRYPT" + rotation_period = "2592000s" + labels = null + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = ["serviceAccount:${module.project.service_accounts.robots.apigee}"] + } + } + } +} + module "disks_kms" { - for_each = var.apigee_config.instances + for_each = toset([for k, v in var.apigee_config.instances : k if v.disk_encryption_key_config.auto_create]) source = "../../../modules/kms" project_id = module.project.project_id keyring = { location = each.key - name = "apigee-${each.key}-${random_id.disks_kms[each.key].hex}" + name = "apigee-disk-${each.value}-${random_id.disks_kms[each.value].hex}" } keys = { disk-key = { diff --git a/blueprints/apigee/apigee-x-foundations/variables.tf b/blueprints/apigee/apigee-x-foundations/variables.tf index 673493edb4..74f22acc71 100644 --- a/blueprints/apigee/apigee-x-foundations/variables.tf +++ b/blueprints/apigee/apigee-x-foundations/variables.tf @@ -25,18 +25,26 @@ variable "apigee_config" { monetization = optional(bool, false) })) organization = object({ - analytics_region = optional(string) - api_consumer_data_encryption_key = optional(string) - api_consumer_data_location = optional(string) - authorized_network = optional(string) - billing_type = optional(string) - control_plane_encryption_key = optional(string) - database_encryption_key = optional(string) - description = optional(string, "Terraform-managed") - disable_vpc_peering = optional(bool, false) - display_name = optional(string) - properties = optional(map(string), {}) - retention = optional(string) + analytics_region = optional(string) + api_consumer_data_encryption_key_config = optional(object({ + auto_create = optional(bool, false) + id = optional(string) + }), {}) + api_consumer_data_location = optional(string) + billing_type = optional(string) + control_plane_encryption_key_config = optional(object({ + auto_create = optional(bool, false) + id = optional(string) + }), {}) + database_encryption_key_config = optional(object({ + auto_create = optional(bool, false) + id = optional(string) + }), {}) + description = optional(string, "Terraform-managed") + disable_vpc_peering = optional(bool, false) + display_name = optional(string) + properties = optional(map(string), {}) + retention = optional(string) }) envgroups = optional(map(list(string)), {}) environments = optional(map(object({ @@ -69,7 +77,10 @@ variable "apigee_config" { type = optional(string) })), {}) instances = optional(map(object({ - disk_encryption_key = optional(string) + disk_encryption_key_config = optional(object({ + auto_create = optional(bool, false) + id = optional(string) + }), {}) environments = optional(list(string), []) external = optional(bool, true) runtime_ip_cidr_range = optional(string) @@ -86,6 +97,18 @@ variable "apigee_config" { alltrue([for k, v in var.apigee_config.endpoint_attachments : length(v.dns_names) == 0])) error_message = "If disable_vpc_peering is true for the organization, DNS names cannot be used for endpoint attachments." } + validation { + condition = !(var.apigee_config.organization.database_encryption_key_config.auto_create && var.apigee_config.organization.database_encryption_key_config.id != null) + error_message = "If the database encryption key is to be created you should not be passing an id." + } + validation { + condition = !(var.apigee_config.organization.api_consumer_data_encryption_key_config.auto_create && var.apigee_config.organization.api_consumer_data_encryption_key_config.id != null) + error_message = "If the api consumer data encryption key is to be created you should not be passing an id." + } + validation { + condition = !(var.apigee_config.organization.control_plane_encryption_key_config.auto_create && var.apigee_config.organization.control_plane_encryption_key_config.id != null) + error_message = "If the control plane encryption key is to be created you should not be passing an id." + } nullable = false }