From 36ccc0998af2e77fdb70d5257842b02664d26765 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Mon, 1 Dec 2025 13:41:50 +0530 Subject: [PATCH 01/15] feat: Monolith example for base-ocp-vpc DA --- README.md | 16 +- common-dev-assets | 2 +- examples/monolith/README.md | 21 + examples/monolith/main.tf | 213 +++ examples/monolith/outputs.tf | 289 +++ examples/monolith/provider.tf | 28 + examples/monolith/variables.tf | 614 ++++++ examples/monolith/version.tf | 21 + modules/monolith/README.md | 265 +++ modules/monolith/main.tf | 708 +++++++ modules/monolith/outputs.tf | 307 +++ modules/monolith/variables.tf | 1684 +++++++++++++++++ modules/monolith/version.tf | 13 + tests/existing-resources-monolith/README.md | 1 + tests/existing-resources-monolith/main.tf | 24 + tests/existing-resources-monolith/outputs.tf | 18 + tests/existing-resources-monolith/provider.tf | 4 + .../existing-resources-monolith/variables.tf | 32 + tests/existing-resources-monolith/version.tf | 9 + tests/other_test.go | 103 + 20 files changed, 4364 insertions(+), 8 deletions(-) create mode 100644 examples/monolith/README.md create mode 100644 examples/monolith/main.tf create mode 100644 examples/monolith/outputs.tf create mode 100644 examples/monolith/provider.tf create mode 100644 examples/monolith/variables.tf create mode 100644 examples/monolith/version.tf create mode 100644 modules/monolith/README.md create mode 100644 modules/monolith/main.tf create mode 100644 modules/monolith/outputs.tf create mode 100644 modules/monolith/variables.tf create mode 100644 modules/monolith/version.tf create mode 100644 tests/existing-resources-monolith/README.md create mode 100644 tests/existing-resources-monolith/main.tf create mode 100644 tests/existing-resources-monolith/outputs.tf create mode 100644 tests/existing-resources-monolith/provider.tf create mode 100644 tests/existing-resources-monolith/variables.tf create mode 100644 tests/existing-resources-monolith/version.tf diff --git a/README.md b/README.md index 66b0d7675..c7ecdf294 100644 --- a/README.md +++ b/README.md @@ -28,15 +28,17 @@ Optionally, the module supports advanced security group management for the worke * [Submodules](./modules) * [fscloud](./modules/fscloud) * [kube-audit](./modules/kube-audit) + * [monolith](./modules/monolith) * [worker-pool](./modules/worker-pool) * [Examples](./examples) - * [2 MZR clusters in same VPC example](./examples/multiple_mzr_clusters) - * [Advanced example (mzr, auto-scale, kms, taints)](./examples/advanced) - * [Attaching custom security groups](./examples/custom_sg) - * [Basic single zone cluster with allowed outbound traffic](./examples/basic) - * [Cluster security group rules example](./examples/add_rules_to_sg) - * [Cross account KMS encryption example](./examples/cross_kms_support) - * [Financial Services compliant example](./examples/fscloud) + *
Cluster security group rules example
Deploy to IBM Cloud button
+ *
Advanced example (mzr, auto-scale, kms, taints)
Deploy to IBM Cloud button
+ *
Basic single zone cluster with allowed outbound traffic
Deploy to IBM Cloud button
+ *
Cross account KMS encryption example
Deploy to IBM Cloud button
+ *
Attaching custom security groups
Deploy to IBM Cloud button
+ *
Financial Services compliant example
Deploy to IBM Cloud button
+ *
IBM Cloud OpenShift DA - Monolith Add-ons Module
Deploy to IBM Cloud button
+ *
2 MZR clusters in same VPC example
Deploy to IBM Cloud button
* [Contributing](#contributing) diff --git a/common-dev-assets b/common-dev-assets index 3cfd2b622..238892ddd 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit 3cfd2b622d864175e7979de6885a65b4fb4ab6db +Subproject commit 238892dddce116998ab6b6ebdb998708401174d1 diff --git a/examples/monolith/README.md b/examples/monolith/README.md new file mode 100644 index 000000000..dac08c088 --- /dev/null +++ b/examples/monolith/README.md @@ -0,0 +1,21 @@ +# IBM Cloud OpenShift DA - Monolith Add-ons Module + +A simple example that shows how to provision a multi zone OCP VPC cluster as well as all foundational infrastructure and supporting services required for a secure and compliant OpenShift (OCP) cluster deployment on IBM Cloud VPC. + +The following resources are provisioned by this example: +- A new resource group, if an existing one is not passed in. +- A Key Protect instance with 2 root keys, one for cluster encryption, and one for worker boot volume encryption. +- A VPC with subnets across 3 zones. +- A public gateway for all the three zones +- A multi-zone (3 zone) KMS encrypted OCP VPC cluster, with worker pools in each zone. +- An additional worker pool named workerpool is created and attached to the cluster using the worker-pool submodule. +- Auto scaling enabled for the default worker pool. +- Taints against the workers in zone-2 and zone-3. +- Enable Kubernetes API server audit logs. +- A Cloud logs instance +- A Cloud monitoring instance +- An activity tracker event routing instance +- A secrets manager instance +- A COS instance along with 3 buckets for VPC flow logs, metrics/data bucket and activity tracker bucket. +- A SCC-WP instance +- A VPC instance diff --git a/examples/monolith/main.tf b/examples/monolith/main.tf new file mode 100644 index 000000000..cf7748270 --- /dev/null +++ b/examples/monolith/main.tf @@ -0,0 +1,213 @@ +######################################################################################################################## +# Resource group +######################################################################################################################## + +module "resource_group" { + source = "terraform-ibm-modules/resource-group/ibm" + version = "1.4.0" + existing_resource_group_name = var.existing_resource_group_name +} + +######################################################################################################################## +# Add-ons +######################################################################################################################## + +module "monolith_add_ons" { + source = "../../modules/monolith" + prefix = var.prefix + region = var.region + resource_group_id = module.resource_group.resource_group_id + kms_encryption_enabled_cluster = var.kms_encryption_enabled_cluster + existing_kms_instance_crn = var.existing_kms_instance_crn + existing_cluster_kms_key_crn = var.existing_cluster_kms_key_crn + kms_endpoint_type = var.kms_endpoint_type + key_protect_allowed_network = var.key_protect_allowed_network + kms_encryption_enabled_boot_volume = var.kms_encryption_enabled_boot_volume + existing_boot_volume_kms_key_crn = var.existing_boot_volume_kms_key_crn + kms_plan = var.kms_plan + existing_secrets_manager_crn = var.existing_secrets_manager_crn + secrets_manager_service_plan = var.secrets_manager_service_plan + secrets_manager_endpoint_type = var.secrets_manager_endpoint_type + secrets_manager_allowed_network = var.secrets_manager_allowed_network + existing_event_notifications_instance_crn = var.existing_event_notifications_instance_crn + existing_cos_instance_crn = var.existing_cos_instance_crn + cos_instance_plan = var.cos_instance_plan + existing_cloud_monitoring_crn = var.existing_cloud_monitoring_crn + cloud_monitoring_plan = var.cloud_monitoring_plan + existing_cloud_logs_crn = var.existing_cloud_logs_crn + scc_workload_protection_service_plan = var.scc_workload_protection_service_plan + enable_vpc_flow_logs = var.enable_vpc_flow_logs +} + +######################################################################################################################## +# OCP VPC cluster +######################################################################################################################## + +locals { + vpc_subnets = { + # The default behavior is to deploy the worker pool across all subnets within the VPC. + "default" = [ + for subnet in module.monolith_add_ons.subnet_zone_list : + { + id = subnet.id + zone = subnet.zone + cidr_block = subnet.cidr + } + ] + } + + worker_pools = concat([ + { + subnet_prefix = "default" + pool_name = "default" + machine_type = var.default_worker_pool_machine_type + workers_per_zone = var.default_worker_pool_workers_per_zone + resource_group_id = module.resource_group.resource_group_id + operating_system = var.default_worker_pool_operating_system + labels = var.default_worker_pool_labels + minSize = var.default_pool_minimum_number_of_nodes + maxSize = var.default_pool_maximum_number_of_nodes + enableAutoscaling = var.enable_autoscaling_for_default_pool + boot_volume_encryption_kms_config = { + crk = module.monolith_add_ons.boot_volume_kms_key_id + kms_instance_id = module.monolith_add_ons.boot_volume_existing_kms_guid + kms_account_id = module.monolith_add_ons.boot_volume_kms_account_id + } + additional_security_group_ids = var.additional_security_group_ids + } + ], [for pool in var.additional_worker_pools : merge(pool, { resource_group_id = module.resource_group.resource_group_id + boot_volume_encryption_kms_config = { + crk = module.monolith_add_ons.boot_volume_kms_key_id + kms_instance_id = module.monolith_add_ons.boot_volume_existing_kms_guid + kms_account_id = module.monolith_add_ons.boot_volume_kms_account_id + } }) if length(pool.vpc_subnets) > 0], + [for pool in var.additional_worker_pools : { + pool_name = pool.pool_name + machine_type = pool.machine_type + workers_per_zone = pool.workers_per_zone + resource_group_id = module.resource_group.resource_group_id + operating_system = pool.operating_system + labels = pool.labels + minSize = pool.minSize + secondary_storage = pool.secondary_storage + maxSize = pool.maxSize + enableAutoscaling = pool.enableAutoscaling + boot_volume_encryption_kms_config = { + crk = module.monolith_add_ons.boot_volume_kms_key_id + kms_instance_id = module.monolith_add_ons.boot_volume_existing_kms_guid + kms_account_id = module.monolith_add_ons.boot_volume_kms_account_id + } + additional_security_group_ids = pool.additional_security_group_ids + subnet_prefix = "default" + } if length(pool.vpc_subnets) == 0]) + + # Managing the ODF version accordingly, as it changes with each OCP version. + addons = lookup(var.addons, "openshift-data-foundation", null) != null ? lookup(var.addons["openshift-data-foundation"], "version", null) == null ? { for key, value in var.addons : + key => value != null ? { + version = lookup(value, "version", null) == null && key == "openshift-data-foundation" ? "${var.openshift_version}.0" : lookup(value, "version", null) + parameters_json = lookup(value, "parameters_json", null) + } : null } : var.addons : var.addons +} + +module "ocp_base" { + depends_on = [module.monolith_add_ons] + source = "../.." + resource_group_id = module.resource_group.resource_group_id + region = var.region + tags = var.cluster_resource_tags + cluster_name = "${var.prefix}-${var.cluster_name}" + force_delete_storage = true + use_existing_cos = true + existing_cos_id = module.monolith_add_ons.cos_instance_id + vpc_id = module.monolith_add_ons.vpc_id + vpc_subnets = local.vpc_subnets + ocp_version = var.openshift_version + worker_pools = local.worker_pools + access_tags = var.access_tags + ocp_entitlement = var.ocp_entitlement + additional_lb_security_group_ids = var.additional_lb_security_group_ids + additional_vpe_security_group_ids = var.additional_vpe_security_group_ids + addons = local.addons + allow_default_worker_pool_replacement = var.allow_default_worker_pool_replacement + attach_ibm_managed_security_group = var.attach_ibm_managed_security_group + cluster_config_endpoint_type = var.cluster_config_endpoint_type + cbr_rules = var.ocp_cbr_rules + cluster_ready_when = var.cluster_ready_when + custom_security_group_ids = var.custom_security_group_ids + disable_outbound_traffic_protection = var.allow_outbound_traffic + disable_public_endpoint = !var.allow_public_access_to_cluster_management + enable_ocp_console = var.enable_ocp_console + ignore_worker_pool_size_changes = var.ignore_worker_pool_size_changes + kms_config = module.monolith_add_ons.kms_config + manage_all_addons = var.manage_all_addons + number_of_lbs = var.number_of_lbs + pod_subnet_cidr = var.pod_subnet_cidr + service_subnet_cidr = var.service_subnet_cidr + verify_worker_network_readiness = var.verify_worker_network_readiness + worker_pools_taints = var.worker_pools_taints + enable_secrets_manager_integration = var.enable_secrets_manager_integration + existing_secrets_manager_instance_crn = module.monolith_add_ons.secrets_manager_crn + secrets_manager_secret_group_id = var.secrets_manager_secret_group_id != null ? var.secrets_manager_secret_group_id : (var.enable_secrets_manager_integration ? module.secret_group[0].secret_group_id : null) + skip_ocp_secrets_manager_iam_auth_policy = var.skip_ocp_secrets_manager_iam_auth_policy +} + +resource "terraform_data" "delete_secrets" { + depends_on = [module.monolith_add_ons] + count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 + input = { + secret_id = module.secret_group[0].secret_group_id + provider_visibility = var.provider_visibility + secrets_manager_instance_id = module.monolith_add_ons.secrets_manager_guid + secrets_manager_region = module.monolith_add_ons.secrets_manager_region + secrets_manager_endpoint = var.secrets_manager_endpoint_type + } + # api key in triggers_replace to avoid it to be printed out in clear text in terraform_data output + triggers_replace = { + api_key = var.ibmcloud_api_key + } + provisioner "local-exec" { + when = destroy + command = "${path.module}/../../solutions/fully-configurable/scripts/delete_secrets.sh ${self.input.secret_id} ${self.input.provider_visibility} ${self.input.secrets_manager_instance_id} ${self.input.secrets_manager_region} ${self.input.secrets_manager_endpoint}" + interpreter = ["/bin/bash", "-c"] + + environment = { + API_KEY = self.triggers_replace.api_key + } + } +} + +module "secret_group" { + count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 + source = "terraform-ibm-modules/secrets-manager-secret-group/ibm" + version = "1.3.15" + region = module.monolith_add_ons.secrets_manager_region + secrets_manager_guid = module.monolith_add_ons.secrets_manager_guid + secret_group_name = module.ocp_base.cluster_id + secret_group_description = "Secret group for storing ingress certificates for cluster ${var.cluster_name} with id: ${module.ocp_base.cluster_id}" + endpoint_type = var.secrets_manager_endpoint_type +} + +data "ibm_container_cluster_config" "cluster_config" { + count = var.enable_kube_audit ? 1 : 0 + cluster_name_id = module.ocp_base.cluster_id + config_dir = "${path.module}/../../kubeconfig" + admin = true + resource_group_id = module.ocp_base.resource_group_id + endpoint_type = var.cluster_config_endpoint_type != "default" ? var.cluster_config_endpoint_type : null +} + +module "kube_audit" { + count = var.enable_kube_audit ? 1 : 0 + ibmcloud_api_key = var.ibmcloud_api_key + source = "../../modules/kube-audit" + cluster_id = module.ocp_base.cluster_id + cluster_resource_group_id = module.ocp_base.resource_group_id + region = module.ocp_base.region + use_private_endpoint = var.use_private_endpoint + cluster_config_endpoint_type = var.cluster_config_endpoint_type + audit_log_policy = var.audit_log_policy + audit_namespace = var.audit_namespace + audit_deployment_name = var.audit_deployment_name + audit_webhook_listener_image = var.audit_webhook_listener_image + audit_webhook_listener_image_tag_digest = var.audit_webhook_listener_image_tag_digest +} diff --git a/examples/monolith/outputs.tf b/examples/monolith/outputs.tf new file mode 100644 index 000000000..ab94ac26d --- /dev/null +++ b/examples/monolith/outputs.tf @@ -0,0 +1,289 @@ +######################################################################################################################## +# Outputs +######################################################################################################################## + + +############################################################################## +# VPC +############################################################################## + +output "vpc_name" { + description = "Name of the VPC created." + value = module.monolith_add_ons.vpc_name +} + +output "vpc_id" { + description = "ID of the VPC created." + value = module.monolith_add_ons.vpc_id +} + +output "vpc_crn" { + description = "CRN of the VPC created." + value = module.monolith_add_ons.vpc_crn +} + +############################################################################## +# Public Gateways +############################################################################## + +output "public_gateways" { + description = "Map of the public gateways by zone." + value = module.monolith_add_ons.public_gateways +} + +############################################################################## +# VPC flow logs +############################################################################## + +output "vpc_flow_logs" { + description = "Details of the VPC flow logs collector." + value = module.monolith_add_ons.vpc_flow_logs +} + +############################################################################## +# Network ACLs +############################################################################## + +output "network_acls" { + description = "List of shortnames and IDs of network ACLs." + value = module.monolith_add_ons.network_acls +} + +############################################################################## +# Subnet Outputs +############################################################################## + +output "subnet_ids" { + description = "The IDs of the subnets." + value = module.monolith_add_ons.subnet_ids +} + +output "private_path_subnet_id" { + description = "The IDs of the subnets." + value = length(module.monolith_add_ons.subnet_ids) > 0 ? module.monolith_add_ons.subnet_ids[0] : null +} + +output "subnet_detail_list" { + description = "A list of subnets containing names, CIDR blocks, and zones." + value = module.monolith_add_ons.subnet_detail_list +} + +output "subnet_zone_list" { + description = "A list of subnet IDs and subnet zones." + value = module.monolith_add_ons.subnet_zone_list +} + +output "subnet_detail_map" { + description = "A map of subnets containing IDs, CIDR blocks, and zones." + value = module.monolith_add_ons.subnet_detail_map +} + +############################################################################## +# VPN Gateways Outputs +############################################################################## + +output "vpn_gateways_name" { + description = "List of names of VPN gateways." + value = module.monolith_add_ons.vpn_gateways_name +} + +output "vpn_gateways_data" { + description = "Details of VPN gateways data." + value = module.monolith_add_ons.vpn_gateways_data +} + +############################################################################## +# VPE Outputs +############################################################################## + +output "vpe_ips" { + description = "The reserved IPs for endpoint gateways." + value = module.monolith_add_ons.vpe_ips +} + +output "vpe_crn" { + description = "The CRN of the endpoint gateway." + value = module.monolith_add_ons.vpe_crn +} + +############################################################################## +# KMS Outputs +############################################################################## + +output "kms_guid" { + description = "Key Protect instance GUID or the KMS instance GUID if existing_kms_instance_crn was set" + value = module.monolith_add_ons.kms_guid +} + +output "kms_account_id" { + description = "The account ID of the KMS instance." + value = module.monolith_add_ons.kms_account_id +} + +output "key_protect_id" { + description = "Key Protect instance ID when an instance is created, otherwise null" + value = module.monolith_add_ons.key_protect_id +} + +output "kms_instance_crn" { + value = module.monolith_add_ons.kms_instance_crn + description = "The CRN of the Hyper Protect Crypto Service instance or Key Protect instance" +} + +############################################################################## +# SM Outputs +############################################################################## + +output "secrets_manager_guid" { + description = "GUID of Secrets Manager instance" + value = module.monolith_add_ons.secrets_manager_guid +} + +output "secrets_manager_crn" { + value = module.monolith_add_ons.secrets_manager_crn + description = "CRN of the Secrets Manager instance" +} + +output "secrets_manager_region" { + value = module.monolith_add_ons.secrets_manager_region + description = "Region of the Secrets Manager instance" +} + +############################################################################## +# COS Outputs +############################################################################## + +output "cos_instance_crn" { + description = "COS instance crn" + value = module.monolith_add_ons.cos_instance_crn +} + +output "cos_instance_guid" { + description = "COS instance guid" + value = module.monolith_add_ons.cos_instance_guid +} + +############################################################################## +# Cloud Monitoring Outputs +############################################################################## + +output "cloud_monitoring_crn" { + value = module.monolith_add_ons.cloud_monitoring_crn + description = "The id of the provisioned IBM Cloud Monitoring instance." +} +output "cloud_monitoring_name" { + value = module.monolith_add_ons.cloud_monitoring_name + description = "The name of the provisioned IBM Cloud Monitoring instance." +} + +output "cloud_monitoring_guid" { + value = module.monolith_add_ons.cloud_monitoring_guid + description = "The guid of the provisioned IBM Cloud Monitoring instance." +} + +output "cloud_monitoring_access_key_name" { + value = module.monolith_add_ons.cloud_monitoring_access_key_name + description = "The name of the IBM Cloud Monitoring access key for agents to use" +} + +output "cloud_monitoring_access_key" { + value = module.monolith_add_ons.cloud_monitoring_access_key + description = "The IBM Cloud Monitoring access key for agents to use" + sensitive = true +} + +############################################################################## +# Cloud Logs Outputs +############################################################################## + +output "cloud_logs_crn" { + value = module.monolith_add_ons.cloud_logs_crn + description = "The id of the provisioned IBM Cloud Logs instance." +} + +output "cloud_logs_guid" { + value = module.monolith_add_ons.cloud_logs_guid + description = "The guid of the provisioned IBM Cloud Logs instance." +} + +output "cloud_logs_name" { + value = module.monolith_add_ons.cloud_logs_name + description = "The name of the provisioned IBM Cloud Logs instance." +} + +output "logs_bucket_crn" { + description = "Logs Cloud Object Storage bucket CRN" + value = module.monolith_add_ons.logs_bucket_crn +} + +output "metrics_bucket_crn" { + description = "Metrics Cloud Object Storage bucket CRN" + value = module.monolith_add_ons.metrics_bucket_crn +} + +############################################################################## +# Activity Tracker Event Routing Outputs +############################################################################## + +output "activity_tracker_cos_target_bucket_name" { + value = module.monolith_add_ons.activity_tracker_cos_target_bucket_name + description = "he name of the object storage bucket which is set as activity tracker event routing target to collect audit events." +} + +output "activity_tracker_targets" { + value = module.monolith_add_ons.activity_tracker_targets + description = "The map of created Activity Tracker Event Routing targets" +} + +output "activity_tracker_routes" { + value = module.monolith_add_ons.activity_tracker_routes + description = "The map of created Activity Tracker Event Routing routes" +} + +############################################################################## +# SCC-WP Outputs +############################################################################## + +output "scc_workload_protection_id" { + description = "SCC Workload Protection instance ID" + value = module.monolith_add_ons.scc_workload_protection_id +} + +output "scc_workload_protection_crn" { + description = "SCC Workload Protection instance CRN" + value = module.monolith_add_ons.scc_workload_protection_crn +} + +output "scc_workload_protection_name" { + description = "SCC Workload Protection instance name" + value = module.monolith_add_ons.scc_workload_protection_name +} + +############################################################################## +# Cluster Outputs +############################################################################## + +output "cluster_name" { + value = module.ocp_base.cluster_name + description = "The name of the provisioned OpenShift cluster." +} + +output "cluster_id" { + value = module.ocp_base.cluster_id + description = "The unique identifier assigned to the provisioned OpenShift cluster." +} + +output "cluster_crn" { + description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." + value = module.ocp_base.cluster_crn +} + +output "workerpools" { + description = "A list of worker pools associated with the provisioned cluster" + value = module.ocp_base.workerpools +} + +output "ocp_version" { + description = "The version of OpenShift running on the provisioned cluster." + value = module.ocp_base.ocp_version +} diff --git a/examples/monolith/provider.tf b/examples/monolith/provider.tf new file mode 100644 index 000000000..df39925fa --- /dev/null +++ b/examples/monolith/provider.tf @@ -0,0 +1,28 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} + +data "ibm_iam_auth_token" "auth_token" {} + +provider "restapi" { + uri = "https://resource-controller.cloud.ibm.com" + headers = { + Authorization = data.ibm_iam_auth_token.auth_token.iam_access_token + } + write_returns_object = true +} + +provider "helm" { + kubernetes = { + host = data.ibm_container_cluster_config.cluster_config[0].host + token = data.ibm_container_cluster_config.cluster_config[0].token + cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config[0].ca_certificate + } +} + +provider "kubernetes" { + host = data.ibm_container_cluster_config.cluster_config[0].host + token = data.ibm_container_cluster_config.cluster_config[0].token + cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config[0].ca_certificate +} diff --git a/examples/monolith/variables.tf b/examples/monolith/variables.tf new file mode 100644 index 000000000..bc9b9416e --- /dev/null +++ b/examples/monolith/variables.tf @@ -0,0 +1,614 @@ +######################################################################################################################## +# Input variables +######################################################################################################################## + +variable "ibmcloud_api_key" { + type = string + description = "The IBM Cloud api token" + sensitive = true +} + +variable "prefix" { + type = string + description = "Prefix for name of all resource created by this example" + default = "mon-eg" + validation { + error_message = "Prefix must begin and end with a letter and contain only letters, numbers, and - characters." + condition = can(regex("^([A-z]|[a-z][-a-z0-9]*[a-z0-9])$", var.prefix)) + } +} + +variable "region" { + type = string + description = "Region where resources are created" + default = "us-south" +} + +variable "provider_visibility" { + description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`." + type = string + default = "private" + validation { + condition = contains(["public", "private", "public-and-private"], var.provider_visibility) + error_message = "Invalid visibility option. Allowed values are `public`, `private`, or `public-and-private`." + } +} + +variable "existing_resource_group_name" { + type = string + description = "The name of an existing resource group to provision the resources." + default = "Default" +} + +variable "existing_event_notifications_instance_crn" { + type = string + description = "The CRN of the Event Notifications service used to enable lifecycle notifications for your Secrets Manager instance." + default = null +} + +variable "kms_encryption_enabled_cluster" { + description = "Set to true to enable KMS encryption for the cluster's Object Storage bucket. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn`." + type = bool + default = true + nullable = false + + validation { + condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_cluster : true + error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_cluster' to true." + } + + validation { + condition = var.existing_cluster_kms_key_crn != null ? var.kms_encryption_enabled_cluster : true + error_message = "If passing a value for 'existing_cluster_kms_key_crn', you should set 'kms_encryption_enabled_cluster' to true." + } +} + +variable "existing_kms_instance_crn" { + type = string + default = null + description = "The CRN of an existing KMS instance (Hyper Protect Crypto Services or Key Protect)." + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)), + var.existing_kms_instance_crn == null, + ]) + error_message = "The provided KMS instance CRN in the input 'existing_kms_instance_crn' in not valid." + } +} + +variable "existing_cluster_kms_key_crn" { + type = string + default = null + description = "The CRN of an existing KMS key to use for encrypting the Object Storage of the Cluster. If no value is set for this variable, specify a value for `existing_kms_instance_crn` variable to create a key ring and key." + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_cluster_kms_key_crn)), + var.existing_cluster_kms_key_crn == null, + ]) + error_message = "The provided KMS key CRN in the input 'existing_cluster_kms_key_crn' in not valid." + } + + validation { + condition = var.existing_cluster_kms_key_crn != null ? var.existing_kms_instance_crn == null : true + error_message = "A value should not be passed for 'existing_kms_instance_crn' when passing an existing key value using the 'existing_cluster_kms_key_crn' input." + } +} + +variable "kms_endpoint_type" { + type = string + description = "The endpoint for communicating with the KMS instance. Possible values: `public`, `private`. Applies only if `kms_encryption_enabled_cluster` is true" + default = "private" + nullable = false + validation { + condition = can(regex("^(public|private)$", var.kms_endpoint_type)) + error_message = "The kms_endpoint_type value must be 'public' or 'private'." + } +} + +variable "key_protect_allowed_network" { + type = string + description = "Allowed network types for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create_key_protect_instance' is set to `true`." + default = "private-only" + validation { + condition = can(regex("private-only|public-and-private", var.key_protect_allowed_network)) + error_message = "The `key_protect_allowed_network` value must be 'private-only' or 'public-and-private'." + } +} + +variable "kms_encryption_enabled_boot_volume" { + type = bool + description = "Set this to true to control the encryption keys used to encrypt the data that for the block storage volumes for VPC. If set to false, the data is encrypted by using randomly generated keys. For more info on encrypting block storage volumes, see https://cloud.ibm.com/docs/vpc?topic=vpc-creating-instances-byok" + default = true + nullable = false + + validation { + condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_boot_volume || var.kms_encryption_enabled_cluster : true + error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_boot_volume' to true." + } + + validation { + condition = var.existing_boot_volume_kms_key_crn != null ? var.kms_encryption_enabled_boot_volume : true + error_message = "If passing a value for 'existing_boot_volume_kms_key_crn', you should set 'kms_encryption_enabled_boot_volume' to true." + } +} + +variable "existing_boot_volume_kms_key_crn" { + type = string + default = null + description = "The CRN of an existing KMS key to use to encrypt the the block storage volumes for VPC. If no value is set for this variable, specify a value for either the `existing_kms_instance_crn` variable to create a key ring and key." + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_boot_volume_kms_key_crn)), + var.existing_boot_volume_kms_key_crn == null, + ]) + error_message = "The provided KMS key CRN in the input 'existing_boot_volume_kms_key_crn' in not valid." + } +} + +variable "kms_plan" { + type = string + description = "Plan for the Key Protect instance. Supported values are 'tiered-pricing' and 'cross-region-resiliency'. Only used if 'create_key_protect_instance' is set to `true`." + default = "tiered-pricing" + # validation performed in terraform-ibm-key-protect module +} + +variable "existing_secrets_manager_crn" { + type = string + description = "The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created." + default = null +} + +variable "secrets_manager_service_plan" { + type = string + description = "The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. You can create only one Trial instance of Secrets Manager per account. Before you can create a new Trial instance, you must delete the existing Trial instance and its reclamation." + default = "standard" + validation { + condition = var.existing_secrets_manager_crn == null ? contains(["standard", "trial"], var.secrets_manager_service_plan) : true + error_message = "Only 'standard' and 'trial' are allowed values for 'secrets_manager_service_plan'. Applies only if not providing a value for the 'existing_secrets_manager_crn' input." + } +} + +variable "secrets_manager_allowed_network" { + type = string + description = "The types of service endpoints to set on the Secrets Manager instance. Possible values are `private-only` or `public-and-private`." + default = "private-only" + validation { + condition = contains(["private-only", "public-and-private"], var.secrets_manager_allowed_network) + error_message = "The specified allowed_network is not a valid selection!" + } +} + +variable "secrets_manager_endpoint_type" { + type = string + description = "The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications." + default = "private" + validation { + condition = contains(["public", "private"], var.secrets_manager_endpoint_type) + error_message = "The specified service endpoint is not a valid selection!" + } +} + +variable "existing_cos_instance_crn" { + type = string + description = "The CRN of an existing Object Storage instance." + default = null +} + +variable "cos_instance_plan" { + description = "The plan to use when Object Storage instances are created." + type = string + default = "standard" + validation { + condition = contains(["standard", "cos-one-rate-plan"], var.cos_instance_plan) + error_message = "The specified plan is not a valid selection!" + } +} + +variable "existing_cloud_monitoring_crn" { + type = string + default = null + description = "The CRN of an existing Cloud Monitoring instance. If not supplied, a new instance will be created." +} + +variable "cloud_monitoring_plan" { + type = string + description = "The IBM Cloud Monitoring plan to provision. Available values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." + default = "graduated-tier" + + validation { + condition = can(regex("^lite$|^graduated-tier$|^graduated-tier-sysdig-secure-plus-monitor$", var.cloud_monitoring_plan)) + error_message = "The plan value must be one of the following: lite, graduated-tier and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." + } + + validation { + condition = (var.cloud_monitoring_plan != "graduated-tier-sysdig-secure-plus-monitor") || var.region == "eu-fr2" + error_message = "When cloud_monitoring_plan is graduated-tier-sysdig-secure-plus-monitor region should be set to eu-fr2." + } +} + +variable "existing_cloud_logs_crn" { + type = string + default = null + description = "The CRN of an existing Cloud Logs instance. If not supplied, a new instance will be created." +} + +variable "scc_workload_protection_service_plan" { + description = "The pricing plan for the Workload Protection instance service. Possible values: `free-trial`, `graduated-tier`." + type = string + default = "graduated-tier" + validation { + error_message = "Plan for Workload Protection instances can only be `free-trial` or `graduated-tier`." + condition = contains( + ["free-trial", "graduated-tier"], + var.scc_workload_protection_service_plan + ) + } +} + +variable "enable_vpc_flow_logs" { + description = "To enable VPC Flow logs, set this to true." + type = bool + nullable = false + default = true +} + +######################################################################################################################## +# OCP VPC cluster +######################################################################################################################## + +variable "cluster_name" { + type = string + description = "The name of the new IBM Cloud OpenShift Cluster. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "openshift" +} + +variable "default_worker_pool_machine_type" { + type = string + description = "The machine type for worker nodes." + default = "bx2.4x16" + validation { + condition = length(regexall("^[a-z0-9]+(?:\\.[a-z0-9]+)*\\.\\d+x\\d+(?:\\.[a-z0-9]+)?$", var.default_worker_pool_machine_type)) > 0 + error_message = "Invalid value provided for the machine type." + } +} + +variable "default_worker_pool_workers_per_zone" { + type = number + description = "Number of worker nodes in each zone of the cluster." + default = 1 +} + +variable "default_worker_pool_operating_system" { + type = string + description = "The operating system installed on the worker nodes." + default = "RHCOS" +} + +variable "default_worker_pool_labels" { + type = map(string) + description = "A set of key-value labels assigned to the worker pool for identification." + default = {} +} + +variable "default_pool_minimum_number_of_nodes" { + type = number + description = "The minimum number of worker nodes allowed in the pool, ensuring at least one worker is always running." + default = 1 +} + +variable "default_pool_maximum_number_of_nodes" { + type = number + description = "The maximum number of worker nodes allowed in the pool, preventing the pool from exceeding three workers." + default = 3 +} + +variable "additional_security_group_ids" { + type = list(string) + description = "A list of security group IDs that are attached to the worker nodes for additional network security controls." + default = [] +} + +variable "additional_worker_pools" { + type = list(object({ + vpc_subnets = optional(list(object({ + id = string + zone = string + cidr_block = string + })), []) + pool_name = string + machine_type = string + workers_per_zone = number + operating_system = string + labels = optional(map(string)) + minSize = optional(number) + secondary_storage = optional(string) + maxSize = optional(number) + enableAutoscaling = optional(bool) + additional_security_group_ids = optional(list(string)) + })) + description = "List of additional worker pools." + default = [] +} + +variable "enable_autoscaling_for_default_pool" { + type = bool + description = "Set `true` to enable automatic scaling of worker based on workload demand." + default = false +} + +variable "addons" { + type = object({ + debug-tool = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + image-key-synchronizer = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + openshift-data-foundation = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + vpc-file-csi-driver = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + static-route = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + cluster-autoscaler = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + vpc-block-csi-driver = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + ibm-storage-operator = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + openshift-ai = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + }) + description = "Map of OCP cluster add-on versions to install (NOTE: The 'vpc-block-csi-driver' add-on is installed by default for VPC clusters and 'ibm-storage-operator' is installed by default in OCP 4.15 and later, however you can explicitly specify it here if you wish to choose a later version than the default one). [Check supported addons and versions here](https://cloud.ibm.com/docs/containers?topic=containers-supported-cluster-addon-versions)." + nullable = false + default = {} +} + +variable "openshift_version" { + type = string + description = "Version of the OpenShift cluster to provision." + default = "4.19" +} + +variable "cluster_resource_tags" { + type = list(string) + description = "Metadata labels describing this cluster deployment, i.e. test." + default = [] +} + +variable "access_tags" { + type = list(string) + description = "A list of access tags to apply to the resources created by the module." + default = [] +} + +variable "ocp_entitlement" { + type = string + description = "Value that is applied to the entitlements for OCP cluster provisioning." + default = null +} + +variable "additional_lb_security_group_ids" { + description = "List of additional security group IDs to add to the load balancers associated with the cluster. Ensure that the `number_of_lbs` variable is set to the number of Load Balancers associated with the cluster. This comes in addition to the IBM maintained security group." + type = list(string) + default = [] + nullable = false +} + +variable "number_of_lbs" { + description = "The total number of Load Balancers in the cluster that should be associated with the security groups defined in `additional_lb_security_group_ids` variable." + type = number + default = 1 + nullable = false +} + +variable "additional_vpe_security_group_ids" { + description = "Additional security groups to add to all existing load balancers. This comes in addition to the IBM maintained security group." + type = object({ + master = optional(list(string), []) + registry = optional(list(string), []) + api = optional(list(string), []) + }) + default = {} +} + +variable "allow_default_worker_pool_replacement" { + type = bool + description = "Set to true to allow the module to recreate a default worker pool. Only use in the case where you are getting an error indicating that the default worker pool cannot be replaced on apply. Once the default worker pool is handled separately, if you wish to make any change to the default worker pool which requires the re-creation of the default pool set this variable to true." + default = false + nullable = false +} + +variable "attach_ibm_managed_security_group" { + description = "Specify whether to attach the IBM-defined default security group (whose name is kube-) to all worker nodes. Only applicable if `custom_security_group_ids` is set." + type = bool + default = true +} + +variable "cluster_config_endpoint_type" { + description = "Specify which type of endpoint to use for cluster config access: 'default', 'private', 'vpe', 'link'. A 'default' value uses the default endpoint of the cluster." + type = string + default = "default" + nullable = false +} + +variable "verify_worker_network_readiness" { + type = bool + description = "By setting this to true, a script runs kubectl commands to verify that all worker nodes can communicate successfully with the master. If the runtime does not have access to the kube cluster to run kubectl commands, set this value to false." + default = true +} + +variable "cluster_ready_when" { + type = string + description = "The cluster is ready based on one of the following:: MasterNodeReady (not recommended), OneWorkerNodeReady, Normal, IngressReady." + default = "IngressReady" +} + +variable "custom_security_group_ids" { + description = "Security groups to add to all worker nodes. This comes in addition to the IBM maintained security group if `attach_ibm_managed_security_group` is set to true. If this variable is set, the default VPC security group is NOT assigned to the worker nodes." + type = list(string) + default = null +} + +variable "allow_outbound_traffic" { + type = bool + description = "Set to true to allow public outbound access from the cluster workers." + default = true +} + +variable "allow_public_access_to_cluster_management" { + type = bool + description = "Set to true to access the cluster through a public cloud service endpoint." + default = true +} + +variable "enable_ocp_console" { + description = "Flag to specify whether to enable or disable the OpenShift console. If set to `null` the module does not modify the current setting on the cluster. Keep in mind that when this input is set to `true` or `false` on a cluster with private only endpoint enabled, the runtime must be able to access the private endpoint." + type = bool + default = null + nullable = true +} + +variable "ignore_worker_pool_size_changes" { + type = bool + description = "Enable if using worker autoscaling. Stops Terraform managing worker count." + default = false +} + +variable "manage_all_addons" { + type = bool + default = false + nullable = false + description = "Instructs deployable architecture to manage all cluster addons, even if addons were installed outside of the module. If set to 'true' this deployable architecture destroys any addons that were installed by other sources." +} + +variable "pod_subnet_cidr" { + type = string + description = "Specify a custom subnet CIDR to provide private IP addresses for pods. The subnet must have a CIDR of at least `/23` or larger. Default value is `172.30.0.0/16` when the variable is set to `null`." + default = null +} + +variable "service_subnet_cidr" { + type = string + description = "Specify a custom subnet CIDR to provide private IP addresses for services. The subnet must be at least `/24` or larger. Default value is `172.21.0.0/16` when the variable is set to `null`." + default = null +} + +variable "worker_pools_taints" { + type = map(list(object({ key = string, value = string, effect = string }))) + description = "Optional, Map of lists containing node taints by node-pool name." + default = null +} + +variable "enable_secrets_manager_integration" { + type = bool + description = "Integrate with IBM Cloud Secrets Manager so you can centrally manage Ingress subdomain certificates and other secrets." + default = true + nullable = false +} + +variable "secrets_manager_secret_group_id" { + type = string + description = "Secret group ID where Ingress secrets are stored in the Secrets Manager instance. If 'enable_secrets_manager_integration' is set to true and 'secrets_manager_secret_group_id' is not provided, a new group will be created with the same name as cluster_id." + default = null +} + +variable "skip_ocp_secrets_manager_iam_auth_policy" { + type = bool + description = "To skip creating auth policy that allows OCP cluster 'Manager' role access in the existing Secrets Manager instance for managing ingress certificates." + default = false +} + +############################################################## +# Kube Audit +############################################################## + +variable "enable_kube_audit" { + type = bool + description = "Kubernetes audit logging provides a chronological record of operations performed on the cluster, including by users, administrators, and system components. It is useful for compliance, and security monitoring. Set true to enable kube audit by default." + default = true +} + +variable "audit_log_policy" { + type = string + description = "Specify the amount of information that is logged to the API server audit logs by choosing the audit log policy profile to use. Supported values are `default` and `WriteRequestBodies`." + default = "default" + + validation { + error_message = "Invalid Audit log policy Type! Valid values are 'default' or 'WriteRequestBodies'" + condition = contains(["default", "WriteRequestBodies"], var.audit_log_policy) + } +} + +variable "audit_namespace" { + type = string + description = "The name of the namespace where log collection service and a deployment will be created." + default = "ibm-kube-audit" +} + +variable "audit_deployment_name" { + type = string + description = "The name of log collection deployment and service." + default = "ibmcloud-kube-audit" +} + +variable "audit_webhook_listener_image" { + type = string + description = "The audit webhook listener image reference in the format of `[registry-url]/[namespace]/[image]`. This solution uses the `icr.io/ibm/ibmcloud-kube-audit-to-ibm-cloud-logs` image to forward logs to IBM Cloud Logs. This image is for demonstration purposes only. For a production solution, configure and maintain your own log forwarding image." + default = "icr.io/ibm/ibmcloud-kube-audit-to-ibm-cloud-logs" +} + +variable "audit_webhook_listener_image_tag_digest" { + type = string + description = "The tag or digest for the audit webhook listener image to deploy. If changing the value, ensure it is compatible with `audit_webhook_listener_image`." + default = "deaabcb8225e800385413ba420cf3f819d3b0671@sha256:acf123f4dba63534cbc104c6886abedff9d25a22a34ab7b549ede988ed6e7144" +} + +variable "use_private_endpoint" { + type = bool + description = "Set this to true to force all API calls to use the IBM Cloud private endpoints." + default = false +} + +variable "ocp_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + tags = optional(list(object({ + name = string + value = string + })), []) + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restriction rules to create." + default = [] +} diff --git a/examples/monolith/version.tf b/examples/monolith/version.tf new file mode 100644 index 000000000..8c94c3ba8 --- /dev/null +++ b/examples/monolith/version.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">=1.9.0" + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = "1.84.3" + } + restapi = { + source = "Mastercard/restapi" + version = "2.0.1" + } + helm = { + source = "hashicorp/helm" + version = "3.0.2" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.38.0" + } + } +} diff --git a/modules/monolith/README.md b/modules/monolith/README.md new file mode 100644 index 000000000..83016376c --- /dev/null +++ b/modules/monolith/README.md @@ -0,0 +1,265 @@ +# Monolith module + +The module acts as a monolithic wrapper around a collection of smaller, official IBM Terraform modules, simplifying the deployment of a compliant, secure, and fully operational environment with a single configuration. This module integrates essential foundational services for security, monitoring, and logging for creating a fully configurable OCP cluster on an IBM Cloud Virtual Private Cloud. + +### Components + +The primary goal of this module is to provision an OpenShift cluster on VPC and automatically configure the necessary supporting services, including: +* `VPC Infrastructure`: The base VPC, subnets, and network access controls (ACLs) for the OpenShift cluster. +* `Key Management (KMS)`: Optional provision and configuration of an IBM Key Protect or Hyper Protect Crypto Services (HPCS) instance for encrypting cluster and boot volumes. +* `Secrets Management`: Optional provision and configuration of an IBM Secrets Manager instance to securely store service credentials and other secrets. +* `Cloud Object Storage (COS)`: Optional provision and configuration of COS instances and buckets for flow logs, activity tracker, and other data storage needs. +* `Monitoring & Logging`: Optional provision and configuration of IBM Cloud Monitoring and IBM Cloud Logs instances for centralized observability. +* `Activity Tracker and Event Routing`: Configure event routing for platform audit logs to a COS bucket or IBM Cloud Logs. +* `Security & Compliance`: Optional integration with IBM Cloud Security and Compliance Center (SCC) Workload Protection. +* `VPE Gateways`: Optional configuration of Virtual Private Endpoint (VPE) gateways for secure private connectivity to cloud services. + +## Usage + +```hcl +module "monolith_ocp_add_ons" { + source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/monolith" + version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release + prefix = "" + region = "us-south" + resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" + existing_event_notifications_instance_crn = var.existing_event_notifications_instance_crn +} +``` + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >=1.9.0 | +| [ibm](#requirement\_ibm) | >= 1.78.2, < 2.0.0 | +| [time](#requirement\_time) | >= 0.9.1, < 1.0.0 | + +### Modules + +| Name | Source | Version | +|------|--------|---------| +| [activity\_tracker](#module\_activity\_tracker) | terraform-ibm-modules/activity-tracker/ibm | 1.5.0 | +| [at\_cos\_bucket](#module\_at\_cos\_bucket) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | +| [cloud\_logs](#module\_cloud\_logs) | terraform-ibm-modules/cloud-logs/ibm | 1.10.0 | +| [cloud\_logs\_buckets](#module\_cloud\_logs\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.7 | +| [cloud\_monitoring](#module\_cloud\_monitoring) | terraform-ibm-modules/cloud-monitoring/ibm | 1.11.0 | +| [cos](#module\_cos) | terraform-ibm-modules/cos/ibm//modules/fscloud | 10.5.9 | +| [existing\_boot\_volume\_kms\_key\_crn\_parser](#module\_existing\_boot\_volume\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.2.0 | +| [existing\_cloud\_monitoring\_crn\_parser](#module\_existing\_cloud\_monitoring\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | +| [existing\_cluster\_kms\_key\_crn\_parser](#module\_existing\_cluster\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.2.0 | +| [existing\_cos\_instance\_crn\_parser](#module\_existing\_cos\_instance\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | +| [existing\_kms\_crn\_parser](#module\_existing\_kms\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.2.0 | +| [kms](#module\_kms) | terraform-ibm-modules/kms-all-inclusive/ibm | 5.4.5 | +| [metrics\_routing](#module\_metrics\_routing) | terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing | 1.11.0 | +| [scc\_wp](#module\_scc\_wp) | terraform-ibm-modules/scc-workload-protection/ibm | 1.16.4 | +| [secrets\_manager](#module\_secrets\_manager) | terraform-ibm-modules/secrets-manager/ibm | 2.11.9 | +| [secrets\_manager\_crn\_parser](#module\_secrets\_manager\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | +| [secrets\_manager\_service\_credentials](#module\_secrets\_manager\_service\_credentials) | terraform-ibm-modules/secrets-manager/ibm//modules/secrets | 2.11.9 | +| [vpc](#module\_vpc) | terraform-ibm-modules/landing-zone-vpc/ibm | 8.9.1 | +| [vpc\_cos\_buckets](#module\_vpc\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | +| [vpe\_gateway](#module\_vpe\_gateway) | terraform-ibm-modules/vpe-gateway/ibm | 4.6.6 | + +### Resources + +| Name | Type | +|------|------| +| [ibm_en_subscription_email.email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | +| [ibm_en_topic.en_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | +| [ibm_iam_authorization_policy.secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [time_sleep.wait_for_cos_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [time_sleep.wait_for_secrets_manager](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [ibm_en_destinations.en_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [activity\_tracker\_cloud\_logs\_route\_name](#input\_activity\_tracker\_cloud\_logs\_route\_name) | Name of the cloud logs route for activity tracker event routing. | `string` | `null` | no | +| [activity\_tracker\_cos\_bucket\_access\_tags](#input\_activity\_tracker\_cos\_bucket\_access\_tags) | A list of optional access tags to add to the IBM Cloud Activity Tracker Event Routing Cloud Object Storage bucket. | `list(string)` | `[]` | no | +| [activity\_tracker\_cos\_bucket\_retention\_policy](#input\_activity\_tracker\_cos\_bucket\_retention\_policy) | The retention policy of the IBM Cloud Activity Tracker Event Routing COS target bucket. |
object({
default = optional(number, 90)
maximum = optional(number, 350)
minimum = optional(number, 90)
permanent = optional(bool, false)
})
| `null` | no | +| [activity\_tracker\_cos\_route\_name](#input\_activity\_tracker\_cos\_route\_name) | Name of the cos route for activity tracker event routing. | `string` | `null` | no | +| [activity\_tracker\_cos\_target\_bucket\_class](#input\_activity\_tracker\_cos\_target\_bucket\_class) | The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`. | `string` | `"smart"` | no | +| [activity\_tracker\_cos\_target\_bucket\_name](#input\_activity\_tracker\_cos\_target\_bucket\_name) | The name of the Cloud Object Storage bucket to create for the Cloud Object Storage target to store AT events. Cloud Object Storage bucket names are globally unique. If the `add_bucket_name_suffix` variable is set to `true`, 4 random characters are added to this name to ensure that the name of the bucket is globally unique. If the prefix input variable is passed, the name of the instance is prefixed to the value in the `-value` format. | `string` | `"at-events-cos-bucket"` | no | +| [address\_prefixes](#input\_address\_prefixes) | The IP range that will be defined for the VPC for a certain location. Use only with manual address prefixes. |
object({
zone-1 = optional(list(string))
zone-2 = optional(list(string))
zone-3 = optional(list(string))
})
|
{
"zone-1": null,
"zone-2": null,
"zone-3": null
}
| no | +| [app\_config\_crn](#input\_app\_config\_crn) | The CRN of an existing App Config instance to use with the SCC Workload Protection instance. Required if `cspm_enabled` is true. NOTE: Ensure the App Config instance has configuration aggregator enabled. | `string` | `null` | no | +| [append\_random\_bucket\_name\_suffix](#input\_append\_random\_bucket\_name\_suffix) | Append random generated suffix (4 characters long) to the newly provisioned IBM Cloud Logs Object Storage bucket names. | `bool` | `true` | no | +| [boot\_volume\_kms\_key\_name](#input\_boot\_volume\_kms\_key\_name) | The name for the key created for the block storage volumes. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key"` | no | +| [boot\_volume\_kms\_key\_ring\_name](#input\_boot\_volume\_kms\_key\_ring\_name) | The name for the key ring created for the block storage volumes key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key-ring"` | no | +| [clean\_default\_security\_group\_acl](#input\_clean\_default\_security\_group\_acl) | Remove all rules from the default VPC security group and VPC ACL (less permissive). | `bool` | `true` | no | +| [cloud\_logs\_access\_tags](#input\_cloud\_logs\_access\_tags) | A list of access tags to apply to the IBM Cloud Logs instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | +| [cloud\_logs\_cbr\_rules](#input\_cloud\_logs\_cbr\_rules) | (Optional, list) List of context-based restrictions rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [cloud\_logs\_cos\_buckets\_class](#input\_cloud\_logs\_cos\_buckets\_class) | The storage class of the newly provisioned IBM Cloud Logs Object Storage buckets. Possible values: `standard` or `smart`. Applies only if `existing_cloud_logs_crn` is not provided. | `string` | `"smart"` | no | +| [cloud\_logs\_data\_cos\_bucket\_name](#input\_cloud\_logs\_data\_cos\_bucket\_name) | The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs-logs-bucket"` | no | +| [cloud\_logs\_instance\_name](#input\_cloud\_logs\_instance\_name) | The name of the IBM Cloud Logs instance to create. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs"` | no | +| [cloud\_logs\_metrics\_cos\_bucket\_name](#input\_cloud\_logs\_metrics\_cos\_bucket\_name) | The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs-metrics-bucket"` | no | +| [cloud\_logs\_resource\_tags](#input\_cloud\_logs\_resource\_tags) | Tags associated with the IBM Cloud Logs instance (Optional, array of strings). | `list(string)` | `[]` | no | +| [cloud\_logs\_retention\_period](#input\_cloud\_logs\_retention\_period) | The number of days IBM Cloud Logs will retain the logs data in Priority insights. Allowed values: 7, 14, 30, 60, 90. | `number` | `7` | no | +| [cloud\_logs\_target\_name](#input\_cloud\_logs\_target\_name) | Name of the cloud logs target for activity tracker event routing. | `string` | `null` | no | +| [cloud\_monitoring\_access\_tags](#input\_cloud\_monitoring\_access\_tags) | A list of access tags to apply to the IBM Cloud Monitoring instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | +| [cloud\_monitoring\_cbr\_rules](#input\_cloud\_monitoring\_cbr\_rules) | The list of context-based restriction rules to create for the instance. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [cloud\_monitoring\_instance\_name](#input\_cloud\_monitoring\_instance\_name) | The name of the IBM Cloud Monitoring instance to create. If the prefix variable is passed, the name of the instance is prefixed to the value in the `-value` format. | `string` | `"cloud-monitoring"` | no | +| [cloud\_monitoring\_plan](#input\_cloud\_monitoring\_plan) | The IBM Cloud Monitoring plan to provision. Available values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only). | `string` | `"graduated-tier"` | no | +| [cloud\_monitoring\_resource\_keys](#input\_cloud\_monitoring\_resource\_keys) | A list of maps representing resource keys to create for the IBM Cloud Monitoring instance. Each entry defines a single resource key. Use this list to manage custom keys and handle key rotation. |
list(object({
name = string
generate_hmac_credentials = optional(bool, false) # pragma: allowlist secret
role = optional(string, "Manager")
service_id_crn = optional(string, null)
}))
| `[]` | no | +| [cloud\_monitoring\_resource\_tags](#input\_cloud\_monitoring\_resource\_tags) | Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings). | `list(string)` | `[]` | no | +| [cluster\_kms\_key\_name](#input\_cluster\_kms\_key\_name) | The name of the key to be created for the cluster's Object Storage bucket encryption. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key"` | no | +| [cluster\_kms\_key\_ring\_name](#input\_cluster\_kms\_key\_ring\_name) | The name of the key ring to be created for the cluster's Object Storage bucket encryption key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key-ring"` | no | +| [cos\_instance\_access\_tags](#input\_cos\_instance\_access\_tags) | A list of access tags to apply to the Object Storage instance created by the module. | `list(string)` | `[]` | no | +| [cos\_instance\_cbr\_rules](#input\_cos\_instance\_cbr\_rules) | The list of context-based restriction rules to create for the instance. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [cos\_instance\_name](#input\_cos\_instance\_name) | The name for the IBM Cloud Object Storage instance provisioned by this solution. If a value is passed for `prefix`, the instance will be named with the prefix value in the format of `-value`. | `string` | `"cos-instance"` | no | +| [cos\_instance\_plan](#input\_cos\_instance\_plan) | The plan to use when Object Storage instances are created. | `string` | `"standard"` | no | +| [cos\_instance\_resource\_tags](#input\_cos\_instance\_resource\_tags) | A list of resource tags to apply to the Object Storage instance. | `list(string)` | `[]` | no | +| [cos\_target\_name](#input\_cos\_target\_name) | Name of the cos target for activity tracker event routing. | `string` | `null` | no | +| [cspm\_enabled](#input\_cspm\_enabled) | Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service. | `bool` | `false` | no | +| [default\_network\_acl\_name](#input\_default\_network\_acl\_name) | Name of the Default ACL. If null, a name will be automatically generated. | `string` | `null` | no | +| [default\_routing\_table\_name](#input\_default\_routing\_table\_name) | Name of the Default Routing Table. If null, a name will be automatically generated. | `string` | `null` | no | +| [default\_security\_group\_name](#input\_default\_security\_group\_name) | Name of the Default Security Group. If null, a name will be automatically generated. | `string` | `null` | no | +| [disable\_access\_key\_creation](#input\_disable\_access\_key\_creation) | When set to true, disables the creation of a default manager access key which is required by agents to ingest metrics. | `bool` | `false` | no | +| [dual\_auth\_delete\_enabled](#input\_dual\_auth\_delete\_enabled) | If set to `true`, a dual authorization policy is enabled on the Key Protect instance. After the dual authorization policy is set on the instance, it cannot be reverted. An instance with dual authorization policy enabled cannot be destroyed by using Terraform. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `false` | no | +| [enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs](#input\_enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs) | When set to `true`, you must provide a value for `existing_cloud_logs_crn` to enable event routing from Activity Tracker to a Cloud Logs instance. | `bool` | `true` | no | +| [enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket](#input\_enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket) | When set to `true`, you must provide a value for `existing_cos_instance_crn` to enable event routing from Activity Tracker to a Object Storage bucket. | `bool` | `true` | no | +| [enable\_metrics](#input\_enable\_metrics) | Set to `true` to enable metrics on the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. In order to view metrics, you need an IBM Cloud Monitoring (Sysdig) instance that is located in the same region as the Key Protect instance. After you provision a Monitoring instance, enable platform metrics to monitor your Key Protect instance. | `bool` | `true` | no | +| [enable\_metrics\_routing\_to\_cloud\_monitoring](#input\_enable\_metrics\_routing\_to\_cloud\_monitoring) | Whether to enable metrics routing from IBM Cloud Metric Routing to Cloud Monitoring. | `bool` | `true` | no | +| [enable\_platform\_metrics](#input\_enable\_platform\_metrics) | When set to `true`, the IBM Cloud Monitoring instance collects the platform metrics. | `bool` | `false` | no | +| [enable\_primary\_metadata\_region](#input\_enable\_primary\_metadata\_region) | When set to `true`, sets `primary_metadata_region` to `region`, storing Metrics Router metadata in that region. When `false`, no region is set and the default global region is used. For new accounts, creating targets and routes will fail until primary\_metadata\_region is set, so it is recommended to default enable\_primary\_metadata\_region to true. | `bool` | `true` | no | +| [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | To enable VPC Flow logs, set this to true. | `bool` | `false` | no | +| [event\_notifications\_email\_list](#input\_event\_notifications\_email\_list) | The list of email address to target out when Secrets Manager triggers an event | `list(string)` | `[]` | no | +| [event\_notifications\_from\_email](#input\_event\_notifications\_from\_email) | The email address used to send any Secrets Manager event coming via Event Notifications | `string` | `"compliancealert@ibm.com"` | no | +| [event\_notifications\_reply\_to\_email](#input\_event\_notifications\_reply\_to\_email) | The email address specified in the 'reply\_to' section for any Secret Manager event coming via Event Notifications | `string` | `"no-reply@ibm.com"` | no | +| [existing\_activity\_tracker\_cos\_target\_bucket\_endpoint](#input\_existing\_activity\_tracker\_cos\_target\_bucket\_endpoint) | The name of an existing Cloud Object Storage bucket endpoint to use for setting up IBM Cloud Activity Tracker Event Routing. If an existing endpoint is not specified, the endpoint of the new Cloud Object Storage bucket is used. | `string` | `null` | no | +| [existing\_activity\_tracker\_cos\_target\_bucket\_name](#input\_existing\_activity\_tracker\_cos\_target\_bucket\_name) | The name of an existing bucket within the Cloud Object Storage instance in which to store IBM Cloud Activity Tracker Event Routing. If an existing Cloud Object Storage bucket is not specified, a bucket is created. | `string` | `null` | no | +| [existing\_boot\_volume\_kms\_key\_crn](#input\_existing\_boot\_volume\_kms\_key\_crn) | The CRN of an existing KMS key to use to encrypt the the block storage volumes for VPC. If no value is set for this variable, specify a value for either the `existing_kms_instance_crn` variable to create a key ring and key. | `string` | `null` | no | +| [existing\_cloud\_logs\_crn](#input\_existing\_cloud\_logs\_crn) | The CRN of an existing Cloud Logs instance. If not supplied, a new instance will be created. | `string` | `null` | no | +| [existing\_cloud\_monitoring\_crn](#input\_existing\_cloud\_monitoring\_crn) | The CRN of an existing Cloud Monitoring instance. If not supplied, a new instance will be created. | `string` | `null` | no | +| [existing\_cluster\_kms\_key\_crn](#input\_existing\_cluster\_kms\_key\_crn) | The CRN of an existing KMS key to use for encrypting the Object Storage of the Cluster. If no value is set for this variable, specify a value for `existing_kms_instance_crn` variable to create a key ring and key. | `string` | `null` | no | +| [existing\_cos\_instance\_crn](#input\_existing\_cos\_instance\_crn) | The CRN of an existing Object Storage instance. | `string` | `null` | no | +| [existing\_event\_notifications\_instance\_crn](#input\_existing\_event\_notifications\_instance\_crn) | The CRN of the Event Notifications service used to enable lifecycle notifications for your Secrets Manager instance. | `string` | `null` | no | +| [existing\_event\_notifications\_instances](#input\_existing\_event\_notifications\_instances) | List of Event Notifications instance details for routing critical events that occur in your IBM Cloud Logs. |
list(object({
crn = string
integration_name = optional(string)
skip_iam_auth_policy = optional(bool, false)
}))
| `[]` | no | +| [existing\_kms\_instance\_crn](#input\_existing\_kms\_instance\_crn) | The CRN of an existing KMS instance (Hyper Protect Crypto Services or Key Protect). | `string` | `null` | no | +| [existing\_secrets\_manager\_crn](#input\_existing\_secrets\_manager\_crn) | The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created. | `string` | `null` | no | +| [flow\_logs\_cos\_bucket\_archive\_days](#input\_flow\_logs\_cos\_bucket\_archive\_days) | The number of days before the `archive_type` rule action takes effect for the flow logs cloud object storage bucket. | `number` | `90` | no | +| [flow\_logs\_cos\_bucket\_archive\_type](#input\_flow\_logs\_cos\_bucket\_archive\_type) | The storage class or archive type you want the object to transition to in the flow logs cloud object storage bucket. | `string` | `"Glacier"` | no | +| [flow\_logs\_cos\_bucket\_default\_retention\_days](#input\_flow\_logs\_cos\_bucket\_default\_retention\_days) | The number of days that an object can remain unmodified in the flow logs cloud object storage bucket. | `number` | `90` | no | +| [flow\_logs\_cos\_bucket\_enable\_object\_versioning](#input\_flow\_logs\_cos\_bucket\_enable\_object\_versioning) | Set it to true if object versioning is enabled so that multiple versions of an object are retained in the flow logs cloud object storage bucket. Cannot be used if `flow_logs_cos_bucket_enable_retention` is true. | `bool` | `false` | no | +| [flow\_logs\_cos\_bucket\_enable\_permanent\_retention](#input\_flow\_logs\_cos\_bucket\_enable\_permanent\_retention) | Whether permanent retention status is enabled for the flow logs cloud object storage bucket. | `bool` | `false` | no | +| [flow\_logs\_cos\_bucket\_enable\_retention](#input\_flow\_logs\_cos\_bucket\_enable\_retention) | Set to true to enable retention for the flow logs cloud object storage bucket. | `bool` | `false` | no | +| [flow\_logs\_cos\_bucket\_expire\_days](#input\_flow\_logs\_cos\_bucket\_expire\_days) | The number of days before the expire rule action takes effect for the flow logs cloud object storage bucket. | `number` | `366` | no | +| [flow\_logs\_cos\_bucket\_maximum\_retention\_days](#input\_flow\_logs\_cos\_bucket\_maximum\_retention\_days) | The maximum number of days that an object can be kept unmodified in the flow logs cloud object storage. | `number` | `350` | no | +| [flow\_logs\_cos\_bucket\_minimum\_retention\_days](#input\_flow\_logs\_cos\_bucket\_minimum\_retention\_days) | The minimum number of days that an object must be kept unmodified in the flow logs cloud object storage. | `number` | `90` | no | +| [flow\_logs\_cos\_bucket\_name](#input\_flow\_logs\_cos\_bucket\_name) | Name of the Cloud Object Storage bucket to be created to collect VPC flow logs. | `string` | `"flow-logs-bucket"` | no | +| [key\_create\_import\_access\_enabled](#input\_key\_create\_import\_access\_enabled) | If set to `true`, a key create and import access policy is enabled on the instance of Key Protect. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `true` | no | +| [key\_protect\_allowed\_network](#input\_key\_protect\_allowed\_network) | Allowed network types for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"private-only"` | no | +| [kms\_access\_tags](#input\_kms\_access\_tags) | A list of access tags to apply to the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `list(string)` | `[]` | no | +| [kms\_cbr\_rules](#input\_kms\_cbr\_rules) | The context-based restrictions rule to create. Only one rule is allowed. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [kms\_encryption\_enabled\_boot\_volume](#input\_kms\_encryption\_enabled\_boot\_volume) | Set this to true to control the encryption keys used to encrypt the data that for the block storage volumes for VPC. If set to false, the data is encrypted by using randomly generated keys. For more info on encrypting block storage volumes, see https://cloud.ibm.com/docs/vpc?topic=vpc-creating-instances-byok | `bool` | `false` | no | +| [kms\_encryption\_enabled\_buckets](#input\_kms\_encryption\_enabled\_buckets) | Set to true to enable KMS encryption on the Object Storage buckets created for the IBM Cloud Logs instance. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn` (to create a new key). Can not be set to true if passing a value for `existing_cloud_logs_crn`. | `bool` | `false` | no | +| [kms\_encryption\_enabled\_cluster](#input\_kms\_encryption\_enabled\_cluster) | Set to true to enable KMS encryption for the cluster's Object Storage bucket. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn`. | `bool` | `false` | no | +| [kms\_endpoint\_type](#input\_kms\_endpoint\_type) | The endpoint for communicating with the KMS instance. Possible values: `public`, `private`. Applies only if `kms_encryption_enabled_cluster` is true | `string` | `"private"` | no | +| [kms\_instance\_name](#input\_kms\_instance\_name) | The name to give the Key Protect instance that that is created by this module. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"key-protect"` | no | +| [kms\_plan](#input\_kms\_plan) | Plan for the Key Protect instance. Supported values are 'tiered-pricing' and 'cross-region-resiliency'. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"tiered-pricing"` | no | +| [kms\_resource\_tags](#input\_kms\_resource\_tags) | Optional list of tags to add to the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `list(string)` | `[]` | no | +| [logs\_policies](#input\_logs\_policies) | Configuration of Cloud Logs policies. |
list(object({
logs_policy_name = string
logs_policy_description = optional(string, null)
logs_policy_priority = string
application_rule = optional(list(object({
name = string
rule_type_id = string
})))
subsystem_rule = optional(list(object({
name = string
rule_type_id = string
})))
log_rules = optional(list(object({
severities = list(string)
})))
archive_retention = optional(list(object({
id = string
})))
}))
| `[]` | no | +| [logs\_routing\_tenant\_regions](#input\_logs\_routing\_tenant\_regions) | Pass a list of regions to create a tenant for that is targeted to the Cloud Logs instance created by this module. To manage platform logs that are generated by IBM Cloud® services in a region of IBM Cloud, you must create a tenant in each region that you operate. Leave the list empty if you don't want to create any tenants. NOTE: You can only have 1 tenant per region in an account. | `list(any)` | `[]` | no | +| [management\_endpoint\_type\_for\_buckets](#input\_management\_endpoint\_type\_for\_buckets) | The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Possible values: `public`, `private`, `direct`. If you specify `private`, enable virtual routing and forwarding in your account, and the Terraform runtime must have access to the the IBM Cloud private network. | `string` | `"direct"` | no | +| [metrics\_router\_routes](#input\_metrics\_router\_routes) | Routes for IBM Cloud Metrics Routing. |
list(object({
name = string
rules = list(object({
action = string
targets = list(object({
id = string
}))
inclusion_filters = list(object({
operand = string
operator = string
values = list(string)
}))
}))
}))
| `[]` | no | +| [metrics\_routing\_route\_name](#input\_metrics\_routing\_route\_name) | The name of the IBM Cloud Metrics Routing route for the default route that indicate what metrics are routed in a region and where to store them. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"metrics-routing-route"` | no | +| [metrics\_routing\_target\_name](#input\_metrics\_routing\_target\_name) | The name of the IBM Cloud Metrics Routing target where metrics are collected. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"cloud-monitoring-target"` | no | +| [network\_acls](#input\_network\_acls) | The list of ACLs to create. Provide at least one rule for each ACL. |
list(
object({
name = string
add_ibm_cloud_internal_rules = optional(bool)
add_vpc_connectivity_rules = optional(bool)
prepend_ibm_rules = optional(bool)
rules = list(
object({
name = string
action = string
destination = string
direction = string
source = string
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
})
)
|
[
{
"add_ibm_cloud_internal_rules": true,
"add_vpc_connectivity_rules": true,
"name": "vpc-acl",
"prepend_ibm_rules": true,
"rules": [
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-443-inbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443,
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-80-inbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 80,
"port_min": 80,
"source_port_max": 80,
"source_port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-22-inbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 22,
"port_min": 22,
"source_port_max": 22,
"source_port_min": 22
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-443-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443,
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-80-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 80,
"port_min": 80,
"source_port_max": 80,
"source_port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-22-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 22,
"port_min": 22,
"source_port_max": 22,
"source_port_min": 22
}
}
]
}
]
| no | +| [prefix](#input\_prefix) | The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string. | `string` | n/a | yes | +| [region](#input\_region) | The region to provision all resources in. | `string` | `"us-south"` | no | +| [resource\_group\_id](#input\_resource\_group\_id) | The ID of an existing IBM Cloud resource group where the cluster is grouped. | `string` | n/a | yes | +| [rotation\_enabled](#input\_rotation\_enabled) | If set to `true`, a rotation policy is enabled on the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `true` | no | +| [rotation\_interval\_month](#input\_rotation\_interval\_month) | Specifies how often keys are rotated in months. Value must be between `1` and `12` inclusive. Only used if 'create\_key\_protect\_instance' is set to `true`. | `number` | `1` | no | +| [routes](#input\_routes) | Allows you to specify the next hop for packets based on their destination address. |
list(
object({
name = string
route_direct_link_ingress = optional(bool)
route_transit_gateway_ingress = optional(bool)
route_vpc_zone_ingress = optional(bool)
routes = optional(
list(
object({
action = optional(string)
zone = number
destination = string
next_hop = string
})
))
})
)
| `[]` | no | +| [scc\_workload\_protection\_access\_tags](#input\_scc\_workload\_protection\_access\_tags) | A list of access tags to apply to the Workload Protection instance. Maximum length: 128 characters. Possible characters are A-Z, 0-9, spaces, underscores, hyphens, periods, and colons. | `list(string)` | `[]` | no | +| [scc\_workload\_protection\_instance\_name](#input\_scc\_workload\_protection\_instance\_name) | The name for the Workload Protection instance that is created by this solution. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"scc-workload-protection"` | no | +| [scc\_workload\_protection\_instance\_tags](#input\_scc\_workload\_protection\_instance\_tags) | The list of tags to add to the Workload Protection instance. | `list(string)` | `[]` | no | +| [scc\_workload\_protection\_resource\_key\_tags](#input\_scc\_workload\_protection\_resource\_key\_tags) | The tags associated with the Workload Protection resource key. | `list(string)` | `[]` | no | +| [scc\_workload\_protection\_service\_plan](#input\_scc\_workload\_protection\_service\_plan) | The pricing plan for the Workload Protection instance service. Possible values: `free-trial`, `graduated-tier`. | `string` | `"graduated-tier"` | no | +| [scc\_workload\_protection\_trusted\_profile\_name](#input\_scc\_workload\_protection\_trusted\_profile\_name) | The name to give the trusted profile that is created by this module if `cspm_enabled` is `true. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format.` | `string` | `"workload-protection-trusted-profile"` | no | +| [scc\_wp\_cbr\_rules](#input\_scc\_wp\_cbr\_rules) | The list of context-based restriction rules to create for the instance. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [secret\_groups](#input\_secret\_groups) | Secret Manager secret group and access group configurations. If a prefix input variable is specified, it is added to the `access_group_name` value in the `-value` format. If you do not wish to create any groups, set the value to `[]`. |
list(object({
secret_group_name = string
secret_group_description = optional(string)
create_access_group = optional(bool, true)
access_group_name = optional(string)
access_group_roles = optional(list(string), ["SecretsReader"])
access_group_tags = optional(list(string))
}))
|
[
{
"access_group_name": "general-secrets-group-access-group",
"access_group_roles": [
"SecretsReader"
],
"create_access_group": true,
"secret_group_description": "A general purpose secrets group with an associated access group which has a secrets reader role",
"secret_group_name": "General"
}
]
| no | +| [secrets\_manager\_allowed\_network](#input\_secrets\_manager\_allowed\_network) | The types of service endpoints to set on the Secrets Manager instance. Possible values are `private-only` or `public-and-private`. | `string` | `"private-only"` | no | +| [secrets\_manager\_cbr\_rules](#input\_secrets\_manager\_cbr\_rules) | (Optional, list) List of CBR rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [secrets\_manager\_endpoint\_type](#input\_secrets\_manager\_endpoint\_type) | The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications. | `string` | `"private"` | no | +| [secrets\_manager\_instance\_name](#input\_secrets\_manager\_instance\_name) | The name to give the Secrets Manager instance provisioned by this solution. If a prefix input variable is specified, it is added to the value in the `-value` format. Applies only if `existing_secrets_manager_crn` is not provided. | `string` | `"secrets-manager"` | no | +| [secrets\_manager\_resource\_tags](#input\_secrets\_manager\_resource\_tags) | The list of resource tags you want to associate with your Secrets Manager instance. Applies only if `existing_secrets_manager_crn` is not provided. | `list(string)` | `[]` | no | +| [secrets\_manager\_service\_plan](#input\_secrets\_manager\_service\_plan) | The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. You can create only one Trial instance of Secrets Manager per account. Before you can create a new Trial instance, you must delete the existing Trial instance and its reclamation. | `string` | `"standard"` | no | +| [security\_group\_rules](#input\_security\_group\_rules) | A list of security group rules to be added to the default vpc security group (default empty). |
list(
object({
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
| `[]` | no | +| [service\_cred](#input\_service\_cred) | Service configuration for COS. |
list(object({
secret_group_name = string # pragma: allowlist secret
secret_group_description = optional(string) # pragma: allowlist secret
existing_secret_group = optional(bool) # pragma: allowlist secret
service_credentials = list(object({ # pragma: allowlist secret
secret_name = string # pragma: allowlist secret
service_credentials_source_service_role_crn = string # pragma: allowlist secret
secret_labels = optional(list(string)) # pragma: allowlist secret
secret_auto_rotation = optional(bool) # pragma: allowlist secret
secret_auto_rotation_unit = optional(string) # pragma: allowlist secret
secret_auto_rotation_interval = optional(number) # pragma: allowlist secret
service_credentials_ttl = optional(string) # pragma: allowlist secret
service_credential_secret_description = optional(string) # pragma: allowlist secret

}))
}))
| `[]` | no | +| [skip\_activity\_tracker\_cos\_auth\_policy](#input\_skip\_activity\_tracker\_cos\_auth\_policy) | To skip creating an IAM authorization policy that allows the Activity Tracker to write to the Cloud Object Storage instance, set this variable to `true`. | `bool` | `false` | no | +| [skip\_cloud\_logs\_cos\_auth\_policy](#input\_skip\_cloud\_logs\_cos\_auth\_policy) | To skip creating an IAM authorization policy that allows the IBM Cloud logs to write to the Cloud Object Storage bucket, set this variable to `true`. | `bool` | `false` | no | +| [skip\_logs\_routing\_auth\_policy](#input\_skip\_logs\_routing\_auth\_policy) | Whether to create an IAM authorization policy that permits the Logs Routing server 'Sender' access to the IBM Cloud Logs instance created by this Deployable Architecture. | `bool` | `false` | no | +| [skip\_secrets\_manager\_cos\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_cos\_iam\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Cloud Object Storage. Set to `true` to use an existing policy. | `bool` | `false` | no | +| [skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy) | If set to true, this skips the creation of a service to service authorization from Secrets Manager to Event Notifications. If false, the service to service authorization is created. | `bool` | `false` | no | +| [skip\_secrets\_manager\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_iam\_auth\_policy) | Whether to skip the creation of the IAM authorization policies required to enable the IAM credentials engine (if you are using an existing Secrets Manager instance, attempting to re-create can cause conflicts if the policies already exist). If set to false, policies will be created that grants the Secrets Manager instance 'Operator' access to the IAM identity service, and 'Groups Service Member Manage' access to the IAM groups service. | `bool` | `false` | no | +| [skip\_secrets\_manager\_kms\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_kms\_iam\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances in the resource group to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. | `bool` | `false` | no | +| [skip\_vpc\_cos\_iam\_auth\_policy](#input\_skip\_vpc\_cos\_iam\_auth\_policy) | To skip creating an IAM authorization policy that allows the VPC to access the Cloud Object Storage, set this variable to `true`. Required only if `enable_vpc_flow_logs` is set to true. | `bool` | `false` | no | +| [subnets](#input\_subnets) | List of subnets for the vpc. For each item in each array, a subnet will be created. Items can be either CIDR blocks or total ipv4 addresses. Public gateways will be enabled only in zones where a gateway has been createds. |
object({
zone-1 = list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
}))
zone-2 = optional(list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
})))
zone-3 = optional(list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
})))
})
|
{
"zone-1": [
{
"acl_name": "vpc-acl",
"cidr": "10.10.10.0/24",
"name": "subnet-a",
"no_addr_prefix": false,
"public_gateway": true
}
],
"zone-2": [
{
"acl_name": "vpc-acl",
"cidr": "10.20.10.0/24",
"name": "subnet-b",
"no_addr_prefix": false,
"public_gateway": true
}
],
"zone-3": [
{
"acl_name": "vpc-acl",
"cidr": "10.30.10.0/24",
"name": "subnet-c",
"no_addr_prefix": false,
"public_gateway": true
}
]
}
| no | +| [vpc\_access\_tags](#input\_vpc\_access\_tags) | The list of access tags to add to the VPC instance. | `list(string)` | `[]` | no | +| [vpc\_flow\_logs\_access\_tags](#input\_vpc\_flow\_logs\_access\_tags) | The list of access tags to add to the VPC instance. | `list(string)` | `[]` | no | +| [vpc\_name](#input\_vpc\_name) | Name of the VPC. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"vpc"` | no | +| [vpc\_resource\_tags](#input\_vpc\_resource\_tags) | The list of tags to add to the VPC instance. | `list(string)` | `[]` | no | +| [vpe\_gateway\_cloud\_service\_by\_crn](#input\_vpe\_gateway\_cloud\_service\_by\_crn) | The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. |
set(
object({
crn = string
vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn.
allow_dns_resolution_binding = optional(bool, true)
})
)
| `[]` | no | +| [vpe\_gateway\_cloud\_services](#input\_vpe\_gateway\_cloud\_services) | The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | +| [vpe\_gateway\_reserved\_ips](#input\_vpe\_gateway\_reserved\_ips) | Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used when a user passes their existing reserved ips created here and not attempt to recreate those. |
object({
name = optional(string) # reserved ip name
})
| `{}` | no | +| [vpe\_gateway\_security\_group\_ids](#input\_vpe\_gateway\_security\_group\_ids) | List of security group ids to attach to each endpoint gateway. | `list(string)` | `null` | no | +| [vpe\_gateway\_service\_endpoints](#input\_vpe\_gateway\_service\_endpoints) | Service endpoints to use to create endpoint gateways. Can be `public`, or `private`. | `string` | `"private"` | no | +| [vpn\_gateways](#input\_vpn\_gateways) | List of VPN Gateways to create. |
list(
object({
name = string
subnet_name = string # Do not include prefix, use same name as in `var.subnets`
mode = optional(string)
resource_group = optional(string)
access_tags = optional(list(string), [])
})
)
| `[]` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| [activity\_tracker\_cos\_target\_bucket\_name](#output\_activity\_tracker\_cos\_target\_bucket\_name) | he name of the object storage bucket which is set as activity tracker event routing target to collect audit events. | +| [activity\_tracker\_routes](#output\_activity\_tracker\_routes) | The map of created Activity Tracker Event Routing routes | +| [activity\_tracker\_targets](#output\_activity\_tracker\_targets) | The map of created Activity Tracker Event Routing targets | +| [boot\_volume\_existing\_kms\_guid](#output\_boot\_volume\_existing\_kms\_guid) | The GUID for the boot volume encryption | +| [boot\_volume\_kms\_account\_id](#output\_boot\_volume\_kms\_account\_id) | The Account ID for the boot volume encryption | +| [boot\_volume\_kms\_key\_id](#output\_boot\_volume\_kms\_key\_id) | The Key ID for the boot volume encryption | +| [cloud\_logs\_crn](#output\_cloud\_logs\_crn) | The id of the provisioned IBM Cloud Logs instance. | +| [cloud\_logs\_guid](#output\_cloud\_logs\_guid) | The guid of the provisioned IBM Cloud Logs instance. | +| [cloud\_logs\_ingress\_endpoint](#output\_cloud\_logs\_ingress\_endpoint) | The public ingress endpoint of the provisioned IBM Cloud Logs instance. | +| [cloud\_logs\_ingress\_private\_endpoint](#output\_cloud\_logs\_ingress\_private\_endpoint) | The private ingress endpoint of the provisioned IBM Cloud Logs instance. | +| [cloud\_logs\_logs\_policies\_details](#output\_cloud\_logs\_logs\_policies\_details) | The details of the IBM Cloud logs policies created. | +| [cloud\_logs\_name](#output\_cloud\_logs\_name) | The name of the provisioned IBM Cloud Logs instance. | +| [cloud\_monitoring\_access\_key](#output\_cloud\_monitoring\_access\_key) | The IBM Cloud Monitoring access key for agents to use | +| [cloud\_monitoring\_access\_key\_name](#output\_cloud\_monitoring\_access\_key\_name) | The name of the IBM Cloud Monitoring access key for agents to use | +| [cloud\_monitoring\_crn](#output\_cloud\_monitoring\_crn) | The id of the provisioned IBM Cloud Monitoring instance. | +| [cloud\_monitoring\_guid](#output\_cloud\_monitoring\_guid) | The guid of the provisioned IBM Cloud Monitoring instance. | +| [cloud\_monitoring\_name](#output\_cloud\_monitoring\_name) | The name of the provisioned IBM Cloud Monitoring instance. | +| [cos\_instance\_crn](#output\_cos\_instance\_crn) | COS instance crn | +| [cos\_instance\_guid](#output\_cos\_instance\_guid) | COS instance guid | +| [cos\_instance\_id](#output\_cos\_instance\_id) | COS instance ID | +| [key\_protect\_id](#output\_key\_protect\_id) | Key Protect instance ID when an instance is created, otherwise null | +| [kms\_account\_id](#output\_kms\_account\_id) | The account ID of the KMS instance. | +| [kms\_config](#output\_kms\_config) | The KMS config needed for OCP cluster | +| [kms\_guid](#output\_kms\_guid) | Key Protect instance GUID or the KMS instance GUID if existing\_kms\_instance\_crn was set | +| [kms\_instance\_crn](#output\_kms\_instance\_crn) | The CRN of the Hyper Protect Crypto Service instance or Key Protect instance | +| [logs\_bucket\_crn](#output\_logs\_bucket\_crn) | Logs Cloud Object Storage bucket CRN | +| [metrics\_bucket\_crn](#output\_metrics\_bucket\_crn) | Metrics Cloud Object Storage bucket CRN | +| [network\_acls](#output\_network\_acls) | List of shortnames and IDs of network ACLs. | +| [private\_path\_subnet\_id](#output\_private\_path\_subnet\_id) | The IDs of the subnets. | +| [public\_gateways](#output\_public\_gateways) | Map of the public gateways by zone. | +| [scc\_workload\_protection\_api\_endpoint](#output\_scc\_workload\_protection\_api\_endpoint) | SCC Workload Protection API endpoint | +| [scc\_workload\_protection\_crn](#output\_scc\_workload\_protection\_crn) | SCC Workload Protection instance CRN | +| [scc\_workload\_protection\_id](#output\_scc\_workload\_protection\_id) | SCC Workload Protection instance ID | +| [scc\_workload\_protection\_ingestion\_endpoint](#output\_scc\_workload\_protection\_ingestion\_endpoint) | SCC Workload Protection instance ingestion endpoint | +| [scc\_workload\_protection\_name](#output\_scc\_workload\_protection\_name) | SCC Workload Protection instance name | +| [secrets\_manager\_crn](#output\_secrets\_manager\_crn) | CRN of the Secrets Manager instance | +| [secrets\_manager\_guid](#output\_secrets\_manager\_guid) | GUID of Secrets Manager instance | +| [secrets\_manager\_region](#output\_secrets\_manager\_region) | Region of the Secrets Manager instance | +| [subnet\_detail\_list](#output\_subnet\_detail\_list) | A list of subnets containing names, CIDR blocks, and zones. | +| [subnet\_detail\_map](#output\_subnet\_detail\_map) | A map of subnets containing IDs, CIDR blocks, and zones. | +| [subnet\_ids](#output\_subnet\_ids) | The IDs of the subnets. | +| [subnet\_zone\_list](#output\_subnet\_zone\_list) | A list of subnet IDs and subnet zones. | +| [vpc\_crn](#output\_vpc\_crn) | CRN of the VPC created. | +| [vpc\_flow\_logs](#output\_vpc\_flow\_logs) | Details of the VPC flow logs collector. | +| [vpc\_id](#output\_vpc\_id) | ID of the VPC created. | +| [vpc\_name](#output\_vpc\_name) | Name of the VPC created. | +| [vpe\_crn](#output\_vpe\_crn) | The CRN of the endpoint gateway. | +| [vpe\_ips](#output\_vpe\_ips) | The reserved IPs for endpoint gateways. | +| [vpn\_gateways\_data](#output\_vpn\_gateways\_data) | Details of VPN gateways data. | +| [vpn\_gateways\_name](#output\_vpn\_gateways\_name) | List of names of VPN gateways. | + diff --git a/modules/monolith/main.tf b/modules/monolith/main.tf new file mode 100644 index 000000000..e5a4551b3 --- /dev/null +++ b/modules/monolith/main.tf @@ -0,0 +1,708 @@ +################################################################################# +# KMS +################################################################################# + +module "existing_kms_crn_parser" { + count = var.existing_kms_instance_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.2.0" + crn = var.existing_kms_instance_crn +} + +module "existing_cluster_kms_key_crn_parser" { + count = var.existing_cluster_kms_key_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.2.0" + crn = var.existing_cluster_kms_key_crn +} + +module "existing_boot_volume_kms_key_crn_parser" { + count = var.existing_boot_volume_kms_key_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.2.0" + crn = var.existing_boot_volume_kms_key_crn +} + +locals { + prefix = var.prefix != null ? trimspace(var.prefix) != "" ? "${var.prefix}-" : "" : "" + cluster_existing_kms_guid = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_cluster ? module.existing_kms_crn_parser[0].service_instance : var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].service_instance : var.kms_encryption_enabled_cluster ? module.kms[0].kms_guid : null + cluster_kms_account_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_cluster ? module.existing_kms_crn_parser[0].account_id : var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].account_id : var.kms_encryption_enabled_cluster ? module.kms[0].kms_account_id : null + cluster_kms_key_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_cluster ? module.kms[0].keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].key_id : var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].resource : var.kms_encryption_enabled_cluster ? module.kms[0].keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].key_id : null + cluster_kms_key_crn = var.kms_encryption_enabled_cluster ? module.kms[0].keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn : var.existing_cluster_kms_key_crn != null ? var.existing_boot_volume_kms_key_crn : var.kms_encryption_enabled_cluster ? module.kms[0].key_protect_crn : null + cluster_key_ring_name = "${local.prefix}${var.cluster_kms_key_ring_name}" + cluster_key_name = "${local.prefix}${var.cluster_kms_key_name}" + + boot_volume_key_ring_name = "${local.prefix}${var.boot_volume_kms_key_ring_name}" + boot_volume_key_name = "${local.prefix}${var.boot_volume_kms_key_name}" + boot_volume_existing_kms_guid = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_boot_volume ? module.existing_kms_crn_parser[0].service_instance : var.existing_boot_volume_kms_key_crn != null ? module.existing_boot_volume_kms_key_crn_parser[0].service_instance : var.kms_encryption_enabled_cluster ? module.kms[0].kms_guid : null + boot_volume_kms_account_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_boot_volume ? module.existing_kms_crn_parser[0].account_id : var.existing_boot_volume_kms_key_crn != null ? module.existing_boot_volume_kms_key_crn_parser[0].account_id : var.kms_encryption_enabled_cluster ? module.kms[0].kms_account_id : null + boot_volume_kms_key_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_boot_volume ? module.kms[0].keys[format("%s.%s", local.boot_volume_key_ring_name, local.boot_volume_key_name)].key_id : var.existing_boot_volume_kms_key_crn != null ? module.existing_boot_volume_kms_key_crn_parser[0].resource : var.kms_encryption_enabled_boot_volume ? module.kms[0].keys[format("%s.%s", local.boot_volume_key_ring_name, local.boot_volume_key_name)].key_id : null + parsed_service_name = var.existing_kms_instance_crn != null ? module.existing_kms_crn_parser[0].service_name : (var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].service_name : null) + is_hpcs_key = local.parsed_service_name == "hs-crypto" ? true : false + + kms_config = var.kms_encryption_enabled_cluster ? { + crk_id = local.cluster_kms_key_id + instance_id = local.cluster_existing_kms_guid + private_endpoint = var.kms_endpoint_type == "private" ? true : false + account_id = local.cluster_kms_account_id + } : null + + keys = [ + var.kms_encryption_enabled_cluster ? { + key_ring_name = local.cluster_key_ring_name + existing_key_ring = false + keys = [ + { + key_name = local.cluster_key_name + standard_key = false + rotation_interval_month = 3 + dual_auth_delete_enabled = false + force_delete = true + } + ] + } : null, + var.kms_encryption_enabled_boot_volume ? { + key_ring_name = local.boot_volume_key_ring_name + existing_key_ring = false + keys = [ + { + key_name = local.boot_volume_key_name + standard_key = false + rotation_interval_month = 3 + dual_auth_delete_enabled = false + force_delete = true + } + ] + } : null + ] +} + +module "kms" { + count = (var.kms_encryption_enabled_boot_volume && var.existing_boot_volume_kms_key_crn == null) || (var.kms_encryption_enabled_cluster && var.existing_cluster_kms_key_crn == null) ? 1 : 0 + source = "terraform-ibm-modules/kms-all-inclusive/ibm" + version = "5.4.5" + resource_group_id = var.resource_group_id + region = var.region + create_key_protect_instance = var.existing_kms_instance_crn != null || var.existing_cluster_kms_key_crn != null || var.existing_boot_volume_kms_key_crn != null ? false : true + existing_kms_instance_crn = var.existing_kms_instance_crn + key_protect_instance_name = "${local.prefix}${var.kms_instance_name}" + key_protect_plan = var.kms_plan + rotation_enabled = var.rotation_enabled + rotation_interval_month = var.rotation_interval_month + dual_auth_delete_enabled = var.dual_auth_delete_enabled + enable_metrics = var.enable_metrics + key_create_import_access_enabled = var.key_create_import_access_enabled + key_protect_allowed_network = var.key_protect_allowed_network + key_ring_endpoint_type = var.kms_endpoint_type + key_endpoint_type = var.kms_endpoint_type + resource_tags = var.kms_resource_tags + access_tags = var.kms_access_tags + keys = [for key in local.keys : key if key != null] + cbr_rules = var.kms_cbr_rules +} + +################################################################################# +# Secrets Manager +################################################################################# + +locals { + enable_secrets_manager_cluster = var.existing_secrets_manager_crn == null ? true : false + parsed_existing_secrets_manager_crn = var.existing_secrets_manager_crn != null ? split(":", var.existing_secrets_manager_crn) : [] + secrets_manager_guid = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[7] : null) : module.secrets_manager[0].secrets_manager_guid + secrets_manager_crn = var.existing_secrets_manager_crn != null ? var.existing_secrets_manager_crn : module.secrets_manager[0].secrets_manager_crn + secrets_manager_region = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[5] : null) : module.secrets_manager[0].secrets_manager_region + enable_event_notifications = var.existing_event_notifications_instance_crn == null || var.existing_event_notifications_instance_crn == "" ? false : true + secret_groups_with_prefix = [ + for group in var.secret_groups : merge(group, { + access_group_name = group.access_group_name != null ? "${local.prefix}${group.access_group_name}" : null + }) + ] +} + +module "secrets_manager_crn_parser" { + count = var.existing_secrets_manager_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.3.0" + crn = var.existing_secrets_manager_crn +} + +module "secrets_manager" { + count = local.enable_secrets_manager_cluster ? 1 : 0 + source = "terraform-ibm-modules/secrets-manager/ibm" + version = "2.11.9" + existing_sm_instance_crn = var.existing_secrets_manager_crn + resource_group_id = var.resource_group_id + region = var.region + secrets_manager_name = "${local.prefix}${var.secrets_manager_instance_name}" + sm_service_plan = var.secrets_manager_service_plan + sm_tags = var.secrets_manager_resource_tags + skip_iam_authorization_policy = var.skip_secrets_manager_iam_auth_policy + # kms dependency + is_hpcs_key = local.is_hpcs_key + kms_encryption_enabled = var.kms_encryption_enabled_cluster + kms_key_crn = local.cluster_kms_key_crn + skip_kms_iam_authorization_policy = var.skip_secrets_manager_kms_iam_auth_policy #|| local.create_cross_account_auth_policy + # event notifications dependency + enable_event_notification = local.enable_event_notifications + existing_en_instance_crn = local.enable_event_notifications ? var.existing_event_notifications_instance_crn : null + skip_en_iam_authorization_policy = var.skip_secrets_manager_event_notifications_iam_auth_policy + cbr_rules = var.secrets_manager_cbr_rules + endpoint_type = var.secrets_manager_endpoint_type + allowed_network = var.secrets_manager_allowed_network + secrets = local.secret_groups_with_prefix +} + +################################################################################# +# Secrets Manager Event Notifications Configuration +################################################################################# + +locals { + parsed_existing_en_instance_crn = var.existing_event_notifications_instance_crn == null || var.existing_event_notifications_instance_crn == "" ? [] : split(":", var.existing_event_notifications_instance_crn) + existing_en_guid = length(local.parsed_existing_en_instance_crn) > 0 ? local.parsed_existing_en_instance_crn[7] : null +} + +data "ibm_en_destinations" "en_destinations" { + # if existing SM instance CRN is passed (!= null), then never do data lookup for EN destinations + count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && local.enable_secrets_manager_cluster ? 1 : 0 + instance_guid = local.existing_en_guid +} + +# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5533 +resource "time_sleep" "wait_for_secrets_manager" { + # if existing SM instance CRN is passed (!= null), then never work with EN + count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && local.enable_secrets_manager_cluster ? 1 : 0 + depends_on = [module.secrets_manager] + + create_duration = "30s" +} + +resource "ibm_en_topic" "en_topic" { + # if existing SM instance CRN is passed (!= null), then never create EN topic + count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && local.enable_secrets_manager_cluster ? 1 : 0 + depends_on = [time_sleep.wait_for_secrets_manager] + instance_guid = local.existing_en_guid + name = "Topic for Secrets Manager instance ${module.secrets_manager[0].secrets_manager_guid}" + description = "Topic for Secrets Manager events routing" + sources { + id = local.secrets_manager_crn + rules { + enabled = true + event_type_filter = "$.*" + } + } +} + +resource "ibm_en_subscription_email" "email_subscription" { + # if existing SM instance CRN is passed (!= null), then never create EN email subscription + count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && length(var.event_notifications_email_list) > 0 && local.enable_secrets_manager_cluster ? 1 : 0 + instance_guid = local.existing_en_guid + name = "Email for Secrets Manager Subscription" + description = "Subscription for Secret Manager Events" + destination_id = [for s in toset(data.ibm_en_destinations.en_destinations[count.index].destinations) : s.id if s.type == "smtp_ibm"][0] + topic_id = ibm_en_topic.en_topic[count.index].topic_id + attributes { + add_notification_payload = true + reply_to_mail = var.event_notifications_reply_to_email + reply_to_name = "Secret Manager Event Notifications Bot" + from_name = var.event_notifications_from_email + invited = var.event_notifications_email_list + } +} + +################################################################################# +# COS +################################################################################# + +locals { + create_cos_instance = var.existing_cos_instance_crn == null ? true : false + existing_secrets_manager_instance_guid = var.existing_secrets_manager_crn != null ? module.secrets_manager_crn_parser[0].service_instance : local.enable_secrets_manager_cluster ? module.secrets_manager[0].secrets_manager_guid : "" + existing_secrets_manager_instance_region = var.existing_secrets_manager_crn != null ? module.secrets_manager_crn_parser[0].region : local.enable_secrets_manager_cluster ? module.secrets_manager[0].secrets_manager_region : "" + + service_credential_secrets = [ + for service_credentials in var.service_cred : { + secret_group_name = service_credentials.secret_group_name + secret_group_description = service_credentials.secret_group_description + existing_secret_group = service_credentials.existing_secret_group + secrets = [ + for secret in service_credentials.service_credentials : { + secret_name = secret.secret_name + secret_labels = secret.secret_labels + secret_auto_rotation = secret.secret_auto_rotation + secret_auto_rotation_unit = secret.secret_auto_rotation_unit + secret_auto_rotation_interval = secret.secret_auto_rotation_interval + service_credentials_ttl = secret.service_credentials_ttl + service_credential_secret_description = secret.service_credential_secret_description + service_credentials_source_service_role_crn = secret.service_credentials_source_service_role_crn + service_credentials_source_service_crn = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_id + secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6 + } + ] + } + ] +} + +module "existing_cos_instance_crn_parser" { + count = var.existing_cos_instance_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.3.0" + crn = var.existing_cos_instance_crn +} + +module "cos" { + count = local.create_cos_instance != false ? 1 : 0 + source = "terraform-ibm-modules/cos/ibm//modules/fscloud" + version = "10.5.9" + resource_group_id = var.resource_group_id + create_cos_instance = local.create_cos_instance + cos_instance_name = "${local.prefix}${var.cos_instance_name}" + resource_keys = [] + cos_plan = var.cos_instance_plan + cos_tags = var.cos_instance_resource_tags + access_tags = var.cos_instance_access_tags + instance_cbr_rules = var.cos_instance_cbr_rules +} + +################################################################################# +# Secrets Manager service credentials for COS +################################################################################# + +# create s2s auth policy with Secrets Manager +resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" { + count = !var.skip_secrets_manager_cos_iam_auth_policy && (var.existing_secrets_manager_crn != null || local.enable_secrets_manager_cluster) ? 1 : 0 + source_service_name = "secrets-manager" + source_resource_instance_id = local.existing_secrets_manager_instance_guid + target_service_name = "cloud-object-storage" + target_resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_guid + roles = ["Key Manager"] + description = "Allow Secrets Manager with instance id ${local.existing_secrets_manager_instance_guid} to manage key for the COS instance" +} + +# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 +resource "time_sleep" "wait_for_cos_authorization_policy" { + count = length(local.service_credential_secrets) > 0 ? 1 : 0 + depends_on = [ibm_iam_authorization_policy.secrets_manager_key_manager] + create_duration = "30s" +} + +module "secrets_manager_service_credentials" { + count = length(local.service_credential_secrets) > 0 ? 1 : 0 + depends_on = [time_sleep.wait_for_cos_authorization_policy] + source = "terraform-ibm-modules/secrets-manager/ibm//modules/secrets" + version = "2.11.9" + existing_sm_instance_guid = local.existing_secrets_manager_instance_guid + existing_sm_instance_region = local.existing_secrets_manager_instance_region + endpoint_type = var.secrets_manager_endpoint_type + secrets = local.service_credential_secrets +} + +################################################################################# +# Cloud Monitoring +################################################################################# + +module "existing_cloud_monitoring_crn_parser" { + count = var.existing_cloud_monitoring_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.3.0" + crn = var.existing_cloud_monitoring_crn +} + +locals { + create_cloud_monitoring = var.existing_cloud_monitoring_crn == null + cloud_monitoring_crn = local.create_cloud_monitoring ? module.cloud_monitoring[0].crn : var.existing_cloud_monitoring_crn + cloud_monitoring_instance_name = "${local.prefix}${var.cloud_monitoring_instance_name}" + metrics_router_target_name = "${local.prefix}${var.metrics_routing_target_name}" + metrics_router_route_name = "${local.prefix}${var.metrics_routing_route_name}" + + default_metrics_router_route = var.enable_metrics_routing_to_cloud_monitoring ? [{ + name = local.metrics_router_route_name + rules = [{ + action = "send" + targets = [{ + id = module.metrics_routing[0].metrics_router_targets[local.metrics_router_target_name].id + }] + inclusion_filters = [] + }] + }] : [] +} + +module "cloud_monitoring" { + count = local.create_cloud_monitoring ? 1 : 0 + source = "terraform-ibm-modules/cloud-monitoring/ibm" + version = "1.11.0" + resource_group_id = var.resource_group_id + region = var.region + instance_name = local.cloud_monitoring_instance_name + plan = var.cloud_monitoring_plan + resource_tags = var.cloud_monitoring_resource_tags + access_tags = var.cloud_monitoring_access_tags + resource_keys = var.cloud_monitoring_resource_keys + disable_access_key_creation = var.disable_access_key_creation + service_endpoints = "public-and-private" + enable_platform_metrics = var.enable_platform_metrics + cbr_rules = var.cloud_monitoring_cbr_rules +} + +module "metrics_routing" { + count = var.enable_metrics_routing_to_cloud_monitoring ? 1 : 0 + source = "terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing" + version = "1.11.0" + metrics_router_targets = [ + { + destination_crn = local.cloud_monitoring_crn + target_name = local.metrics_router_target_name + target_region = var.region + skip_metrics_router_auth_policy = false + } + ] + + metrics_router_routes = length(var.metrics_router_routes) != 0 ? var.metrics_router_routes : local.default_metrics_router_route + metrics_router_settings = var.enable_primary_metadata_region ? { primary_metadata_region = var.region } : null +} + +################################################################################# +# Cloud Logs +################################################################################# + +locals { + cloud_logs_instance_name = "${local.prefix}${var.cloud_logs_instance_name}" + create_cloud_logs = var.existing_cloud_logs_crn == null + cloud_logs_crn = local.create_cloud_logs ? module.cloud_logs[0].crn : var.existing_cloud_logs_crn + + data_bucket_name = "${local.prefix}${var.cloud_logs_data_cos_bucket_name}" + metrics_bucket_name = "${local.prefix}${var.cloud_logs_metrics_cos_bucket_name}" + cos_instance_guid = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_guid +} + +module "cloud_logs" { + depends_on = [time_sleep.wait_for_cos_authorization_policy[0]] + count = local.create_cloud_logs ? 1 : 0 + source = "terraform-ibm-modules/cloud-logs/ibm" + version = "1.10.0" + resource_group_id = var.resource_group_id + region = var.region + instance_name = local.cloud_logs_instance_name + plan = "standard" # not a variable because there is only one option + resource_tags = var.cloud_logs_resource_tags + access_tags = var.cloud_logs_access_tags + retention_period = var.cloud_logs_retention_period + service_endpoints = "public-and-private" # not a variable because there is only one option + existing_event_notifications_instances = var.existing_event_notifications_instances + cbr_rules = var.cloud_logs_cbr_rules + data_storage = { + logs_data = { + enabled = true + bucket_crn = module.cloud_logs_buckets.buckets[local.data_bucket_name].bucket_crn + bucket_endpoint = module.cloud_logs_buckets.buckets[local.data_bucket_name].s3_endpoint_direct + skip_cos_auth_policy = var.skip_cloud_logs_cos_auth_policy + }, + metrics_data = { + enabled = true + bucket_crn = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].bucket_crn + bucket_endpoint = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].s3_endpoint_direct + skip_cos_auth_policy = var.skip_cloud_logs_cos_auth_policy + } + } + logs_routing_tenant_regions = var.logs_routing_tenant_regions + skip_logs_routing_auth_policy = var.skip_logs_routing_auth_policy + policies = var.logs_policies +} + +module "cloud_logs_buckets" { + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.7" + bucket_configs = [ + { + bucket_name = local.data_bucket_name + kms_key_crn = var.kms_encryption_enabled_buckets ? local.cluster_kms_key_crn : null + kms_guid = var.kms_encryption_enabled_buckets ? local.cluster_existing_kms_guid : null + kms_encryption_enabled = var.kms_encryption_enabled_buckets + region_location = var.region + resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id + add_bucket_name_suffix = var.append_random_bucket_name_suffix + management_endpoint_type = var.management_endpoint_type_for_buckets + storage_class = var.cloud_logs_cos_buckets_class + force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn + } + }, + { + bucket_name = local.metrics_bucket_name + kms_key_crn = var.kms_encryption_enabled_buckets ? local.cluster_kms_key_crn : null + kms_guid = var.kms_encryption_enabled_buckets ? local.cluster_existing_kms_guid : null + kms_encryption_enabled = var.kms_encryption_enabled_buckets + region_location = var.region + resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id + add_bucket_name_suffix = var.append_random_bucket_name_suffix + management_endpoint_type = var.management_endpoint_type_for_buckets + storage_class = var.cloud_logs_cos_buckets_class + skip_iam_authorization_policy = true + force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn + } + } + ] +} + +################################################################################# +# Activity Tracker +################################################################################# +locals { + activity_tracker_cos_target_bucket_name = try("${local.prefix}${var.activity_tracker_cos_target_bucket_name}", var.activity_tracker_cos_target_bucket_name) + cos_target_bucket_name = var.existing_activity_tracker_cos_target_bucket_name != null ? var.existing_activity_tracker_cos_target_bucket_name : var.enable_activity_tracker_event_routing_to_cos_bucket ? module.at_cos_bucket[0].buckets[local.activity_tracker_cos_target_bucket_name].bucket_name : null + cos_target_bucket_endpoint = var.existing_activity_tracker_cos_target_bucket_endpoint != null ? var.existing_activity_tracker_cos_target_bucket_endpoint : var.enable_activity_tracker_event_routing_to_cos_bucket ? module.at_cos_bucket[0].buckets[local.activity_tracker_cos_target_bucket_name].s3_endpoint_private : null + cos_target_name = var.cos_target_name != null ? var.cos_target_name : local.create_cos_instance ? module.cos[0].cos_instance_name : try("${local.prefix}-cos-target", "cos-target") + cloud_logs_target_name = var.cloud_logs_target_name != null ? var.cloud_logs_target_name : local.create_cos_instance ? module.cos[0].cos_instance_name : try("${local.prefix}-cloud-logs-target", "cloud-logs-target") + activity_tracker_cos_route_name = var.activity_tracker_cos_route_name != null ? var.activity_tracker_cos_route_name : try("${local.prefix}at-cos-route", "at-cos-route") + activity_tracker_cloud_logs_route_name = var.activity_tracker_cloud_logs_route_name != null ? var.activity_tracker_cloud_logs_route_name : try("${local.prefix}at-cloud-logs-route", "at-cloud-logs-route") + activity_tracker_bucket_config = var.existing_activity_tracker_cos_target_bucket_name == null && var.enable_activity_tracker_event_routing_to_cos_bucket ? { + class = var.activity_tracker_cos_target_bucket_class + name = local.activity_tracker_cos_target_bucket_name + tag = var.activity_tracker_cos_bucket_access_tags + } : null + + + bucket_retention_configs = local.activity_tracker_bucket_config != null ? { (local.activity_tracker_cos_target_bucket_name) = var.activity_tracker_cos_bucket_retention_policy } : null + + at_buckets_config = local.activity_tracker_bucket_config != null ? [local.activity_tracker_bucket_config] : [] + + archive_rule = length(local.at_buckets_config) != 0 ? { + enable = true + days = 90 + type = "Glacier" + } : null + + expire_rule = length(local.at_buckets_config) != 0 ? { + enable = true + days = 366 + } : null + + activity_tracker_cos_route = var.enable_activity_tracker_event_routing_to_cos_bucket ? [{ + route_name = local.activity_tracker_cos_route_name + locations = ["*"] + target_ids = [module.activity_tracker.activity_tracker_targets[local.cos_target_name].id] + }] : [] + + activity_tracker_cloud_logs_route = var.enable_activity_tracker_event_routing_to_cloud_logs ? [{ + route_name = local.activity_tracker_cloud_logs_route_name + locations = ["*"] + target_ids = [module.activity_tracker.activity_tracker_targets[local.cloud_logs_target_name].id] + }] : [] + activity_tracker_routes = concat(local.activity_tracker_cos_route, local.activity_tracker_cloud_logs_route) + +} + +module "activity_tracker" { + source = "terraform-ibm-modules/activity-tracker/ibm" + version = "1.5.0" + cos_targets = var.enable_activity_tracker_event_routing_to_cos_bucket ? [ + { + bucket_name = local.cos_target_bucket_name + endpoint = local.cos_target_bucket_endpoint + instance_id = var.existing_cos_instance_crn != null ? var.existing_cos_instance_crn : module.cos[0].cos_instance_crn + target_region = var.region + target_name = local.cos_target_name + skip_atracker_cos_iam_auth_policy = var.skip_activity_tracker_cos_auth_policy + service_to_service_enabled = true + } + ] : [] + + cloud_logs_targets = var.enable_activity_tracker_event_routing_to_cloud_logs ? [ + { + instance_id = var.existing_cloud_logs_crn != null ? var.existing_cloud_logs_crn : module.cloud_logs[0].crn + target_region = var.region + target_name = local.cloud_logs_target_name + } + ] : [] + + # Routes + activity_tracker_routes = local.activity_tracker_routes +} + +module "at_cos_bucket" { + count = length(coalesce(local.at_buckets_config, [])) != 0 ? 1 : 0 # no need to call COS module if consumer is using existing COS bucket + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.8" + bucket_configs = [ + for value in local.at_buckets_config : + { + access_tags = value.tag + bucket_name = value.name + add_bucket_name_suffix = var.append_random_bucket_name_suffix + kms_guid = local.cluster_existing_kms_guid + kms_encryption_enabled = var.kms_encryption_enabled_buckets + kms_key_crn = local.cluster_kms_key_crn + skip_iam_authorization_policy = false + management_endpoint_type = var.management_endpoint_type_for_buckets + storage_class = value.class + resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id + region_location = var.region + force_delete = true + archive_rule = local.archive_rule + expire_rule = local.expire_rule + retention_rule = lookup(local.bucket_retention_configs, value.name, null) + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + # If `existing_monitoring_crn` is not passed, metrics are sent to the instance associated to the container's location unless otherwise specified in the Metrics Router service configuration. + metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn + } + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + } + ] +} + +################################################################################# +# SCC Workload Protection +################################################################################# + +locals { + scc_workload_protection_instance_name = "${local.prefix}${var.scc_workload_protection_instance_name}" + scc_workload_protection_resource_key_name = "${local.prefix}${var.scc_workload_protection_instance_name}-key" +} + +module "scc_wp" { + source = "terraform-ibm-modules/scc-workload-protection/ibm" + version = "1.16.4" + name = local.scc_workload_protection_instance_name + region = var.region + resource_group_id = var.resource_group_id + resource_tags = var.scc_workload_protection_instance_tags + resource_key_name = local.scc_workload_protection_resource_key_name + resource_key_tags = var.scc_workload_protection_resource_key_tags + cloud_monitoring_instance_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn + access_tags = var.scc_workload_protection_access_tags + scc_wp_service_plan = var.scc_workload_protection_service_plan + app_config_crn = var.app_config_crn + scc_workload_protection_trusted_profile_name = "${local.prefix}${var.scc_workload_protection_trusted_profile_name}" + cbr_rules = var.scc_wp_cbr_rules + cspm_enabled = var.cspm_enabled +} + + + +############################################################################# +# COS Bucket for VPC flow logs +############################################################################# + + +locals { + vpc_flow_logs_bucket_name = "${local.prefix}${var.flow_logs_cos_bucket_name}" + # configuration for the flow logs bucket + flow_logs_bucket_config = [{ + access_tags = var.vpc_flow_logs_access_tags + bucket_name = local.vpc_flow_logs_bucket_name + add_bucket_name_suffix = var.append_random_bucket_name_suffix + kms_encryption_enabled = var.kms_encryption_enabled_buckets + kms_guid = local.cluster_existing_kms_guid + kms_key_crn = local.cluster_kms_key_crn + skip_iam_authorization_policy = true + management_endpoint_type = var.management_endpoint_type_for_buckets + storage_class = var.cloud_logs_cos_buckets_class + resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id + region_location = var.region + force_delete = true + archive_rule = var.flow_logs_cos_bucket_archive_days != null ? { + enable = true + days = var.flow_logs_cos_bucket_archive_days + type = var.flow_logs_cos_bucket_archive_type + } : null + expire_rule = var.flow_logs_cos_bucket_expire_days != null ? { + enable = true + days = var.flow_logs_cos_bucket_expire_days + } : null + retention_rule = var.flow_logs_cos_bucket_enable_retention ? { + default = var.flow_logs_cos_bucket_default_retention_days + maximum = var.flow_logs_cos_bucket_maximum_retention_days + minimum = var.flow_logs_cos_bucket_minimum_retention_days + permanent = var.flow_logs_cos_bucket_enable_permanent_retention + } : null + object_versioning_enabled = var.flow_logs_cos_bucket_enable_object_versioning + }] +} + +# Create COS bucket using the defined bucket configuration +module "vpc_cos_buckets" { + count = var.enable_vpc_flow_logs ? 1 : 0 + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.8" + bucket_configs = local.flow_logs_bucket_config +} + +############################################################################# +# VPC +############################################################################# + +locals { + # create 'use_public_gateways' object + public_gateway_object = { + for key, value in var.subnets : key => value != null ? length([for sub in value : sub.public_gateway if sub.public_gateway]) > 0 ? [for sub in value : sub.public_gateway if sub.public_gateway][0] : false : false + } +} + +# Create VPC +module "vpc" { + source = "terraform-ibm-modules/landing-zone-vpc/ibm" + version = "8.9.1" + resource_group_id = var.resource_group_id + region = var.region + create_vpc = true + name = var.vpc_name + prefix = local.prefix != "" ? trimspace(var.prefix) : null + tags = var.vpc_resource_tags + access_tags = var.vpc_access_tags + subnets = var.subnets + default_network_acl_name = var.default_network_acl_name + default_security_group_name = var.default_security_group_name + default_routing_table_name = var.default_routing_table_name + network_acls = var.network_acls + security_group_rules = var.security_group_rules + clean_default_sg_acl = var.clean_default_security_group_acl + use_public_gateways = local.public_gateway_object + address_prefixes = var.address_prefixes + routes = var.routes + enable_vpc_flow_logs = var.enable_vpc_flow_logs + create_authorization_policy_vpc_to_cos = !var.skip_vpc_cos_iam_auth_policy + existing_cos_instance_guid = var.enable_vpc_flow_logs ? local.cos_instance_guid : null + existing_storage_bucket_name = var.enable_vpc_flow_logs ? module.vpc_cos_buckets[0].buckets[local.vpc_flow_logs_bucket_name].bucket_name : null + vpn_gateways = var.vpn_gateways +} + +############################################################################# +# VPE Gateway +############################################################################# + +module "vpe_gateway" { + source = "terraform-ibm-modules/vpe-gateway/ibm" + version = "4.6.6" + resource_group_id = var.resource_group_id + region = var.region + prefix = local.prefix + security_group_ids = var.vpe_gateway_security_group_ids + vpc_name = module.vpc.vpc_name + vpc_id = module.vpc.vpc_id + subnet_zone_list = module.vpc.subnet_zone_list + cloud_services = var.vpe_gateway_cloud_services + cloud_service_by_crn = var.vpe_gateway_cloud_service_by_crn + service_endpoints = var.vpe_gateway_service_endpoints + reserved_ips = var.vpe_gateway_reserved_ips +} diff --git a/modules/monolith/outputs.tf b/modules/monolith/outputs.tf new file mode 100644 index 000000000..d43df4a98 --- /dev/null +++ b/modules/monolith/outputs.tf @@ -0,0 +1,307 @@ +############################################################################## +# VPC +############################################################################## + +output "vpc_name" { + description = "Name of the VPC created." + value = module.vpc.vpc_name +} + +output "vpc_id" { + description = "ID of the VPC created." + value = module.vpc.vpc_id +} + +output "vpc_crn" { + description = "CRN of the VPC created." + value = module.vpc.vpc_crn +} + +############################################################################## +# Public Gateways +############################################################################## + +output "public_gateways" { + description = "Map of the public gateways by zone." + value = module.vpc.public_gateways +} + +############################################################################## +# VPC flow logs +############################################################################## + +output "vpc_flow_logs" { + description = "Details of the VPC flow logs collector." + value = module.vpc.vpc_flow_logs +} + +############################################################################## +# Network ACLs +############################################################################## + +output "network_acls" { + description = "List of shortnames and IDs of network ACLs." + value = module.vpc.network_acls +} + +############################################################################## +# Subnet Outputs +############################################################################## + +output "subnet_ids" { + description = "The IDs of the subnets." + value = module.vpc.subnet_ids +} + +output "private_path_subnet_id" { + description = "The IDs of the subnets." + value = length(module.vpc.subnet_ids) > 0 ? module.vpc.subnet_ids[0] : null +} + +output "subnet_detail_list" { + description = "A list of subnets containing names, CIDR blocks, and zones." + value = module.vpc.subnet_detail_list +} + +output "subnet_zone_list" { + description = "A list of subnet IDs and subnet zones." + value = module.vpc.subnet_zone_list +} + +output "subnet_detail_map" { + description = "A map of subnets containing IDs, CIDR blocks, and zones." + value = module.vpc.subnet_detail_map +} + +############################################################################## +# VPN Gateways Outputs +############################################################################## + +output "vpn_gateways_name" { + description = "List of names of VPN gateways." + value = module.vpc.vpn_gateways_name +} + +output "vpn_gateways_data" { + description = "Details of VPN gateways data." + value = module.vpc.vpn_gateways_data +} + +############################################################################## +# VPE Outputs +############################################################################## + +output "vpe_ips" { + description = "The reserved IPs for endpoint gateways." + value = module.vpe_gateway.vpe_ips +} + +output "vpe_crn" { + description = "The CRN of the endpoint gateway." + value = module.vpe_gateway.crn +} + +############################################################################## +# KMS Outputs +############################################################################## + +output "kms_guid" { + description = "Key Protect instance GUID or the KMS instance GUID if existing_kms_instance_crn was set" + value = local.cluster_existing_kms_guid +} + +output "kms_account_id" { + description = "The account ID of the KMS instance." + value = local.cluster_kms_account_id +} + +output "key_protect_id" { + description = "Key Protect instance ID when an instance is created, otherwise null" + value = local.cluster_kms_key_id +} + +output "kms_instance_crn" { + value = var.existing_kms_instance_crn == null ? var.kms_encryption_enabled_cluster ? module.kms[0].key_protect_crn : null : var.existing_kms_instance_crn + description = "The CRN of the Hyper Protect Crypto Service instance or Key Protect instance" +} + +output "kms_config" { + description = "The KMS config needed for OCP cluster" + value = local.kms_config +} + +output "boot_volume_kms_key_id" { + description = "The Key ID for the boot volume encryption" + value = local.boot_volume_kms_key_id +} + +output "boot_volume_existing_kms_guid" { + description = "The GUID for the boot volume encryption" + value = local.boot_volume_existing_kms_guid +} + +output "boot_volume_kms_account_id" { + description = "The Account ID for the boot volume encryption" + value = local.boot_volume_kms_account_id +} + +############################################################################## +# SM Outputs +############################################################################## + +output "secrets_manager_guid" { + description = "GUID of Secrets Manager instance" + value = local.secrets_manager_guid +} + +output "secrets_manager_crn" { + value = local.secrets_manager_crn + description = "CRN of the Secrets Manager instance" +} + +output "secrets_manager_region" { + value = local.secrets_manager_region + description = "Region of the Secrets Manager instance" +} + +############################################################################## +# COS Outputs +############################################################################## + +output "cos_instance_crn" { + description = "COS instance crn" + value = var.existing_cos_instance_crn != null ? var.existing_cos_instance_crn : module.cos[0].cos_instance_crn +} + +output "cos_instance_guid" { + description = "COS instance guid" + value = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_guid +} + +output "cos_instance_id" { + description = "COS instance ID" + value = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_crn +} + + +############################################################################## +# Cloud Monitoring Outputs +############################################################################## + +output "cloud_monitoring_crn" { + value = local.cloud_monitoring_crn + description = "The id of the provisioned IBM Cloud Monitoring instance." +} +output "cloud_monitoring_name" { + value = local.create_cloud_monitoring ? module.cloud_monitoring[0].name : null + description = "The name of the provisioned IBM Cloud Monitoring instance." +} + +output "cloud_monitoring_guid" { + value = local.create_cloud_monitoring ? module.cloud_monitoring[0].guid : module.existing_cloud_monitoring_crn_parser[0].service_instance + description = "The guid of the provisioned IBM Cloud Monitoring instance." +} + +output "cloud_monitoring_access_key_name" { + value = local.create_cloud_monitoring ? module.cloud_monitoring[0].access_key_name : null + description = "The name of the IBM Cloud Monitoring access key for agents to use" +} + +output "cloud_monitoring_access_key" { + value = local.create_cloud_monitoring ? module.cloud_monitoring[0].access_key : null + description = "The IBM Cloud Monitoring access key for agents to use" + sensitive = true +} + +############################################################################## +# Cloud Logs Outputs +############################################################################## + +output "cloud_logs_crn" { + value = local.cloud_logs_crn + description = "The id of the provisioned IBM Cloud Logs instance." +} + +output "cloud_logs_guid" { + value = local.create_cloud_logs ? module.cloud_logs[0].guid : null + description = "The guid of the provisioned IBM Cloud Logs instance." +} + +output "cloud_logs_name" { + value = local.create_cloud_logs ? module.cloud_logs[0].name : null + description = "The name of the provisioned IBM Cloud Logs instance." +} + +output "cloud_logs_ingress_endpoint" { + value = local.create_cloud_logs ? module.cloud_logs[0].ingress_endpoint : null + description = "The public ingress endpoint of the provisioned IBM Cloud Logs instance." +} + +output "cloud_logs_ingress_private_endpoint" { + value = local.create_cloud_logs ? module.cloud_logs[0].ingress_private_endpoint : null + description = "The private ingress endpoint of the provisioned IBM Cloud Logs instance." +} + +output "cloud_logs_logs_policies_details" { + value = local.create_cloud_logs ? module.cloud_logs[0].logs_policies_details : null + description = "The details of the IBM Cloud logs policies created." +} + +output "logs_bucket_crn" { + description = "Logs Cloud Object Storage bucket CRN" + value = module.cloud_logs_buckets.buckets[local.data_bucket_name].bucket_crn +} + +output "metrics_bucket_crn" { + description = "Metrics Cloud Object Storage bucket CRN" + value = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].bucket_crn +} + +############################################################################## +# Activity Tracker Event Routing Outputs +############################################################################## + +output "activity_tracker_cos_target_bucket_name" { + value = var.existing_activity_tracker_cos_target_bucket_name == null ? var.enable_activity_tracker_event_routing_to_cos_bucket ? module.at_cos_bucket[0].buckets[local.activity_tracker_cos_target_bucket_name].bucket_name : null : var.existing_activity_tracker_cos_target_bucket_name + description = "he name of the object storage bucket which is set as activity tracker event routing target to collect audit events." +} + +output "activity_tracker_targets" { + value = module.activity_tracker.activity_tracker_targets + description = "The map of created Activity Tracker Event Routing targets" +} + +output "activity_tracker_routes" { + value = module.activity_tracker.activity_tracker_routes + description = "The map of created Activity Tracker Event Routing routes" +} + +############################################################################## +# SCC-WP Outputs +############################################################################## + +output "scc_workload_protection_id" { + description = "SCC Workload Protection instance ID" + value = module.scc_wp.id +} + +output "scc_workload_protection_crn" { + description = "SCC Workload Protection instance CRN" + value = module.scc_wp.crn +} + +output "scc_workload_protection_name" { + description = "SCC Workload Protection instance name" + value = module.scc_wp.name +} + +output "scc_workload_protection_ingestion_endpoint" { + description = "SCC Workload Protection instance ingestion endpoint" + value = module.scc_wp.name +} + +output "scc_workload_protection_api_endpoint" { + description = "SCC Workload Protection API endpoint" + value = module.scc_wp.api_endpoint + sensitive = true +} diff --git a/modules/monolith/variables.tf b/modules/monolith/variables.tf new file mode 100644 index 000000000..73ca707b8 --- /dev/null +++ b/modules/monolith/variables.tf @@ -0,0 +1,1684 @@ +variable "prefix" { + type = string + nullable = true + description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string." + + validation { + # - null and empty string is allowed + # - Must not contain consecutive hyphens (--): length(regexall("--", var.prefix)) == 0 + # - Starts with a lowercase letter: [a-z] + # - Contains only lowercase letters (a–z), digits (0–9), and hyphens (-) + # - Must not end with a hyphen (-): [a-z0-9] + condition = (var.prefix == null || var.prefix == "" ? true : + alltrue([ + can(regex("^[a-z][-a-z0-9]*[a-z0-9]$", var.prefix)), + length(regexall("--", var.prefix)) == 0 + ]) + ) + error_message = "Prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It must not end with a hyphen('-'), and cannot contain consecutive hyphens ('--')." + } + + validation { + # must not exceed 16 characters in length + condition = var.prefix == null || var.prefix == "" ? true : length(var.prefix) <= 16 + error_message = "Prefix must not exceed 16 characters." + } +} + +variable "region" { + type = string + description = "The region to provision all resources in." + default = "us-south" + nullable = false +} + +variable "resource_group_id" { + type = string + description = "The ID of an existing IBM Cloud resource group where the cluster is grouped." +} + +############################################################## +# KMS Related +############################################################## +variable "kms_encryption_enabled_cluster" { + description = "Set to true to enable KMS encryption for the cluster's Object Storage bucket. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn`." + type = bool + default = false + nullable = false + + validation { + condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_cluster : true + error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_cluster' to true." + } + + validation { + condition = var.existing_cluster_kms_key_crn != null ? var.kms_encryption_enabled_cluster : true + error_message = "If passing a value for 'existing_cluster_kms_key_crn', you should set 'kms_encryption_enabled_cluster' to true." + } +} + +variable "existing_kms_instance_crn" { + type = string + default = null + description = "The CRN of an existing KMS instance (Hyper Protect Crypto Services or Key Protect)." + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)), + var.existing_kms_instance_crn == null, + ]) + error_message = "The provided KMS instance CRN in the input 'existing_kms_instance_crn' in not valid." + } +} + +variable "existing_cluster_kms_key_crn" { + type = string + default = null + description = "The CRN of an existing KMS key to use for encrypting the Object Storage of the Cluster. If no value is set for this variable, specify a value for `existing_kms_instance_crn` variable to create a key ring and key." + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_cluster_kms_key_crn)), + var.existing_cluster_kms_key_crn == null, + ]) + error_message = "The provided KMS key CRN in the input 'existing_cluster_kms_key_crn' in not valid." + } + + validation { + condition = var.existing_cluster_kms_key_crn != null ? var.existing_kms_instance_crn == null : true + error_message = "A value should not be passed for 'existing_kms_instance_crn' when passing an existing key value using the 'existing_cluster_kms_key_crn' input." + } + +} + +variable "kms_endpoint_type" { + type = string + description = "The endpoint for communicating with the KMS instance. Possible values: `public`, `private`. Applies only if `kms_encryption_enabled_cluster` is true" + default = "private" + nullable = false + validation { + condition = can(regex("^(public|private)$", var.kms_endpoint_type)) + error_message = "The kms_endpoint_type value must be 'public' or 'private'." + } +} + +variable "cluster_kms_key_ring_name" { + type = string + default = "cluster-key-ring" + description = "The name of the key ring to be created for the cluster's Object Storage bucket encryption key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "cluster_kms_key_name" { + type = string + default = "cluster-key" + description = "The name of the key to be created for the cluster's Object Storage bucket encryption. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "kms_encryption_enabled_boot_volume" { + type = bool + description = "Set this to true to control the encryption keys used to encrypt the data that for the block storage volumes for VPC. If set to false, the data is encrypted by using randomly generated keys. For more info on encrypting block storage volumes, see https://cloud.ibm.com/docs/vpc?topic=vpc-creating-instances-byok" + default = false + nullable = false + + validation { + condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_boot_volume || var.kms_encryption_enabled_cluster : true + error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_boot_volume' to true." + } + + validation { + condition = var.existing_boot_volume_kms_key_crn != null ? var.kms_encryption_enabled_boot_volume : true + error_message = "If passing a value for 'existing_boot_volume_kms_key_crn', you should set 'kms_encryption_enabled_boot_volume' to true." + } +} + +variable "existing_boot_volume_kms_key_crn" { + type = string + default = null + description = "The CRN of an existing KMS key to use to encrypt the the block storage volumes for VPC. If no value is set for this variable, specify a value for either the `existing_kms_instance_crn` variable to create a key ring and key." + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_boot_volume_kms_key_crn)), + var.existing_boot_volume_kms_key_crn == null, + ]) + error_message = "The provided KMS key CRN in the input 'existing_boot_volume_kms_key_crn' in not valid." + } +} + +variable "boot_volume_kms_key_ring_name" { + type = string + default = "boot-volume-key-ring" + description = "The name for the key ring created for the block storage volumes key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "boot_volume_kms_key_name" { + type = string + default = "boot-volume-key" + description = "The name for the key created for the block storage volumes. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "kms_instance_name" { + type = string + description = "The name to give the Key Protect instance that that is created by this module. Only used if 'create_key_protect_instance' is set to `true`." + default = "key-protect" +} + +variable "kms_plan" { + type = string + description = "Plan for the Key Protect instance. Supported values are 'tiered-pricing' and 'cross-region-resiliency'. Only used if 'create_key_protect_instance' is set to `true`." + default = "tiered-pricing" + # validation performed in terraform-ibm-key-protect module +} + +variable "rotation_enabled" { + type = bool + description = "If set to `true`, a rotation policy is enabled on the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`." + default = true +} + +variable "rotation_interval_month" { + type = number + description = "Specifies how often keys are rotated in months. Value must be between `1` and `12` inclusive. Only used if 'create_key_protect_instance' is set to `true`." + default = 1 +} + +variable "dual_auth_delete_enabled" { + type = bool + description = "If set to `true`, a dual authorization policy is enabled on the Key Protect instance. After the dual authorization policy is set on the instance, it cannot be reverted. An instance with dual authorization policy enabled cannot be destroyed by using Terraform. Only used if 'create_key_protect_instance' is set to `true`." + default = false +} + +variable "enable_metrics" { + type = bool + description = "Set to `true` to enable metrics on the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`. In order to view metrics, you need an IBM Cloud Monitoring (Sysdig) instance that is located in the same region as the Key Protect instance. After you provision a Monitoring instance, enable platform metrics to monitor your Key Protect instance." + default = true +} + +variable "key_create_import_access_enabled" { + type = bool + description = "If set to `true`, a key create and import access policy is enabled on the instance of Key Protect. Only used if 'create_key_protect_instance' is set to `true`." + default = true +} + +variable "key_protect_allowed_network" { + type = string + description = "Allowed network types for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create_key_protect_instance' is set to `true`." + default = "private-only" + validation { + condition = can(regex("private-only|public-and-private", var.key_protect_allowed_network)) + error_message = "The `key_protect_allowed_network` value must be 'private-only' or 'public-and-private'." + } +} + +variable "kms_resource_tags" { + type = list(string) + description = "Optional list of tags to add to the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`." + default = [] +} + +variable "kms_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`." + default = [] +} + +variable "kms_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The context-based restrictions rule to create. Only one rule is allowed." + default = [] + # Validation happens in the rule module + # NOTE: Context-based restriction rules applies to Key Protect instances only and is not supported by Hyper Protect Crypto Services (HPCS) instances + + validation { + condition = var.existing_kms_instance_crn == null ? true : length(regexall(".*hscrypto.*", var.existing_kms_instance_crn)) > 0 ? length(var.kms_cbr_rules) == 0 : true + error_message = "When passing a Hyper Protect Crypto Services (HPCS) instance as a value for `existing_kms_instance_crn` you cannot provide `kms_cbr_rules`. Context-based restrictions are not supported by HPCS instances. For more information, go to [services that integrate with context-based restrictions](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis#cbr-adopters)." + } + validation { + condition = length(var.kms_cbr_rules) <= 1 + error_message = "Only one CBR rule is allowed." + } +} + +############################################################## +# Secrets Manager +############################################################## + +variable "secrets_manager_instance_name" { + type = string + description = "The name to give the Secrets Manager instance provisioned by this solution. If a prefix input variable is specified, it is added to the value in the `-value` format. Applies only if `existing_secrets_manager_crn` is not provided." + default = "secrets-manager" +} + +variable "existing_secrets_manager_crn" { + type = string + description = "The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created." + default = null +} + +variable "secrets_manager_service_plan" { + type = string + description = "The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. You can create only one Trial instance of Secrets Manager per account. Before you can create a new Trial instance, you must delete the existing Trial instance and its reclamation." + default = "standard" + validation { + condition = var.existing_secrets_manager_crn == null ? contains(["standard", "trial"], var.secrets_manager_service_plan) : true + error_message = "Only 'standard' and 'trial' are allowed values for 'secrets_manager_service_plan'. Applies only if not providing a value for the 'existing_secrets_manager_crn' input." + } +} + +variable "skip_secrets_manager_iam_auth_policy" { + type = bool + description = "Whether to skip the creation of the IAM authorization policies required to enable the IAM credentials engine (if you are using an existing Secrets Manager instance, attempting to re-create can cause conflicts if the policies already exist). If set to false, policies will be created that grants the Secrets Manager instance 'Operator' access to the IAM identity service, and 'Groups Service Member Manage' access to the IAM groups service." + default = false +} + +variable "secrets_manager_resource_tags" { + type = list(string) + description = "The list of resource tags you want to associate with your Secrets Manager instance. Applies only if `existing_secrets_manager_crn` is not provided." + default = [] +} + +variable "secrets_manager_endpoint_type" { + type = string + description = "The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications." + default = "private" + validation { + condition = contains(["public", "private"], var.secrets_manager_endpoint_type) + error_message = "The specified service endpoint is not a valid selection!" + } +} + +variable "secrets_manager_allowed_network" { + type = string + description = "The types of service endpoints to set on the Secrets Manager instance. Possible values are `private-only` or `public-and-private`." + default = "private-only" + validation { + condition = contains(["private-only", "public-and-private"], var.secrets_manager_allowed_network) + error_message = "The specified allowed_network is not a valid selection!" + } +} + +variable "skip_secrets_manager_kms_iam_auth_policy" { + type = bool + description = "Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances in the resource group to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable." + default = false +} + +variable "secret_groups" { + type = list(object({ + secret_group_name = string + secret_group_description = optional(string) + create_access_group = optional(bool, true) + access_group_name = optional(string) + access_group_roles = optional(list(string), ["SecretsReader"]) + access_group_tags = optional(list(string)) + })) + description = "Secret Manager secret group and access group configurations. If a prefix input variable is specified, it is added to the `access_group_name` value in the `-value` format. If you do not wish to create any groups, set the value to `[]`." + nullable = false + default = [ + { + secret_group_name = "General" + secret_group_description = "A general purpose secrets group with an associated access group which has a secrets reader role" + create_access_group = true + access_group_name = "general-secrets-group-access-group" + access_group_roles = ["SecretsReader"] + } + ] + validation { + error_message = "The name of the secret group cannot be null or empty string." + condition = length([ + for group in var.secret_groups : + true if(group.secret_group_name == "" || group.secret_group_name == null) + ]) == 0 + } + validation { + error_message = "When creating an access group, a list of roles must be specified." + condition = length([ + for group in var.secret_groups : + true if(group.create_access_group && group.access_group_roles == null) + ]) == 0 + } +} + +variable "secrets_manager_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "(Optional, list) List of CBR rules to create." + default = [] + # Validation happens in the rule module +} + +######################################################################################################################## +# Event Notifications +######################################################################################################################## + +variable "existing_event_notifications_instance_crn" { + type = string + description = "The CRN of the Event Notifications service used to enable lifecycle notifications for your Secrets Manager instance." + default = null +} + +variable "skip_secrets_manager_event_notifications_iam_auth_policy" { + type = bool + description = "If set to true, this skips the creation of a service to service authorization from Secrets Manager to Event Notifications. If false, the service to service authorization is created." + default = false +} + +variable "event_notifications_email_list" { + type = list(string) + description = "The list of email address to target out when Secrets Manager triggers an event" + default = [] +} + +variable "event_notifications_from_email" { + type = string + description = "The email address used to send any Secrets Manager event coming via Event Notifications" + default = "compliancealert@ibm.com" +} + +variable "event_notifications_reply_to_email" { + type = string + description = "The email address specified in the 'reply_to' section for any Secret Manager event coming via Event Notifications" + default = "no-reply@ibm.com" +} + +############################################################## +# COS +############################################################## + +variable "existing_cos_instance_crn" { + type = string + description = "The CRN of an existing Object Storage instance." + default = null +} + +variable "cos_instance_name" { + description = "The name for the IBM Cloud Object Storage instance provisioned by this solution. If a value is passed for `prefix`, the instance will be named with the prefix value in the format of `-value`." + type = string + default = "cos-instance" +} + +variable "cos_instance_plan" { + description = "The plan to use when Object Storage instances are created." + type = string + default = "standard" + validation { + condition = contains(["standard", "cos-one-rate-plan"], var.cos_instance_plan) + error_message = "The specified plan is not a valid selection!" + } +} + +variable "cos_instance_resource_tags" { + description = "A list of resource tags to apply to the Object Storage instance." + type = list(string) + default = [] +} + +variable "cos_instance_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Object Storage instance created by the module." + default = [] +} + +variable "skip_secrets_manager_cos_iam_auth_policy" { + type = bool + default = false + description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Cloud Object Storage. Set to `true` to use an existing policy." +} + +variable "service_cred" { # pragma: allowlist secret + type = list(object({ + secret_group_name = string # pragma: allowlist secret + secret_group_description = optional(string) # pragma: allowlist secret + existing_secret_group = optional(bool) # pragma: allowlist secret + service_credentials = list(object({ # pragma: allowlist secret + secret_name = string # pragma: allowlist secret + service_credentials_source_service_role_crn = string # pragma: allowlist secret + secret_labels = optional(list(string)) # pragma: allowlist secret + secret_auto_rotation = optional(bool) # pragma: allowlist secret + secret_auto_rotation_unit = optional(string) # pragma: allowlist secret + secret_auto_rotation_interval = optional(number) # pragma: allowlist secret + service_credentials_ttl = optional(string) # pragma: allowlist secret + service_credential_secret_description = optional(string) # pragma: allowlist secret + + })) + })) + default = [] + description = "Service configuration for COS." + + validation { + # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select Cloud Object Storage and select the role + condition = alltrue([ + for group in var.service_cred : alltrue([ + # crn:v?:bluemix; two non-empty segments; three possibly empty segments; :serviceRole or role: non-empty segment + for credential in group.service_credentials : can(regex("^crn:v[0-9]:bluemix(:..*){2}(:.*){3}:(serviceRole|role):..*$", credential.service_credentials_source_service_role_crn)) + ]) + ]) + error_message = "service_credentials_source_service_role_crn must be a serviceRole CRN. See https://cloud.ibm.com/iam/roles" + } + + validation { + condition = length(var.service_cred) > 0 ? var.existing_secrets_manager_crn != null : true + error_message = "When passing a value for 'service_credential', a value must be passed for 'existing_secrets_manager_crn'." + } +} + +variable "cos_instance_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + tags = optional(list(object({ + name = string + value = string + })), []) + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restriction rules to create for the instance." + default = [] + # Validation happens in the rule module +} + +######################################################################################################################## +# Cloud Monitoring +######################################################################################################################## + +variable "existing_cloud_monitoring_crn" { + type = string + default = null + description = "The CRN of an existing Cloud Monitoring instance. If not supplied, a new instance will be created." +} + +variable "cloud_monitoring_instance_name" { + type = string + description = "The name of the IBM Cloud Monitoring instance to create. If the prefix variable is passed, the name of the instance is prefixed to the value in the `-value` format." + default = "cloud-monitoring" +} + +variable "cloud_monitoring_resource_tags" { + type = list(string) + description = "Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings)." + default = [] +} + +variable "cloud_monitoring_access_tags" { + type = list(string) + description = "A list of access tags to apply to the IBM Cloud Monitoring instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." + default = [] +} + +variable "disable_access_key_creation" { + type = bool + description = "When set to true, disables the creation of a default manager access key which is required by agents to ingest metrics." + default = false +} + +variable "cloud_monitoring_resource_keys" { + description = "A list of maps representing resource keys to create for the IBM Cloud Monitoring instance. Each entry defines a single resource key. Use this list to manage custom keys and handle key rotation." + type = list(object({ + name = string + generate_hmac_credentials = optional(bool, false) # pragma: allowlist secret + role = optional(string, "Manager") + service_id_crn = optional(string, null) + })) + default = [] +} + +variable "cloud_monitoring_plan" { + type = string + description = "The IBM Cloud Monitoring plan to provision. Available values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." + default = "graduated-tier" + + validation { + condition = can(regex("^lite$|^graduated-tier$|^graduated-tier-sysdig-secure-plus-monitor$", var.cloud_monitoring_plan)) + error_message = "The plan value must be one of the following: lite, graduated-tier and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." + } + + validation { + condition = (var.cloud_monitoring_plan != "graduated-tier-sysdig-secure-plus-monitor") || var.region == "eu-fr2" + error_message = "When cloud_monitoring_plan is graduated-tier-sysdig-secure-plus-monitor region should be set to eu-fr2." + } +} + +variable "enable_platform_metrics" { + type = bool + description = "When set to `true`, the IBM Cloud Monitoring instance collects the platform metrics." + default = false +} + +######################################################################################################################## +# Metrics Routing +######################################################################################################################## + +variable "metrics_routing_target_name" { + type = string + description = "The name of the IBM Cloud Metrics Routing target where metrics are collected. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format." + default = "cloud-monitoring-target" +} + +variable "metrics_routing_route_name" { + type = string + description = "The name of the IBM Cloud Metrics Routing route for the default route that indicate what metrics are routed in a region and where to store them. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format." + default = "metrics-routing-route" +} + +variable "enable_metrics_routing_to_cloud_monitoring" { + type = bool + description = "Whether to enable metrics routing from IBM Cloud Metric Routing to Cloud Monitoring." + default = true +} + +variable "enable_primary_metadata_region" { + type = bool + description = "When set to `true`, sets `primary_metadata_region` to `region`, storing Metrics Router metadata in that region. When `false`, no region is set and the default global region is used. For new accounts, creating targets and routes will fail until primary_metadata_region is set, so it is recommended to default enable_primary_metadata_region to true." + default = true +} + +variable "metrics_router_routes" { + type = list(object({ + name = string + rules = list(object({ + action = string + targets = list(object({ + id = string + })) + inclusion_filters = list(object({ + operand = string + operator = string + values = list(string) + })) + })) + })) + default = [] + description = "Routes for IBM Cloud Metrics Routing." +} + +variable "cloud_monitoring_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restriction rules to create for the instance." + default = [] + # Validation happens in the rule module +} + +######################################################################################################################## +# Cloud Logs +######################################################################################################################## + +variable "existing_cloud_logs_crn" { + type = string + default = null + description = "The CRN of an existing Cloud Logs instance. If not supplied, a new instance will be created." +} + +variable "cloud_logs_instance_name" { + type = string + description = "The name of the IBM Cloud Logs instance to create. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + default = "cloud-logs" +} + +variable "cloud_logs_resource_tags" { + type = list(string) + description = "Tags associated with the IBM Cloud Logs instance (Optional, array of strings)." + default = [] +} + +variable "cloud_logs_access_tags" { + type = list(string) + description = "A list of access tags to apply to the IBM Cloud Logs instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." + default = [] +} + +variable "cloud_logs_retention_period" { + type = number + description = "The number of days IBM Cloud Logs will retain the logs data in Priority insights. Allowed values: 7, 14, 30, 60, 90." + default = 7 + + validation { + condition = contains([7, 14, 30, 60, 90], var.cloud_logs_retention_period) + error_message = "Valid values 'cloud_logs_retention_period' are: 7, 14, 30, 60, 90" + } +} + +variable "existing_event_notifications_instances" { + type = list(object({ + crn = string + integration_name = optional(string) + skip_iam_auth_policy = optional(bool, false) + })) + default = [] + description = "List of Event Notifications instance details for routing critical events that occur in your IBM Cloud Logs." +} + +variable "cloud_logs_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "(Optional, list) List of context-based restrictions rules to create." + default = [] +} + +variable "cloud_logs_data_cos_bucket_name" { + type = string + nullable = true + default = "cloud-logs-logs-bucket" + description = "The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "cloud_logs_metrics_cos_bucket_name" { + type = string + nullable = true + default = "cloud-logs-metrics-bucket" + description = "The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "skip_cloud_logs_cos_auth_policy" { + type = bool + description = "To skip creating an IAM authorization policy that allows the IBM Cloud logs to write to the Cloud Object Storage bucket, set this variable to `true`." + default = false +} + + + +variable "kms_encryption_enabled_buckets" { + description = "Set to true to enable KMS encryption on the Object Storage buckets created for the IBM Cloud Logs instance. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn` (to create a new key). Can not be set to true if passing a value for `existing_cloud_logs_crn`." + type = bool + default = false + nullable = false + + validation { + condition = var.kms_encryption_enabled_buckets ? var.existing_cloud_logs_crn == null : true + error_message = "'kms_encryption_enabled_buckets' should be false if passing a value for 'existing_cloud_logs_crn' as existing Cloud Logs instance will already have a bucket attached." + } + + validation { + condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_buckets : true + error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_buckets' to true." + } + + validation { + condition = var.existing_cluster_kms_key_crn != null ? var.kms_encryption_enabled_buckets : true + error_message = "If passing a value for 'existing_cluster_kms_key_crn', you should set 'kms_encryption_enabled_buckets' to true." + } + + validation { + condition = var.kms_encryption_enabled_buckets ? ((var.existing_cluster_kms_key_crn != null || var.existing_kms_instance_crn != null) ? true : false) : true + error_message = "Either 'existing_cluster_kms_key_crn' or 'existing_kms_instance_crn' is required if 'kms_encryption_enabled_buckets' is set to true." + } +} + +variable "append_random_bucket_name_suffix" { + type = bool + description = "Append random generated suffix (4 characters long) to the newly provisioned IBM Cloud Logs Object Storage bucket names." + default = true +} + +variable "management_endpoint_type_for_buckets" { + description = "The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Possible values: `public`, `private`, `direct`. If you specify `private`, enable virtual routing and forwarding in your account, and the Terraform runtime must have access to the the IBM Cloud private network." + type = string + default = "direct" + validation { + condition = contains(["public", "private", "direct"], var.management_endpoint_type_for_buckets) + error_message = "The specified management_endpoint_type_for_buckets is not a valid selection!" + } +} + +variable "cloud_logs_cos_buckets_class" { + type = string + default = "smart" + description = "The storage class of the newly provisioned IBM Cloud Logs Object Storage buckets. Possible values: `standard` or `smart`. Applies only if `existing_cloud_logs_crn` is not provided." + validation { + condition = contains(["standard", "smart"], var.cloud_logs_cos_buckets_class) + error_message = "Allowed values for cos_bucket_class are \"standard\" or \"smart\"." + } +} + +############################################################################## +# Logs Routing +############################################################################## + +variable "logs_routing_tenant_regions" { + type = list(any) + default = [] + description = "Pass a list of regions to create a tenant for that is targeted to the Cloud Logs instance created by this module. To manage platform logs that are generated by IBM Cloud® services in a region of IBM Cloud, you must create a tenant in each region that you operate. Leave the list empty if you don't want to create any tenants. NOTE: You can only have 1 tenant per region in an account." + nullable = false +} + +variable "skip_logs_routing_auth_policy" { + description = "Whether to create an IAM authorization policy that permits the Logs Routing server 'Sender' access to the IBM Cloud Logs instance created by this Deployable Architecture." + type = bool + default = false +} + +variable "logs_policies" { + type = list(object({ + logs_policy_name = string + logs_policy_description = optional(string, null) + logs_policy_priority = string + application_rule = optional(list(object({ + name = string + rule_type_id = string + }))) + subsystem_rule = optional(list(object({ + name = string + rule_type_id = string + }))) + log_rules = optional(list(object({ + severities = list(string) + }))) + archive_retention = optional(list(object({ + id = string + }))) + })) + description = "Configuration of Cloud Logs policies." + default = [] + + validation { + condition = alltrue([for config in var.logs_policies : (length(config.logs_policy_name) <= 4096 ? true : false)]) + error_message = "Maximum length of logs_policy_name allowed is 4096 chars." + } + + validation { + condition = alltrue([for config in var.logs_policies : contains(["type_unspecified", "type_block", "type_low", "type_medium", "type_high"], config.logs_policy_priority)]) + error_message = "The specified priority for logs policy is not a valid selection. Allowed values are: type_unspecified, type_block, type_low, type_medium, type_high." + } + + validation { + condition = alltrue( + [for config in var.logs_policies : + (config.application_rule != null ? + (alltrue([for rule in config.application_rule : + contains(["unspecified", "is", "is_not", "start_with", "includes"], rule.rule_type_id)])) + : true) + ]) + error_message = "Identifier of application_rule 'rule_type_id' is not a valid selection. Allowed values are: unspecified, is, is_not, start_with, includes." + } + + validation { + condition = alltrue( + [for config in var.logs_policies : + (config.application_rule != null ? + (alltrue([for rule in config.application_rule : + can(regex("^[\\p{L}\\p{N}\\p{P}\\p{Z}\\p{S}\\p{M}]+$", rule.name)) && length(rule.name) <= 4096 && length(rule.name) > 1])) + : true) + ]) + error_message = "The name of the application_rule does not meet the required criteria." + } + + validation { + condition = alltrue( + [for config in var.logs_policies : + (config.log_rules != null && length(config.log_rules) > 0 ? true : false) + ]) + error_message = "The log_rules can not be empty and must contain at least 1 item." + } + + validation { + condition = alltrue( + [for config in var.logs_policies : + (config.log_rules != null ? + (alltrue([for rule in config.log_rules : + alltrue([for severity in rule["severities"] : + contains(["unspecified", "debug", "verbose", "info", "warning", "error", "critical"], severity)])])) + : true + )]) + error_message = "The 'severities' of log_rules is not a valid selection. Allowed values are: unspecified, debug, verbose, info, warning, error, critical." + } + + validation { + condition = alltrue( + [for config in var.logs_policies : + (config.subsystem_rule != null ? + (alltrue([for rule in config.subsystem_rule : + contains(["unspecified", "is", "is_not", "start_with", "includes"], rule.rule_type_id)])) + : true + )]) + error_message = "Identifier of subsystem_rule 'rule_type_id' is not a valid selection. Allowed values are: unspecified, is, is_not, start_with, includes." + } + + validation { + condition = alltrue( + [for config in var.logs_policies : + (config.subsystem_rule != null ? + (alltrue([for rule in config.subsystem_rule : + can(regex("^[\\p{L}\\p{N}\\p{P}\\p{Z}\\p{S}\\p{M}]+$", rule.name)) && length(rule.name) <= 4096 && length(rule.name) > 1])) + : true) + ]) + error_message = "The name of the subsystem_rule does not meet the required criteria." + } + + validation { + condition = alltrue( + [for config in var.logs_policies : + (config.archive_retention != null ? + (alltrue( + [for rule in config.archive_retention : can(regex("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", rule.id))] + )) : true + )]) + error_message = "The id of the archive_retention does not meet the required criteria." + } +} + +############################################################################## +# Activity Tracker Event Routing +############################################################################## + +variable "enable_activity_tracker_event_routing_to_cos_bucket" { + type = bool + description = "When set to `true`, you must provide a value for `existing_cos_instance_crn` to enable event routing from Activity Tracker to a Object Storage bucket." + default = true + + validation { + condition = var.enable_activity_tracker_event_routing_to_cos_bucket || var.enable_activity_tracker_event_routing_to_cloud_logs + error_message = "At least one of 'enable_activity_tracker_event_routing_to_cos_bucket' or 'enable_activity_tracker_event_routing_to_cloud_logs' must be true to route audit events to COS bucket or Cloud Logs instance." + } + +} + +variable "activity_tracker_cos_target_bucket_name" { + type = string + default = "at-events-cos-bucket" + description = "The name of the Cloud Object Storage bucket to create for the Cloud Object Storage target to store AT events. Cloud Object Storage bucket names are globally unique. If the `add_bucket_name_suffix` variable is set to `true`, 4 random characters are added to this name to ensure that the name of the bucket is globally unique. If the prefix input variable is passed, the name of the instance is prefixed to the value in the `-value` format." +} + +variable "existing_activity_tracker_cos_target_bucket_name" { + type = string + nullable = true + default = null + description = "The name of an existing bucket within the Cloud Object Storage instance in which to store IBM Cloud Activity Tracker Event Routing. If an existing Cloud Object Storage bucket is not specified, a bucket is created." +} + +variable "existing_activity_tracker_cos_target_bucket_endpoint" { + type = string + nullable = true + default = null + description = "The name of an existing Cloud Object Storage bucket endpoint to use for setting up IBM Cloud Activity Tracker Event Routing. If an existing endpoint is not specified, the endpoint of the new Cloud Object Storage bucket is used." +} + +variable "cos_target_name" { + type = string + description = "Name of the cos target for activity tracker event routing." + default = null +} + +variable "cloud_logs_target_name" { + type = string + description = "Name of the cloud logs target for activity tracker event routing." + default = null +} + +variable "activity_tracker_cos_route_name" { + type = string + description = "Name of the cos route for activity tracker event routing." + default = null +} + +variable "activity_tracker_cloud_logs_route_name" { + type = string + description = "Name of the cloud logs route for activity tracker event routing." + default = null +} + +variable "activity_tracker_cos_target_bucket_class" { + type = string + default = "smart" + description = "The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`." + validation { + condition = contains(["standard", "vault", "cold", "smart", "onerate_active"], var.activity_tracker_cos_target_bucket_class) + error_message = "Specify one of the following values for the `cos_bucket_class`: `standard`, `vault`, `cold`, `smart`, or `onerate_active`." + } +} + +variable "activity_tracker_cos_bucket_access_tags" { + type = list(string) + default = [] + description = "A list of optional access tags to add to the IBM Cloud Activity Tracker Event Routing Cloud Object Storage bucket." +} + +variable "activity_tracker_cos_bucket_retention_policy" { + type = object({ + default = optional(number, 90) + maximum = optional(number, 350) + minimum = optional(number, 90) + permanent = optional(bool, false) + }) + description = "The retention policy of the IBM Cloud Activity Tracker Event Routing COS target bucket." + default = null +} + +variable "enable_activity_tracker_event_routing_to_cloud_logs" { + type = bool + description = "When set to `true`, you must provide a value for `existing_cloud_logs_crn` to enable event routing from Activity Tracker to a Cloud Logs instance." + default = true +} + +variable "skip_activity_tracker_cos_auth_policy" { + type = bool + description = "To skip creating an IAM authorization policy that allows the Activity Tracker to write to the Cloud Object Storage instance, set this variable to `true`." + default = false +} + +####################################################################################################################### +# SCC Workload Protection +####################################################################################################################### + +variable "scc_workload_protection_instance_name" { + description = "The name for the Workload Protection instance that is created by this solution. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + type = string + default = "scc-workload-protection" +} + +variable "scc_workload_protection_trusted_profile_name" { + description = "The name to give the trusted profile that is created by this module if `cspm_enabled` is `true. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + type = string + default = "workload-protection-trusted-profile" + validation { + condition = can(regex("^[a-zA-Z][a-zA-Z0-9\\-_\\.]+$", var.scc_workload_protection_trusted_profile_name)) + error_message = "The trusted profile name must begin with a letter and can only contain letters, numbers, hyphens, underscores, and periods." + } + validation { + condition = !(var.cspm_enabled && var.scc_workload_protection_trusted_profile_name == null) + error_message = "Cannot be `null` if `cspm_enabled` is `true`." + } +} + +variable "scc_workload_protection_instance_tags" { + type = list(string) + description = "The list of tags to add to the Workload Protection instance." + default = [] +} + +variable "scc_workload_protection_resource_key_tags" { + type = list(string) + description = "The tags associated with the Workload Protection resource key." + default = [] +} + +variable "scc_workload_protection_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Workload Protection instance. Maximum length: 128 characters. Possible characters are A-Z, 0-9, spaces, underscores, hyphens, periods, and colons." + default = [] + + validation { + condition = alltrue([ + for tag in var.scc_workload_protection_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\", see https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits for more details" + } +} + +variable "scc_workload_protection_service_plan" { + description = "The pricing plan for the Workload Protection instance service. Possible values: `free-trial`, `graduated-tier`." + type = string + default = "graduated-tier" + validation { + error_message = "Plan for Workload Protection instances can only be `free-trial` or `graduated-tier`." + condition = contains( + ["free-trial", "graduated-tier"], + var.scc_workload_protection_service_plan + ) + } +} + +variable "cspm_enabled" { + description = "Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service." + type = bool + default = false + nullable = false +} + +variable "app_config_crn" { + description = "The CRN of an existing App Config instance to use with the SCC Workload Protection instance. Required if `cspm_enabled` is true. NOTE: Ensure the App Config instance has configuration aggregator enabled." + type = string + default = null + validation { + condition = var.cspm_enabled ? var.app_config_crn != null : true + error_message = "Cannot be `null` if CSPM is enabled." + } + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}apprapp:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.app_config_crn)), + var.app_config_crn == null, + ]) + error_message = "The provided CRN is not a valid App Config CRN." + } +} + +variable "scc_wp_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + tags = optional(list(object({ + name = string + value = string + })), []) + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restriction rules to create for the instance." + default = [] + # Validation happens in the rule module +} + +####################################################################################################################### +# VPC and VPE +####################################################################################################################### + +variable "enable_vpc_flow_logs" { + description = "To enable VPC Flow logs, set this to true." + type = bool + nullable = false + default = false +} + +variable "vpc_name" { + default = "vpc" + description = "Name of the VPC. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + type = string +} + +variable "flow_logs_cos_bucket_name" { + description = "Name of the Cloud Object Storage bucket to be created to collect VPC flow logs." + type = string + default = "flow-logs-bucket" +} + +variable "vpc_resource_tags" { + type = list(string) + description = "The list of tags to add to the VPC instance." + default = [] +} + +variable "vpc_access_tags" { + type = list(string) + description = "The list of access tags to add to the VPC instance." + default = [] +} + +variable "vpc_flow_logs_access_tags" { + type = list(string) + description = "The list of access tags to add to the VPC instance." + default = [] +} + +variable "flow_logs_cos_bucket_archive_days" { + description = "The number of days before the `archive_type` rule action takes effect for the flow logs cloud object storage bucket." + type = number + default = 90 +} + +variable "flow_logs_cos_bucket_archive_type" { + description = "The storage class or archive type you want the object to transition to in the flow logs cloud object storage bucket." + type = string + default = "Glacier" + validation { + condition = contains(["Glacier", "Accelerated"], var.flow_logs_cos_bucket_archive_type) + error_message = "The specified flow_logs_cos_bucket_archive_type is not a valid selection!" + } +} + +variable "flow_logs_cos_bucket_expire_days" { + description = "The number of days before the expire rule action takes effect for the flow logs cloud object storage bucket." + type = number + default = 366 +} + +variable "flow_logs_cos_bucket_enable_object_versioning" { + description = "Set it to true if object versioning is enabled so that multiple versions of an object are retained in the flow logs cloud object storage bucket. Cannot be used if `flow_logs_cos_bucket_enable_retention` is true." + type = bool + nullable = false + default = false + + validation { + condition = var.flow_logs_cos_bucket_enable_object_versioning ? (var.flow_logs_cos_bucket_enable_retention ? false : true) : true + error_message = "`flow_logs_cos_bucket_enable_object_versioning` cannot set true if `flow_logs_cos_bucket_enable_retention` is true." + } +} + +variable "flow_logs_cos_bucket_enable_retention" { + description = "Set to true to enable retention for the flow logs cloud object storage bucket." + type = bool + nullable = false + default = false +} + +variable "flow_logs_cos_bucket_default_retention_days" { + description = "The number of days that an object can remain unmodified in the flow logs cloud object storage bucket." + type = number + default = 90 +} + +variable "flow_logs_cos_bucket_maximum_retention_days" { + description = "The maximum number of days that an object can be kept unmodified in the flow logs cloud object storage." + type = number + default = 350 +} + +variable "flow_logs_cos_bucket_minimum_retention_days" { + description = "The minimum number of days that an object must be kept unmodified in the flow logs cloud object storage." + type = number + default = 90 +} + +variable "flow_logs_cos_bucket_enable_permanent_retention" { + description = "Whether permanent retention status is enabled for the flow logs cloud object storage bucket." + type = bool + nullable = false + default = false +} + +variable "subnets" { + description = "List of subnets for the vpc. For each item in each array, a subnet will be created. Items can be either CIDR blocks or total ipv4 addresses. Public gateways will be enabled only in zones where a gateway has been createds." + type = object({ + zone-1 = list(object({ + name = string + cidr = string + public_gateway = optional(bool) + acl_name = string + no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true + subnet_tags = optional(list(string), []) + })) + zone-2 = optional(list(object({ + name = string + cidr = string + public_gateway = optional(bool) + acl_name = string + no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true + subnet_tags = optional(list(string), []) + }))) + zone-3 = optional(list(object({ + name = string + cidr = string + public_gateway = optional(bool) + acl_name = string + no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true + subnet_tags = optional(list(string), []) + }))) + }) + + default = { + zone-1 = [ + { + name = "subnet-a" + cidr = "10.10.10.0/24" + public_gateway = true + acl_name = "vpc-acl" + no_addr_prefix = false + } + ], + zone-2 = [ + { + name = "subnet-b" + cidr = "10.20.10.0/24" + public_gateway = true + acl_name = "vpc-acl" + no_addr_prefix = false + } + ], + zone-3 = [ + { + name = "subnet-c" + cidr = "10.30.10.0/24" + public_gateway = true + acl_name = "vpc-acl" + no_addr_prefix = false + } + ] + } + + validation { + condition = alltrue([for key, value in var.subnets : value != null ? length([for subnet in value : subnet.public_gateway if subnet.public_gateway]) > 1 ? false : true : true]) + error_message = "var.subnets has more than one public gateway in a zone. Only one public gateway can be attached to a zone for the virtual private cloud." + } +} + +variable "default_network_acl_name" { + description = "Name of the Default ACL. If null, a name will be automatically generated." + type = string + default = null +} + +variable "default_security_group_name" { + description = "Name of the Default Security Group. If null, a name will be automatically generated." + type = string + default = null +} + +variable "default_routing_table_name" { + description = "Name of the Default Routing Table. If null, a name will be automatically generated." + type = string + default = null +} + +variable "network_acls" { + description = "The list of ACLs to create. Provide at least one rule for each ACL." + type = list( + object({ + name = string + add_ibm_cloud_internal_rules = optional(bool) + add_vpc_connectivity_rules = optional(bool) + prepend_ibm_rules = optional(bool) + rules = list( + object({ + name = string + action = string + destination = string + direction = string + source = string + tcp = optional( + object({ + port_max = optional(number) + port_min = optional(number) + source_port_max = optional(number) + source_port_min = optional(number) + }) + ) + udp = optional( + object({ + port_max = optional(number) + port_min = optional(number) + source_port_max = optional(number) + source_port_min = optional(number) + }) + ) + icmp = optional( + object({ + type = optional(number) + code = optional(number) + }) + ) + }) + ) + }) + ) + + default = [ + { + name = "vpc-acl" + add_ibm_cloud_internal_rules = true + add_vpc_connectivity_rules = true + prepend_ibm_rules = true + rules = [ + { + name = "allow-all-443-inbound" + action = "allow" + direction = "inbound" + tcp = { + port_min = 443 + port_max = 443 + source_port_min = 443 + source_port_max = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-80-inbound" + action = "allow" + direction = "inbound" + tcp = { + port_min = 80 + port_max = 80 + source_port_min = 80 + source_port_max = 80 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-22-inbound" + action = "allow" + direction = "inbound" + tcp = { + port_min = 22 + port_max = 22 + source_port_min = 22 + source_port_max = 22 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-443-outbound" + action = "allow" + direction = "outbound" + tcp = { + source_port_min = 443 + source_port_max = 443 + port_min = 443 + port_max = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-80-outbound" + action = "allow" + direction = "outbound" + tcp = { + source_port_min = 80 + source_port_max = 80 + port_min = 80 + port_max = 80 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-22-outbound" + action = "allow" + direction = "outbound" + tcp = { + source_port_min = 22 + source_port_max = 22 + port_min = 22 + port_max = 22 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + } + ] + } + ] + + validation { + error_message = "ACL rule actions can only be `allow` or `deny`." + condition = length(distinct( + flatten([ + # Check through rules + for rule in flatten([var.network_acls[*].rules]) : + # Return false action is not valid + false if !contains(["allow", "deny"], rule.action) + ]) + )) == 0 + } + + validation { + error_message = "ACL rule direction can only be `inbound` or `outbound`." + condition = length(distinct( + flatten([ + # Check through rules + for rule in flatten([var.network_acls[*].rules]) : + # Return false if direction is not valid + false if !contains(["inbound", "outbound"], rule.direction) + ]) + )) == 0 + } + + validation { + error_message = "ACL rule names must match the regex pattern ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$." + condition = length(distinct( + flatten([ + # Check through rules + for rule in flatten([var.network_acls[*].rules]) : + # Return false if direction is not valid + false if !can(regex("^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$", rule.name)) + ]) + )) == 0 + } + +} + +############################################################################## +# Default Security Group Rules +############################################################################## + +variable "security_group_rules" { + description = "A list of security group rules to be added to the default vpc security group (default empty)." + default = [] + type = list( + object({ + name = string + direction = string + remote = optional(string) + local = optional(string) + ip_version = optional(string) + tcp = optional( + object({ + port_max = optional(number) + port_min = optional(number) + }) + ) + udp = optional( + object({ + port_max = optional(number) + port_min = optional(number) + }) + ) + icmp = optional( + object({ + type = optional(number) + code = optional(number) + }) + ) + }) + ) + + validation { + error_message = "Security group rule direction can only be `inbound` or `outbound`." + condition = (var.security_group_rules == null || length(var.security_group_rules) == 0) ? true : length(distinct( + flatten([ + # Check through rules + for rule in var.security_group_rules : + # Return false if direction is not valid + false if !contains(["inbound", "outbound"], rule.direction) + ]) + )) == 0 + } + + validation { + error_message = "Security group rule names must match the regex pattern ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$." + condition = (var.security_group_rules == null || length(var.security_group_rules) == 0) ? true : length(distinct( + flatten([ + # Check through rules + for rule in var.security_group_rules : + # Return false if direction is not valid + false if !can(regex("^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$", rule.name)) + ]) + )) == 0 + } +} + +variable "clean_default_security_group_acl" { + description = "Remove all rules from the default VPC security group and VPC ACL (less permissive)." + type = bool + nullable = false + default = true +} + +############################################################################## +# Address Prefixes +############################################################################## + +variable "address_prefixes" { + description = "The IP range that will be defined for the VPC for a certain location. Use only with manual address prefixes." + type = object({ + zone-1 = optional(list(string)) + zone-2 = optional(list(string)) + zone-3 = optional(list(string)) + }) + default = { + zone-1 = null + zone-2 = null + zone-3 = null + } + validation { + error_message = "Keys for `use_public_gateways` must be in the order `zone-1`, `zone-2`, `zone-3`." + condition = var.address_prefixes == null ? true : ( + (length(var.address_prefixes) == 1 && keys(var.address_prefixes)[0] == "zone-1") || + (length(var.address_prefixes) == 2 && keys(var.address_prefixes)[0] == "zone-1" && keys(var.address_prefixes)[1] == "zone-2") || + (length(var.address_prefixes) == 3 && keys(var.address_prefixes)[0] == "zone-1" && keys(var.address_prefixes)[1] == "zone-2") && keys(var.address_prefixes)[2] == "zone-3" + ) + } +} + +############################################################################## +# Add routes to VPC +############################################################################## + +variable "routes" { + description = "Allows you to specify the next hop for packets based on their destination address." + type = list( + object({ + name = string + route_direct_link_ingress = optional(bool) + route_transit_gateway_ingress = optional(bool) + route_vpc_zone_ingress = optional(bool) + routes = optional( + list( + object({ + action = optional(string) + zone = number + destination = string + next_hop = string + }) + )) + }) + ) + default = [] +} + +variable "skip_vpc_cos_iam_auth_policy" { + description = "To skip creating an IAM authorization policy that allows the VPC to access the Cloud Object Storage, set this variable to `true`. Required only if `enable_vpc_flow_logs` is set to true." + type = bool + nullable = false + default = false +} + +variable "vpn_gateways" { + description = "List of VPN Gateways to create." + nullable = false + type = list( + object({ + name = string + subnet_name = string # Do not include prefix, use same name as in `var.subnets` + mode = optional(string) + resource_group = optional(string) + access_tags = optional(list(string), []) + }) + ) + + default = [] +} + +variable "vpe_gateway_cloud_services" { + description = "The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`." + type = set(object({ + service_name = string + vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name. + allow_dns_resolution_binding = optional(bool, false) + })) + default = [] +} + +variable "vpe_gateway_cloud_service_by_crn" { + description = "The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`." + type = set( + object({ + crn = string + vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name. + service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn. + allow_dns_resolution_binding = optional(bool, true) + }) + ) + default = [] +} + +variable "vpe_gateway_service_endpoints" { + description = "Service endpoints to use to create endpoint gateways. Can be `public`, or `private`." + type = string + default = "private" + + validation { + error_message = "Service endpoints can only be `public` or `private`." + condition = contains(["public", "private"], var.vpe_gateway_service_endpoints) + } +} + +variable "vpe_gateway_security_group_ids" { + + # Currently unused — the DA doesn't create any custom security groups. + # The default security group (automatically created with the VPC) is attached to the VPE gateway since no other security groups are present. + # May be useful in the future when DA supports using an existing VPC with custom security groups or if DA supports creating additional security groups we can take `vpe_gateway_security_group_names` as input. + + description = "List of security group ids to attach to each endpoint gateway." + type = list(string) + default = null # Let this default value be null instead of []. Provider issue - https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4546 +} + +variable "vpe_gateway_reserved_ips" { + description = "Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used when a user passes their existing reserved ips created here and not attempt to recreate those." + type = object({ + name = optional(string) # reserved ip name + }) + default = {} +} diff --git a/modules/monolith/version.tf b/modules/monolith/version.tf new file mode 100644 index 000000000..6d52d17c2 --- /dev/null +++ b/modules/monolith/version.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">=1.9.0" + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = ">= 1.78.2, < 2.0.0" + } + time = { + source = "hashicorp/time" + version = ">= 0.9.1, < 1.0.0" + } + } +} diff --git a/tests/existing-resources-monolith/README.md b/tests/existing-resources-monolith/README.md new file mode 100644 index 000000000..705db15d6 --- /dev/null +++ b/tests/existing-resources-monolith/README.md @@ -0,0 +1 @@ +The terraform code in this directory is used by the existing resource test in tests/other_test.go diff --git a/tests/existing-resources-monolith/main.tf b/tests/existing-resources-monolith/main.tf new file mode 100644 index 000000000..3aa2b0abf --- /dev/null +++ b/tests/existing-resources-monolith/main.tf @@ -0,0 +1,24 @@ +############################################################################# +# Provision Resource Group +############################################################################# +module "resource_group" { + source = "terraform-ibm-modules/resource-group/ibm" + version = "1.4.0" + resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null + existing_resource_group_name = var.resource_group +} + +############################################################################## +# Event Notification +############################################################################## + +module "event_notifications" { + source = "terraform-ibm-modules/event-notifications/ibm" + version = "2.7.0" + resource_group_id = module.resource_group.resource_group_id + name = "${var.prefix}-en" + tags = var.resource_tags + plan = "lite" + service_endpoints = "public-and-private" + region = var.region +} diff --git a/tests/existing-resources-monolith/outputs.tf b/tests/existing-resources-monolith/outputs.tf new file mode 100644 index 000000000..4deb3162c --- /dev/null +++ b/tests/existing-resources-monolith/outputs.tf @@ -0,0 +1,18 @@ +######################################################################################################################## +# Outputs +######################################################################################################################## + +output "resource_group_id" { + description = "The id of the resource group where resources are created" + value = module.resource_group.resource_group_id +} + +output "resource_group_name" { + description = "The name of the resource group where resources are created" + value = module.resource_group.resource_group_name +} + +output "event_notifications_instance_crn" { + value = module.event_notifications.crn + description = "CRN of created event notification" +} diff --git a/tests/existing-resources-monolith/provider.tf b/tests/existing-resources-monolith/provider.tf new file mode 100644 index 000000000..df45ef50b --- /dev/null +++ b/tests/existing-resources-monolith/provider.tf @@ -0,0 +1,4 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} diff --git a/tests/existing-resources-monolith/variables.tf b/tests/existing-resources-monolith/variables.tf new file mode 100644 index 000000000..4b4575848 --- /dev/null +++ b/tests/existing-resources-monolith/variables.tf @@ -0,0 +1,32 @@ +############################################################################## +# Input variables +############################################################################## + +variable "ibmcloud_api_key" { + type = string + description = "The IBM Cloud API Key" + sensitive = true +} + +variable "region" { + type = string + description = "Region to provision all resources created by this example" + default = "us-south" +} + +variable "prefix" { + type = string + description = "Prefix to append to all resources created by this example" +} + +variable "resource_group" { + type = string + description = "The name of an existing resource group to provision resources in to. If not set a new resource group will be created using the prefix variable" + default = null +} + +variable "resource_tags" { + type = list(string) + description = "Optional list of tags to be added to created resources" + default = [] +} diff --git a/tests/existing-resources-monolith/version.tf b/tests/existing-resources-monolith/version.tf new file mode 100644 index 000000000..97b20938f --- /dev/null +++ b/tests/existing-resources-monolith/version.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.3.0" + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = ">= 1.64.1" + } + } +} diff --git a/tests/other_test.go b/tests/other_test.go index 1e62fef2e..c81c81694 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -2,10 +2,17 @@ package test import ( + "fmt" + "os" + "strings" "testing" + "github.com/gruntwork-io/terratest/modules/files" + "github.com/gruntwork-io/terratest/modules/logger" + "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testschematic" ) @@ -14,6 +21,7 @@ const advancedExampleDir = "examples/advanced" const basicExampleDir = "examples/basic" const fscloudExampleDir = "examples/fscloud" const crossKmsSupportExampleDir = "examples/cross_kms_support" +const monolithExampleDir = "examples/monolith" func setupOptions(t *testing.T, prefix string, terraformDir string, ocpVersion string) *testhelper.TestOptions { options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ @@ -192,3 +200,98 @@ func TestFSCloudInSchematic(t *testing.T) { err := options.RunSchematicTest() assert.Nil(t, err, "This should not have errored") } + +func provisionPreReq(t *testing.T, p string) (string, *terraform.Options, error) { + // ------------------------------------------------------------------------------------ + // Provision existing resources first + // ------------------------------------------------------------------------------------ + prefix := fmt.Sprintf("%s-%s", p, strings.ToLower(random.UniqueId())) + realTerraformDir := "./existing-resources-monolith" + tempTerraformDir, _ := files.CopyTerraformFolderToTemp(realTerraformDir, prefix) + + // Verify ibmcloud_api_key variable is set + checkVariable := "TF_VAR_ibmcloud_api_key" + val, present := os.LookupEnv(checkVariable) + require.True(t, present, checkVariable+" environment variable not set") + require.NotEqual(t, "", val, checkVariable+" environment variable is empty") + + logger.Log(t, "Tempdir: ", tempTerraformDir) + existingTerraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: tempTerraformDir, + Vars: map[string]interface{}{ + "prefix": prefix, + }, + // Set Upgrade to true to ensure latest version of providers and modules are used by terratest. + // This is the same as setting the -upgrade=true flag with terraform. + Upgrade: true, + }) + + terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix) + _, existErr := terraform.InitAndApplyE(t, existingTerraformOptions) + if existErr != nil { + // assert.True(t, existErr == nil, "Init and Apply of temp existing resource failed") + return "", nil, existErr + } + return prefix, existingTerraformOptions, nil +} + +func TestMonolithExample(t *testing.T) { + t.Parallel() + + prefix, existingTerraformOptions, existErr := provisionPreReq(t, "mon-ocp") + + if existErr != nil { + assert.True(t, existErr == nil, "Init and Apply of temp existing resource failed") + } else { + options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ + Testing: t, + Prefix: prefix, + TarIncludePatterns: []string{ + "*.tf", + monolithExampleDir + "/*.tf", + fullyConfigurableTerraformDir + "/scripts/*.*", + "/scripts/*.*", + "kubeconfig/*.*", + "modules/kube-audit/*.*", + "modules/worker-pool/*.*", + "modules/kube-audit/kubeconfig/*.*", + "modules/kube-audit/scripts/*.*", + "modules/kube-audit/helm-charts/kube-audit/*.*", + "modules/kube-audit/helm-charts/kube-audit/templates/*.*", + "modules/monolith/*.tf", + }, + TemplateFolder: monolithExampleDir, + Tags: []string{"monolith-base-ocp-test"}, + DeleteWorkspaceOnFail: false, + WaitJobCompleteMinutes: 240, + IgnoreAdds: testhelper.Exemptions{ + List: []string{"module.monolith_add_ons.module.scc_wp.restapi_object.cspm"}, + }, + IgnoreUpdates: testhelper.Exemptions{ + List: []string{"module.ocp_base.ibm_container_addons.addons"}, + }, + }) + options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "prefix", Value: prefix, DataType: "string"}, + {Name: "existing_resource_group_name", Value: terraform.Output(t, existingTerraformOptions, "resource_group_name"), DataType: "string"}, + {Name: "kms_encryption_enabled_cluster", Value: true, DataType: "bool"}, + {Name: "existing_event_notifications_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "event_notifications_instance_crn"), DataType: "string"}, + } + + err := options.RunSchematicTest() + assert.Nil(t, err, "This should not have errored") + } + + // Check if "DO_NOT_DESTROY_ON_FAILURE" is set + envVal, _ := os.LookupEnv("DO_NOT_DESTROY_ON_FAILURE") + // Destroy the temporary existing resources if required + if t.Failed() && strings.ToLower(envVal) == "true" { + fmt.Println("Terratest failed. Debug the test and delete resources manually.") + } else { + logger.Log(t, "START: Destroy (prereq resources)") + terraform.Destroy(t, existingTerraformOptions) + terraform.WorkspaceDelete(t, existingTerraformOptions, prefix) + logger.Log(t, "END: Destroy (prereq resources)") + } +} From 14780c320b09020f32dfdb7707b98d807c9969b3 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Mon, 1 Dec 2025 18:03:51 +0530 Subject: [PATCH 02/15] merge changes --- tests/other_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/other_test.go b/tests/other_test.go index 70414fdf8..8a26d9a1a 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -6,13 +6,14 @@ import ( "os" "strings" "testing" + + "github.com/IBM/go-sdk-core/v5/core" "github.com/gruntwork-io/terratest/modules/files" "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/random" - "github.com/stretchr/testify/require" - "github.com/IBM/go-sdk-core/v5/core" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/cloudinfo" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testaddons" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" @@ -293,6 +294,7 @@ func TestMonolithExample(t *testing.T) { terraform.WorkspaceDelete(t, existingTerraformOptions, prefix) logger.Log(t, "END: Destroy (prereq resources)") } +} func TestAddonPermutations(t *testing.T) { testCases := []testaddons.AddonTestCase{ From 66cdfa6b9d3649d4eb74fc1c0d80c7a5a860f7af Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Wed, 3 Dec 2025 02:59:00 +0530 Subject: [PATCH 03/15] Add EN and Apprapp --- README.md | 2 +- examples/monolith/README.md | 4 +- examples/monolith/main.tf | 5 + examples/monolith/outputs.tf | 14 ++ examples/monolith/variables.tf | 49 ++++ modules/monolith/README.md | 69 +++++- modules/monolith/main.tf | 405 +++++++++++++++++++++++++-------- modules/monolith/outputs.tf | 15 ++ modules/monolith/variables.tf | 375 ++++++++++++++++++++++++++++-- tests/other_test.go | 129 +++-------- 10 files changed, 844 insertions(+), 223 deletions(-) diff --git a/README.md b/README.md index f9f232395..ea198e6ab 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Optionally, the module supports advanced security group management for the worke *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
- *
Deploy to IBM Cloud button
+ *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
* [Contributing](#contributing) diff --git a/examples/monolith/README.md b/examples/monolith/README.md index dac08c088..dc3552bfa 100644 --- a/examples/monolith/README.md +++ b/examples/monolith/README.md @@ -1,4 +1,4 @@ -# IBM Cloud OpenShift DA - Monolith Add-ons Module +# IBM Cloud OpenShift DA - Monolith Add-ons Module Example A simple example that shows how to provision a multi zone OCP VPC cluster as well as all foundational infrastructure and supporting services required for a secure and compliant OpenShift (OCP) cluster deployment on IBM Cloud VPC. @@ -19,3 +19,5 @@ The following resources are provisioned by this example: - A COS instance along with 3 buckets for VPC flow logs, metrics/data bucket and activity tracker bucket. - A SCC-WP instance - A VPC instance +- An event notifications instance +- An app configuration service with aggregator enabled diff --git a/examples/monolith/main.tf b/examples/monolith/main.tf index cf7748270..d56c3c17c 100644 --- a/examples/monolith/main.tf +++ b/examples/monolith/main.tf @@ -25,6 +25,8 @@ module "monolith_add_ons" { kms_encryption_enabled_boot_volume = var.kms_encryption_enabled_boot_volume existing_boot_volume_kms_key_crn = var.existing_boot_volume_kms_key_crn kms_plan = var.kms_plan + en_service_plan = var.en_service_plan + en_service_endpoints = var.en_service_endpoints existing_secrets_manager_crn = var.existing_secrets_manager_crn secrets_manager_service_plan = var.secrets_manager_service_plan secrets_manager_endpoint_type = var.secrets_manager_endpoint_type @@ -32,11 +34,14 @@ module "monolith_add_ons" { existing_event_notifications_instance_crn = var.existing_event_notifications_instance_crn existing_cos_instance_crn = var.existing_cos_instance_crn cos_instance_plan = var.cos_instance_plan + management_endpoint_type_for_buckets = var.management_endpoint_type_for_buckets existing_cloud_monitoring_crn = var.existing_cloud_monitoring_crn cloud_monitoring_plan = var.cloud_monitoring_plan existing_cloud_logs_crn = var.existing_cloud_logs_crn scc_workload_protection_service_plan = var.scc_workload_protection_service_plan enable_vpc_flow_logs = var.enable_vpc_flow_logs + app_config_plan = var.app_config_plan + app_config_service_endpoints = var.app_config_service_endpoints } ######################################################################################################################## diff --git a/examples/monolith/outputs.tf b/examples/monolith/outputs.tf index ab94ac26d..d18185c01 100644 --- a/examples/monolith/outputs.tf +++ b/examples/monolith/outputs.tf @@ -130,6 +130,20 @@ output "kms_instance_crn" { description = "The CRN of the Hyper Protect Crypto Service instance or Key Protect instance" } +############################################################################## +# EN Outputs +############################################################################## + +output "en_crn" { + description = "Event Notification crn" + value = module.monolith_add_ons.en_crn +} + +output "en_guid" { + description = "Event Notification guid" + value = module.monolith_add_ons.en_guid +} + ############################################################################## # SM Outputs ############################################################################## diff --git a/examples/monolith/variables.tf b/examples/monolith/variables.tf index bc9b9416e..586793129 100644 --- a/examples/monolith/variables.tf +++ b/examples/monolith/variables.tf @@ -155,6 +155,26 @@ variable "kms_plan" { # validation performed in terraform-ibm-key-protect module } +variable "en_service_plan" { + type = string + description = "The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard`." + default = "standard" + validation { + condition = contains(["lite", "standard"], var.en_service_plan) + error_message = "The specified pricing plan is not available. The following plans are supported: `Lite`, `Standard`" + } +} + +variable "en_service_endpoints" { + type = string + description = "Specify whether you want to enable public, private, or both public and private service endpoints. Possible values: `public`, `private`, `public-and-private`." + default = "public-and-private" + validation { + condition = contains(["public", "private", "public-and-private"], var.en_service_endpoints) + error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`, `public-and-private`" + } +} + variable "existing_secrets_manager_crn" { type = string description = "The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created." @@ -207,6 +227,16 @@ variable "cos_instance_plan" { } } +variable "management_endpoint_type_for_buckets" { + description = "The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Possible values: `public`, `private`, `direct`. If you specify `private`, enable virtual routing and forwarding in your account, and the Terraform runtime must have access to the the IBM Cloud private network." + type = string + default = "direct" + validation { + condition = contains(["public", "private", "direct"], var.management_endpoint_type_for_buckets) + error_message = "The specified management_endpoint_type_for_buckets is not a valid selection!" + } +} + variable "existing_cloud_monitoring_crn" { type = string default = null @@ -255,6 +285,25 @@ variable "enable_vpc_flow_logs" { default = true } +variable "app_config_plan" { + type = string + description = "Plan for the App Configuration service instance." + default = "enterprise" + nullable = false +} + +variable "app_config_service_endpoints" { + type = string + description = "Service Endpoints for the App Configuration service instance, valid endpoints are public or public-and-private." + default = "public" + nullable = false + + validation { + condition = contains(["public", "public-and-private"], var.app_config_service_endpoints) + error_message = "Value for service endpoints must be one of the following: \"public\" or \"public-and-private\"." + } +} + ######################################################################################################################## # OCP VPC cluster ######################################################################################################################## diff --git a/modules/monolith/README.md b/modules/monolith/README.md index 83016376c..f36e5da80 100644 --- a/modules/monolith/README.md +++ b/modules/monolith/README.md @@ -41,22 +41,28 @@ module "monolith_ocp_add_ons" { | Name | Source | Version | |------|--------|---------| | [activity\_tracker](#module\_activity\_tracker) | terraform-ibm-modules/activity-tracker/ibm | 1.5.0 | +| [app\_config](#module\_app\_config) | terraform-ibm-modules/app-configuration/ibm | 1.14.2 | | [at\_cos\_bucket](#module\_at\_cos\_bucket) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | | [cloud\_logs](#module\_cloud\_logs) | terraform-ibm-modules/cloud-logs/ibm | 1.10.0 | -| [cloud\_logs\_buckets](#module\_cloud\_logs\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.7 | +| [cloud\_logs\_buckets](#module\_cloud\_logs\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | | [cloud\_monitoring](#module\_cloud\_monitoring) | terraform-ibm-modules/cloud-monitoring/ibm | 1.11.0 | | [cos](#module\_cos) | terraform-ibm-modules/cos/ibm//modules/fscloud | 10.5.9 | -| [existing\_boot\_volume\_kms\_key\_crn\_parser](#module\_existing\_boot\_volume\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.2.0 | +| [cos\_secrets\_manager\_service\_credentials](#module\_cos\_secrets\_manager\_service\_credentials) | terraform-ibm-modules/secrets-manager/ibm//modules/secrets | 2.11.9 | +| [en\_cos\_buckets](#module\_en\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | +| [en\_secrets\_manager\_service\_credentials](#module\_en\_secrets\_manager\_service\_credentials) | terraform-ibm-modules/secrets-manager/ibm//modules/secrets | 2.11.9 | +| [event\_notifications](#module\_event\_notifications) | terraform-ibm-modules/event-notifications/ibm | 2.7.0 | +| [existing\_boot\_volume\_kms\_key\_crn\_parser](#module\_existing\_boot\_volume\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | | [existing\_cloud\_monitoring\_crn\_parser](#module\_existing\_cloud\_monitoring\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_cluster\_kms\_key\_crn\_parser](#module\_existing\_cluster\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.2.0 | +| [existing\_cluster\_kms\_key\_crn\_parser](#module\_existing\_cluster\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | | [existing\_cos\_instance\_crn\_parser](#module\_existing\_cos\_instance\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_kms\_crn\_parser](#module\_existing\_kms\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.2.0 | +| [existing\_en\_crn\_parser](#module\_existing\_en\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | +| [existing\_kms\_crn\_parser](#module\_existing\_kms\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | +| [existing\_sm\_crn\_parser](#module\_existing\_sm\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | | [kms](#module\_kms) | terraform-ibm-modules/kms-all-inclusive/ibm | 5.4.5 | | [metrics\_routing](#module\_metrics\_routing) | terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing | 1.11.0 | | [scc\_wp](#module\_scc\_wp) | terraform-ibm-modules/scc-workload-protection/ibm | 1.16.4 | | [secrets\_manager](#module\_secrets\_manager) | terraform-ibm-modules/secrets-manager/ibm | 2.11.9 | | [secrets\_manager\_crn\_parser](#module\_secrets\_manager\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [secrets\_manager\_service\_credentials](#module\_secrets\_manager\_service\_credentials) | terraform-ibm-modules/secrets-manager/ibm//modules/secrets | 2.11.9 | | [vpc](#module\_vpc) | terraform-ibm-modules/landing-zone-vpc/ibm | 8.9.1 | | [vpc\_cos\_buckets](#module\_vpc\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | | [vpe\_gateway](#module\_vpe\_gateway) | terraform-ibm-modules/vpe-gateway/ibm | 4.6.6 | @@ -65,12 +71,17 @@ module "monolith_ocp_add_ons" { | Name | Type | |------|------| -| [ibm_en_subscription_email.email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | -| [ibm_en_topic.en_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | -| [ibm_iam_authorization_policy.secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [ibm_en_subscription_email.apprapp_email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | +| [ibm_en_subscription_email.en_email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | +| [ibm_en_topic.en_apprapp_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | +| [ibm_en_topic.en_sm_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | +| [ibm_iam_authorization_policy.cos_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [ibm_iam_authorization_policy.en_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | | [time_sleep.wait_for_cos_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [time_sleep.wait_for_en_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | | [time_sleep.wait_for_secrets_manager](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | -| [ibm_en_destinations.en_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | +| [ibm_en_destinations.en_apprapp_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | +| [ibm_en_destinations.en_sm_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | ### Inputs @@ -83,14 +94,19 @@ module "monolith_ocp_add_ons" { | [activity\_tracker\_cos\_target\_bucket\_class](#input\_activity\_tracker\_cos\_target\_bucket\_class) | The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`. | `string` | `"smart"` | no | | [activity\_tracker\_cos\_target\_bucket\_name](#input\_activity\_tracker\_cos\_target\_bucket\_name) | The name of the Cloud Object Storage bucket to create for the Cloud Object Storage target to store AT events. Cloud Object Storage bucket names are globally unique. If the `add_bucket_name_suffix` variable is set to `true`, 4 random characters are added to this name to ensure that the name of the bucket is globally unique. If the prefix input variable is passed, the name of the instance is prefixed to the value in the `-value` format. | `string` | `"at-events-cos-bucket"` | no | | [address\_prefixes](#input\_address\_prefixes) | The IP range that will be defined for the VPC for a certain location. Use only with manual address prefixes. |
object({
zone-1 = optional(list(string))
zone-2 = optional(list(string))
zone-3 = optional(list(string))
})
|
{
"zone-1": null,
"zone-2": null,
"zone-3": null
}
| no | -| [app\_config\_crn](#input\_app\_config\_crn) | The CRN of an existing App Config instance to use with the SCC Workload Protection instance. Required if `cspm_enabled` is true. NOTE: Ensure the App Config instance has configuration aggregator enabled. | `string` | `null` | no | +| [app\_config\_collections](#input\_app\_config\_collections) | (Optional, list) A list of collections to be added to the App Configuration instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-app-configuration/tree/main/solutions/fully-configurable/DA-collections.md). |
list(object({
name = string
collection_id = string
description = optional(string, null)
tags = optional(string, null)
}))
| `[]` | no | +| [app\_config\_event\_notifications\_source\_name](#input\_app\_config\_event\_notifications\_source\_name) | The name by which Event Notifications source will be created in the existing Event Notification instance. | `string` | `"app-config-en"` | no | +| [app\_config\_name](#input\_app\_config\_name) | Name for the App Configuration service instance. | `string` | `"app-config"` | no | +| [app\_config\_plan](#input\_app\_config\_plan) | Plan for the App Configuration service instance. | `string` | `"enterprise"` | no | +| [app\_config\_service\_endpoints](#input\_app\_config\_service\_endpoints) | Service Endpoints for the App Configuration service instance, valid endpoints are public or public-and-private. | `string` | `"public-and-private"` | no | +| [app\_config\_tags](#input\_app\_config\_tags) | Optional list of tags to be added to the App Config instance. | `list(string)` | `[]` | no | | [append\_random\_bucket\_name\_suffix](#input\_append\_random\_bucket\_name\_suffix) | Append random generated suffix (4 characters long) to the newly provisioned IBM Cloud Logs Object Storage bucket names. | `bool` | `true` | no | +| [apprapp\_cbr\_rules](#input\_apprapp\_cbr\_rules) | The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md). |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | | [boot\_volume\_kms\_key\_name](#input\_boot\_volume\_kms\_key\_name) | The name for the key created for the block storage volumes. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key"` | no | | [boot\_volume\_kms\_key\_ring\_name](#input\_boot\_volume\_kms\_key\_ring\_name) | The name for the key ring created for the block storage volumes key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key-ring"` | no | | [clean\_default\_security\_group\_acl](#input\_clean\_default\_security\_group\_acl) | Remove all rules from the default VPC security group and VPC ACL (less permissive). | `bool` | `true` | no | | [cloud\_logs\_access\_tags](#input\_cloud\_logs\_access\_tags) | A list of access tags to apply to the IBM Cloud Logs instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | | [cloud\_logs\_cbr\_rules](#input\_cloud\_logs\_cbr\_rules) | (Optional, list) List of context-based restrictions rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [cloud\_logs\_cos\_buckets\_class](#input\_cloud\_logs\_cos\_buckets\_class) | The storage class of the newly provisioned IBM Cloud Logs Object Storage buckets. Possible values: `standard` or `smart`. Applies only if `existing_cloud_logs_crn` is not provided. | `string` | `"smart"` | no | | [cloud\_logs\_data\_cos\_bucket\_name](#input\_cloud\_logs\_data\_cos\_bucket\_name) | The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs-logs-bucket"` | no | | [cloud\_logs\_instance\_name](#input\_cloud\_logs\_instance\_name) | The name of the IBM Cloud Logs instance to create. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs"` | no | | [cloud\_logs\_metrics\_cos\_bucket\_name](#input\_cloud\_logs\_metrics\_cos\_bucket\_name) | The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs-metrics-bucket"` | no | @@ -105,27 +121,48 @@ module "monolith_ocp_add_ons" { | [cloud\_monitoring\_resource\_tags](#input\_cloud\_monitoring\_resource\_tags) | Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings). | `list(string)` | `[]` | no | | [cluster\_kms\_key\_name](#input\_cluster\_kms\_key\_name) | The name of the key to be created for the cluster's Object Storage bucket encryption. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key"` | no | | [cluster\_kms\_key\_ring\_name](#input\_cluster\_kms\_key\_ring\_name) | The name of the key ring to be created for the cluster's Object Storage bucket encryption key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key-ring"` | no | +| [config\_aggregator\_enterprise\_account\_group\_ids\_to\_assign](#input\_config\_aggregator\_enterprise\_account\_group\_ids\_to\_assign) | A list of enterprise account group IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all account groups. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`. | `list(string)` |
[
"all"
]
| no | +| [config\_aggregator\_enterprise\_account\_ids\_to\_assign](#input\_config\_aggregator\_enterprise\_account\_ids\_to\_assign) | A list of enterprise account IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all accounts. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`. | `list(string)` | `[]` | no | +| [config\_aggregator\_enterprise\_id](#input\_config\_aggregator\_enterprise\_id) | If the account is an enterprise account, this value should be set to the enterprise ID (NOTE: This is different to the account ID). | `string` | `null` | no | +| [config\_aggregator\_enterprise\_trusted\_profile\_name](#input\_config\_aggregator\_enterprise\_trusted\_profile\_name) | The name to give the enterprise viewer trusted profile with that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"config-aggregator-enterprise-trusted-profile"` | no | +| [config\_aggregator\_enterprise\_trusted\_profile\_template\_name](#input\_config\_aggregator\_enterprise\_trusted\_profile\_template\_name) | The name to give the trusted profile template that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"config-aggregator-trusted-profile-template"` | no | +| [config\_aggregator\_resource\_collection\_regions](#input\_config\_aggregator\_resource\_collection\_regions) | From which region do you want to collect configuration data? Only applies if `enable_config_aggregator` is set to true. | `list(string)` |
[
"all"
]
| no | +| [config\_aggregator\_trusted\_profile\_name](#input\_config\_aggregator\_trusted\_profile\_name) | The name to give the trusted profile that will be created if `enable_config_aggregator` is set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"config-aggregator-trusted-profile"` | no | +| [cos\_buckets\_class](#input\_cos\_buckets\_class) | The storage class of the newly provisioned IBM Cloud Logs Object Storage buckets. Possible values: `standard` or `smart`. Applies only if `existing_cloud_logs_crn` is not provided. | `string` | `"smart"` | no | | [cos\_instance\_access\_tags](#input\_cos\_instance\_access\_tags) | A list of access tags to apply to the Object Storage instance created by the module. | `list(string)` | `[]` | no | | [cos\_instance\_cbr\_rules](#input\_cos\_instance\_cbr\_rules) | The list of context-based restriction rules to create for the instance. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | | [cos\_instance\_name](#input\_cos\_instance\_name) | The name for the IBM Cloud Object Storage instance provisioned by this solution. If a value is passed for `prefix`, the instance will be named with the prefix value in the format of `-value`. | `string` | `"cos-instance"` | no | | [cos\_instance\_plan](#input\_cos\_instance\_plan) | The plan to use when Object Storage instances are created. | `string` | `"standard"` | no | | [cos\_instance\_resource\_tags](#input\_cos\_instance\_resource\_tags) | A list of resource tags to apply to the Object Storage instance. | `list(string)` | `[]` | no | | [cos\_target\_name](#input\_cos\_target\_name) | Name of the cos target for activity tracker event routing. | `string` | `null` | no | -| [cspm\_enabled](#input\_cspm\_enabled) | Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service. | `bool` | `false` | no | +| [cspm\_enabled](#input\_cspm\_enabled) | Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service. | `bool` | `true` | no | | [default\_network\_acl\_name](#input\_default\_network\_acl\_name) | Name of the Default ACL. If null, a name will be automatically generated. | `string` | `null` | no | | [default\_routing\_table\_name](#input\_default\_routing\_table\_name) | Name of the Default Routing Table. If null, a name will be automatically generated. | `string` | `null` | no | | [default\_security\_group\_name](#input\_default\_security\_group\_name) | Name of the Default Security Group. If null, a name will be automatically generated. | `string` | `null` | no | | [disable\_access\_key\_creation](#input\_disable\_access\_key\_creation) | When set to true, disables the creation of a default manager access key which is required by agents to ingest metrics. | `bool` | `false` | no | | [dual\_auth\_delete\_enabled](#input\_dual\_auth\_delete\_enabled) | If set to `true`, a dual authorization policy is enabled on the Key Protect instance. After the dual authorization policy is set on the instance, it cannot be reverted. An instance with dual authorization policy enabled cannot be destroyed by using Terraform. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `false` | no | +| [en\_access\_tags](#input\_en\_access\_tags) | A list of access tags to apply to the Event Notifications instance created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial). | `list(string)` | `[]` | no | +| [en\_cbr\_rules](#input\_en\_cbr\_rules) | The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md). |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [en\_cos\_bucket\_access\_tags](#input\_en\_cos\_bucket\_access\_tags) | A list of access tags to apply to the Cloud Object Storage bucket created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial). | `list(string)` | `[]` | no | +| [en\_cos\_bucket\_name](#input\_en\_cos\_bucket\_name) | The name to use when creating the Object Storage bucket for the storage of failed delivery events. Bucket names are globally unique. If `add_bucket_name_suffix` is set to `true`, a random 4 character string is added to this name to help ensure that the bucket name is unique. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"base-event-notifications-bucket"` | no | +| [en\_resource\_tags](#input\_en\_resource\_tags) | The list of tags to add to the Event Notifications instance. | `list(string)` | `[]` | no | +| [en\_service\_credential\_names](#input\_en\_service\_credential\_names) | A mapping of names and associated roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/blob/main/solutions/fully-configurable/DA-types.md#service-credentials-). | `map(string)` | `{}` | no | +| [en\_service\_credential\_secrets](#input\_en\_service\_credential\_secrets) | Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets). |
list(object({
secret_group_name = string # pragma: allowlist secret
secret_group_description = optional(string) # pragma: allowlist secret
existing_secret_group = optional(bool) # pragma: allowlist secret
service_credentials = list(object({ # pragma: allowlist secret
secret_name = string # pragma: allowlist secret
service_credentials_source_service_role_crn = string # pragma: allowlist secret
secret_labels = optional(list(string)) # pragma: allowlist secret
secret_auto_rotation = optional(bool) # pragma: allowlist secret
secret_auto_rotation_unit = optional(string) # pragma: allowlist secret
secret_auto_rotation_interval = optional(number) # pragma: allowlist secret
service_credentials_ttl = optional(string) # pragma: allowlist secret
service_credential_secret_description = optional(string) # pragma: allowlist secret

}))
}))
| `[]` | no | +| [en\_service\_endpoints](#input\_en\_service\_endpoints) | Specify whether you want to enable public, private, or both public and private service endpoints. Possible values: `public`, `private`, `public-and-private`. | `string` | `"private"` | no | +| [en\_service\_plan](#input\_en\_service\_plan) | The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard`. | `string` | `"standard"` | no | | [enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs](#input\_enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs) | When set to `true`, you must provide a value for `existing_cloud_logs_crn` to enable event routing from Activity Tracker to a Cloud Logs instance. | `bool` | `true` | no | | [enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket](#input\_enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket) | When set to `true`, you must provide a value for `existing_cos_instance_crn` to enable event routing from Activity Tracker to a Object Storage bucket. | `bool` | `true` | no | +| [enable\_collecting\_failed\_events](#input\_enable\_collecting\_failed\_events) | Set to true to enable Cloud Object Storage integration. If enabled, you must also provide a Cloud Object Storage instance (for storing failed events) using the `existing_cos_instance_crn` variable. For more information, [see here](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-cfe-integrations). | `bool` | `true` | no | +| [enable\_config\_aggregator](#input\_enable\_config\_aggregator) | Set to true to enable configuration aggregator. By setting to true a trusted profile will be created with the required access to record configuration data from all resources across regions in your account. [Learn more](https://cloud.ibm.com/docs/app-configuration?topic=app-configuration-ac-configuration-aggregator). | `bool` | `true` | no | | [enable\_metrics](#input\_enable\_metrics) | Set to `true` to enable metrics on the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. In order to view metrics, you need an IBM Cloud Monitoring (Sysdig) instance that is located in the same region as the Key Protect instance. After you provision a Monitoring instance, enable platform metrics to monitor your Key Protect instance. | `bool` | `true` | no | | [enable\_metrics\_routing\_to\_cloud\_monitoring](#input\_enable\_metrics\_routing\_to\_cloud\_monitoring) | Whether to enable metrics routing from IBM Cloud Metric Routing to Cloud Monitoring. | `bool` | `true` | no | | [enable\_platform\_metrics](#input\_enable\_platform\_metrics) | When set to `true`, the IBM Cloud Monitoring instance collects the platform metrics. | `bool` | `false` | no | | [enable\_primary\_metadata\_region](#input\_enable\_primary\_metadata\_region) | When set to `true`, sets `primary_metadata_region` to `region`, storing Metrics Router metadata in that region. When `false`, no region is set and the default global region is used. For new accounts, creating targets and routes will fail until primary\_metadata\_region is set, so it is recommended to default enable\_primary\_metadata\_region to true. | `bool` | `true` | no | | [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | To enable VPC Flow logs, set this to true. | `bool` | `false` | no | | [event\_notifications\_email\_list](#input\_event\_notifications\_email\_list) | The list of email address to target out when Secrets Manager triggers an event | `list(string)` | `[]` | no | +| [event\_notifications\_endpoint\_url](#input\_event\_notifications\_endpoint\_url) | The URL of the Event Notifications service endpoint to use for notifying configuration changes. For more information on the endpoint URL for Event Notifications, go to [Service endpoints](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-regions-endpoints#en-service-endpoints). It is required if `enable_event_notifications` is set to true. | `string` | `null` | no | | [event\_notifications\_from\_email](#input\_event\_notifications\_from\_email) | The email address used to send any Secrets Manager event coming via Event Notifications | `string` | `"compliancealert@ibm.com"` | no | +| [event\_notifications\_instance\_name](#input\_event\_notifications\_instance\_name) | The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications"` | no | | [event\_notifications\_reply\_to\_email](#input\_event\_notifications\_reply\_to\_email) | The email address specified in the 'reply\_to' section for any Secret Manager event coming via Event Notifications | `string` | `"no-reply@ibm.com"` | no | | [existing\_activity\_tracker\_cos\_target\_bucket\_endpoint](#input\_existing\_activity\_tracker\_cos\_target\_bucket\_endpoint) | The name of an existing Cloud Object Storage bucket endpoint to use for setting up IBM Cloud Activity Tracker Event Routing. If an existing endpoint is not specified, the endpoint of the new Cloud Object Storage bucket is used. | `string` | `null` | no | | [existing\_activity\_tracker\_cos\_target\_bucket\_name](#input\_existing\_activity\_tracker\_cos\_target\_bucket\_name) | The name of an existing bucket within the Cloud Object Storage instance in which to store IBM Cloud Activity Tracker Event Routing. If an existing Cloud Object Storage bucket is not specified, a bucket is created. | `string` | `null` | no | @@ -156,6 +193,7 @@ module "monolith_ocp_add_ons" { | [kms\_encryption\_enabled\_buckets](#input\_kms\_encryption\_enabled\_buckets) | Set to true to enable KMS encryption on the Object Storage buckets created for the IBM Cloud Logs instance. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn` (to create a new key). Can not be set to true if passing a value for `existing_cloud_logs_crn`. | `bool` | `false` | no | | [kms\_encryption\_enabled\_cluster](#input\_kms\_encryption\_enabled\_cluster) | Set to true to enable KMS encryption for the cluster's Object Storage bucket. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn`. | `bool` | `false` | no | | [kms\_endpoint\_type](#input\_kms\_endpoint\_type) | The endpoint for communicating with the KMS instance. Possible values: `public`, `private`. Applies only if `kms_encryption_enabled_cluster` is true | `string` | `"private"` | no | +| [kms\_endpoint\_url](#input\_kms\_endpoint\_url) | The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input. | `string` | `null` | no | | [kms\_instance\_name](#input\_kms\_instance\_name) | The name to give the Key Protect instance that that is created by this module. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"key-protect"` | no | | [kms\_plan](#input\_kms\_plan) | Plan for the Key Protect instance. Supported values are 'tiered-pricing' and 'cross-region-resiliency'. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"tiered-pricing"` | no | | [kms\_resource\_tags](#input\_kms\_resource\_tags) | Optional list of tags to add to the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `list(string)` | `[]` | no | @@ -189,7 +227,12 @@ module "monolith_ocp_add_ons" { | [security\_group\_rules](#input\_security\_group\_rules) | A list of security group rules to be added to the default vpc security group (default empty). |
list(
object({
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
| `[]` | no | | [service\_cred](#input\_service\_cred) | Service configuration for COS. |
list(object({
secret_group_name = string # pragma: allowlist secret
secret_group_description = optional(string) # pragma: allowlist secret
existing_secret_group = optional(bool) # pragma: allowlist secret
service_credentials = list(object({ # pragma: allowlist secret
secret_name = string # pragma: allowlist secret
service_credentials_source_service_role_crn = string # pragma: allowlist secret
secret_labels = optional(list(string)) # pragma: allowlist secret
secret_auto_rotation = optional(bool) # pragma: allowlist secret
secret_auto_rotation_unit = optional(string) # pragma: allowlist secret
secret_auto_rotation_interval = optional(number) # pragma: allowlist secret
service_credentials_ttl = optional(string) # pragma: allowlist secret
service_credential_secret_description = optional(string) # pragma: allowlist secret

}))
}))
| `[]` | no | | [skip\_activity\_tracker\_cos\_auth\_policy](#input\_skip\_activity\_tracker\_cos\_auth\_policy) | To skip creating an IAM authorization policy that allows the Activity Tracker to write to the Cloud Object Storage instance, set this variable to `true`. | `bool` | `false` | no | +| [skip\_app\_config\_event\_notifications\_auth\_policy](#input\_skip\_app\_config\_event\_notifications\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits App configuration instances to integrate with Event Notification in the same account. | `bool` | `false` | no | +| [skip\_app\_config\_kms\_auth\_policy](#input\_skip\_app\_config\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits App configuration instances in the resource group to read the encryption key from the KMS instance in the same account. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the other account. | `bool` | `false` | no | | [skip\_cloud\_logs\_cos\_auth\_policy](#input\_skip\_cloud\_logs\_cos\_auth\_policy) | To skip creating an IAM authorization policy that allows the IBM Cloud logs to write to the Cloud Object Storage bucket, set this variable to `true`. | `bool` | `false` | no | +| [skip\_event\_notifications\_cos\_auth\_policy](#input\_skip\_event\_notifications\_cos\_auth\_policy) | Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy. | `bool` | `false` | no | +| [skip\_event\_notifications\_kms\_auth\_policy](#input\_skip\_event\_notifications\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | +| [skip\_event\_notifications\_secrets\_manager\_auth\_policy](#input\_skip\_event\_notifications\_secrets\_manager\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing\_secrets\_manager\_crn' is not passed. | `bool` | `false` | no | | [skip\_logs\_routing\_auth\_policy](#input\_skip\_logs\_routing\_auth\_policy) | Whether to create an IAM authorization policy that permits the Logs Routing server 'Sender' access to the IBM Cloud Logs instance created by this Deployable Architecture. | `bool` | `false` | no | | [skip\_secrets\_manager\_cos\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_cos\_iam\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Cloud Object Storage. Set to `true` to use an existing policy. | `bool` | `false` | no | | [skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy) | If set to true, this skips the creation of a service to service authorization from Secrets Manager to Event Notifications. If false, the service to service authorization is created. | `bool` | `false` | no | @@ -232,6 +275,8 @@ module "monolith_ocp_add_ons" { | [cos\_instance\_crn](#output\_cos\_instance\_crn) | COS instance crn | | [cos\_instance\_guid](#output\_cos\_instance\_guid) | COS instance guid | | [cos\_instance\_id](#output\_cos\_instance\_id) | COS instance ID | +| [en\_crn](#output\_en\_crn) | Event Notification crn | +| [en\_guid](#output\_en\_guid) | Event Notification guid | | [key\_protect\_id](#output\_key\_protect\_id) | Key Protect instance ID when an instance is created, otherwise null | | [kms\_account\_id](#output\_kms\_account\_id) | The account ID of the KMS instance. | | [kms\_config](#output\_kms\_config) | The KMS config needed for OCP cluster | diff --git a/modules/monolith/main.tf b/modules/monolith/main.tf index e5a4551b3..7a33e6fad 100644 --- a/modules/monolith/main.tf +++ b/modules/monolith/main.tf @@ -5,21 +5,21 @@ module "existing_kms_crn_parser" { count = var.existing_kms_instance_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.2.0" + version = "1.3.0" crn = var.existing_kms_instance_crn } module "existing_cluster_kms_key_crn_parser" { count = var.existing_cluster_kms_key_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.2.0" + version = "1.3.0" crn = var.existing_cluster_kms_key_crn } module "existing_boot_volume_kms_key_crn_parser" { count = var.existing_boot_volume_kms_key_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.2.0" + version = "1.3.0" crn = var.existing_boot_volume_kms_key_crn } @@ -101,6 +101,217 @@ module "kms" { cbr_rules = var.kms_cbr_rules } +################################################################################# +# Cloud Monitoring +################################################################################# + +module "existing_cloud_monitoring_crn_parser" { + count = var.existing_cloud_monitoring_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.3.0" + crn = var.existing_cloud_monitoring_crn +} + +locals { + create_cloud_monitoring = var.existing_cloud_monitoring_crn == null + cloud_monitoring_crn = local.create_cloud_monitoring ? module.cloud_monitoring[0].crn : var.existing_cloud_monitoring_crn + cloud_monitoring_instance_name = "${local.prefix}${var.cloud_monitoring_instance_name}" + metrics_router_target_name = "${local.prefix}${var.metrics_routing_target_name}" + metrics_router_route_name = "${local.prefix}${var.metrics_routing_route_name}" + + default_metrics_router_route = var.enable_metrics_routing_to_cloud_monitoring ? [{ + name = local.metrics_router_route_name + rules = [{ + action = "send" + targets = [{ + id = module.metrics_routing[0].metrics_router_targets[local.metrics_router_target_name].id + }] + inclusion_filters = [] + }] + }] : [] +} + +module "cloud_monitoring" { + count = local.create_cloud_monitoring ? 1 : 0 + source = "terraform-ibm-modules/cloud-monitoring/ibm" + version = "1.11.0" + resource_group_id = var.resource_group_id + region = var.region + instance_name = local.cloud_monitoring_instance_name + plan = var.cloud_monitoring_plan + resource_tags = var.cloud_monitoring_resource_tags + access_tags = var.cloud_monitoring_access_tags + resource_keys = var.cloud_monitoring_resource_keys + disable_access_key_creation = var.disable_access_key_creation + service_endpoints = "public-and-private" + enable_platform_metrics = var.enable_platform_metrics + cbr_rules = var.cloud_monitoring_cbr_rules +} + +module "metrics_routing" { + count = var.enable_metrics_routing_to_cloud_monitoring ? 1 : 0 + source = "terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing" + version = "1.11.0" + metrics_router_targets = [ + { + destination_crn = local.cloud_monitoring_crn + target_name = local.metrics_router_target_name + target_region = var.region + skip_metrics_router_auth_policy = false + } + ] + + metrics_router_routes = length(var.metrics_router_routes) != 0 ? var.metrics_router_routes : local.default_metrics_router_route + metrics_router_settings = var.enable_primary_metadata_region ? { primary_metadata_region = var.region } : null +} + + + +######################################################################################################################## +# Event Notifications +######################################################################################################################## + +# If existing EN instance CRN passed, parse details from it +module "existing_en_crn_parser" { + count = var.existing_event_notifications_instance_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.3.0" + crn = var.existing_event_notifications_instance_crn +} + +locals { + use_existing_en_instance = var.existing_event_notifications_instance_crn != null + existing_en_instance_guid = local.use_existing_en_instance ? module.existing_en_crn_parser[0].service_instance : null + eventnotification_guid = local.use_existing_en_instance ? local.existing_en_instance_guid : module.event_notifications[0].guid + eventnotification_crn = local.use_existing_en_instance ? var.existing_event_notifications_instance_crn : module.event_notifications[0].crn + en_cos_bucket_name = "${local.prefix}${var.en_cos_bucket_name}" +} + +module "event_notifications" { + count = local.use_existing_en_instance ? 0 : 1 + source = "terraform-ibm-modules/event-notifications/ibm" + version = "2.7.0" + resource_group_id = var.resource_group_id + region = var.region + name = "${local.prefix}${var.event_notifications_instance_name}" + plan = var.en_service_plan + tags = var.en_resource_tags + access_tags = var.en_access_tags + service_endpoints = var.en_service_endpoints + service_credential_names = var.en_service_credential_names + # KMS Related + kms_encryption_enabled = var.kms_encryption_enabled_cluster + kms_endpoint_url = (var.kms_encryption_enabled_boot_volume && var.existing_boot_volume_kms_key_crn == null) || (var.kms_encryption_enabled_cluster && var.existing_cluster_kms_key_crn == null) ? var.kms_endpoint_type == "private" ? module.kms[0].kms_private_endpoint : module.kms[0].kms_public_endpoint : var.kms_endpoint_url + existing_kms_instance_crn = var.existing_kms_instance_crn != null ? var.existing_kms_instance_crn : module.kms[0].key_protect_crn + root_key_id = local.cluster_kms_key_id + skip_en_kms_auth_policy = var.skip_event_notifications_kms_auth_policy + # COS Related + cos_integration_enabled = var.enable_collecting_failed_events + cos_bucket_name = var.existing_event_notifications_instance_crn == null && var.enable_collecting_failed_events ? module.en_cos_buckets[0].buckets[local.en_cos_bucket_name].bucket_name : null + cos_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id + skip_en_cos_auth_policy = var.skip_event_notifications_cos_auth_policy + cos_endpoint = var.existing_event_notifications_instance_crn == null && var.enable_collecting_failed_events ? "https://${module.en_cos_buckets[0].buckets[local.en_cos_bucket_name].s3_endpoint_direct}" : null + cbr_rules = var.en_cbr_rules +} + +locals { + bucket_config = [{ + access_tags = var.en_cos_bucket_access_tags + bucket_name = local.en_cos_bucket_name + add_bucket_name_suffix = var.append_random_bucket_name_suffix + kms_encryption_enabled = var.kms_encryption_enabled_buckets + kms_guid = local.cluster_existing_kms_guid + kms_key_crn = local.cluster_kms_key_crn + skip_iam_authorization_policy = false + management_endpoint_type = var.management_endpoint_type_for_buckets + storage_class = var.cos_buckets_class + resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id + region_location = var.region + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn + } + force_delete = true + }] +} + +module "en_cos_buckets" { + count = var.enable_collecting_failed_events && var.existing_event_notifications_instance_crn == null ? 1 : 0 + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.8" + bucket_configs = local.bucket_config +} + +######################################################################################################################## +# Service Credentials +######################################################################################################################## + +# If existing EN instance CRN passed, parse details from it +module "existing_sm_crn_parser" { + count = var.existing_secrets_manager_crn != null ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.3.0" + crn = var.existing_secrets_manager_crn +} + +locals { + en_service_credential_secrets = [ + for service_credentials in var.en_service_credential_secrets : { + secret_group_name = service_credentials.secret_group_name + secret_group_description = service_credentials.secret_group_description + existing_secret_group = service_credentials.existing_secret_group + secrets = [ + for secret in service_credentials.service_credentials : { + secret_name = secret.secret_name + secret_labels = secret.secret_labels + secret_auto_rotation = secret.secret_auto_rotation + secret_auto_rotation_unit = secret.secret_auto_rotation_unit + secret_auto_rotation_interval = secret.secret_auto_rotation_interval + service_credentials_ttl = secret.service_credentials_ttl + service_credential_secret_description = secret.service_credential_secret_description + service_credentials_source_service_role_crn = secret.service_credentials_source_service_role_crn + service_credentials_source_service_crn = local.eventnotification_crn + secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6 + } + ] + } + ] +} + +# create a service authorization between Secrets Manager and the target service (Event Notification) +resource "ibm_iam_authorization_policy" "en_secrets_manager_key_manager" { + count = var.skip_event_notifications_secrets_manager_auth_policy || var.existing_secrets_manager_crn == null ? 0 : 1 + source_service_name = "secrets-manager" + source_resource_instance_id = local.existing_secrets_manager_instance_guid + target_service_name = "event-notifications" + target_resource_instance_id = local.eventnotification_guid + roles = ["Key Manager"] + description = "Allow Secrets Manager instance to manage key for the event-notification instance" +} + +# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 +resource "time_sleep" "wait_for_en_authorization_policy" { + depends_on = [ibm_iam_authorization_policy.en_secrets_manager_key_manager] + create_duration = "30s" +} + +module "en_secrets_manager_service_credentials" { + count = length(local.en_service_credential_secrets) > 0 ? 1 : 0 + depends_on = [time_sleep.wait_for_en_authorization_policy] + source = "terraform-ibm-modules/secrets-manager/ibm//modules/secrets" + version = "2.11.9" + existing_sm_instance_guid = local.existing_secrets_manager_instance_guid + existing_sm_instance_region = local.existing_secrets_manager_instance_region + endpoint_type = var.secrets_manager_endpoint_type + secrets = local.en_service_credential_secrets +} + ################################################################################# # Secrets Manager ################################################################################# @@ -111,7 +322,6 @@ locals { secrets_manager_guid = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[7] : null) : module.secrets_manager[0].secrets_manager_guid secrets_manager_crn = var.existing_secrets_manager_crn != null ? var.existing_secrets_manager_crn : module.secrets_manager[0].secrets_manager_crn secrets_manager_region = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[5] : null) : module.secrets_manager[0].secrets_manager_region - enable_event_notifications = var.existing_event_notifications_instance_crn == null || var.existing_event_notifications_instance_crn == "" ? false : true secret_groups_with_prefix = [ for group in var.secret_groups : merge(group, { access_group_name = group.access_group_name != null ? "${local.prefix}${group.access_group_name}" : null @@ -143,8 +353,8 @@ module "secrets_manager" { kms_key_crn = local.cluster_kms_key_crn skip_kms_iam_authorization_policy = var.skip_secrets_manager_kms_iam_auth_policy #|| local.create_cross_account_auth_policy # event notifications dependency - enable_event_notification = local.enable_event_notifications - existing_en_instance_crn = local.enable_event_notifications ? var.existing_event_notifications_instance_crn : null + enable_event_notification = true + existing_en_instance_crn = local.eventnotification_crn skip_en_iam_authorization_policy = var.skip_secrets_manager_event_notifications_iam_auth_policy cbr_rules = var.secrets_manager_cbr_rules endpoint_type = var.secrets_manager_endpoint_type @@ -157,28 +367,28 @@ module "secrets_manager" { ################################################################################# locals { - parsed_existing_en_instance_crn = var.existing_event_notifications_instance_crn == null || var.existing_event_notifications_instance_crn == "" ? [] : split(":", var.existing_event_notifications_instance_crn) + parsed_existing_en_instance_crn = split(":", local.eventnotification_crn) existing_en_guid = length(local.parsed_existing_en_instance_crn) > 0 ? local.parsed_existing_en_instance_crn[7] : null } -data "ibm_en_destinations" "en_destinations" { +data "ibm_en_destinations" "en_sm_destinations" { # if existing SM instance CRN is passed (!= null), then never do data lookup for EN destinations - count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && local.enable_secrets_manager_cluster ? 1 : 0 + count = var.existing_secrets_manager_crn == null && local.enable_secrets_manager_cluster ? 1 : 0 instance_guid = local.existing_en_guid } # workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5533 resource "time_sleep" "wait_for_secrets_manager" { # if existing SM instance CRN is passed (!= null), then never work with EN - count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && local.enable_secrets_manager_cluster ? 1 : 0 + count = var.existing_secrets_manager_crn == null && local.enable_secrets_manager_cluster ? 1 : 0 depends_on = [module.secrets_manager] create_duration = "30s" } -resource "ibm_en_topic" "en_topic" { +resource "ibm_en_topic" "en_sm_topic" { # if existing SM instance CRN is passed (!= null), then never create EN topic - count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && local.enable_secrets_manager_cluster ? 1 : 0 + count = var.existing_secrets_manager_crn == null && local.enable_secrets_manager_cluster ? 1 : 0 depends_on = [time_sleep.wait_for_secrets_manager] instance_guid = local.existing_en_guid name = "Topic for Secrets Manager instance ${module.secrets_manager[0].secrets_manager_guid}" @@ -192,14 +402,14 @@ resource "ibm_en_topic" "en_topic" { } } -resource "ibm_en_subscription_email" "email_subscription" { +resource "ibm_en_subscription_email" "en_email_subscription" { # if existing SM instance CRN is passed (!= null), then never create EN email subscription - count = var.existing_secrets_manager_crn == null && local.enable_event_notifications && length(var.event_notifications_email_list) > 0 && local.enable_secrets_manager_cluster ? 1 : 0 + count = var.existing_secrets_manager_crn == null && length(var.event_notifications_email_list) > 0 && local.enable_secrets_manager_cluster ? 1 : 0 instance_guid = local.existing_en_guid name = "Email for Secrets Manager Subscription" description = "Subscription for Secret Manager Events" - destination_id = [for s in toset(data.ibm_en_destinations.en_destinations[count.index].destinations) : s.id if s.type == "smtp_ibm"][0] - topic_id = ibm_en_topic.en_topic[count.index].topic_id + destination_id = [for s in toset(data.ibm_en_destinations.en_sm_destinations[count.index].destinations) : s.id if s.type == "smtp_ibm"][0] + topic_id = ibm_en_topic.en_sm_topic[count.index].topic_id attributes { add_notification_payload = true reply_to_mail = var.event_notifications_reply_to_email @@ -218,7 +428,7 @@ locals { existing_secrets_manager_instance_guid = var.existing_secrets_manager_crn != null ? module.secrets_manager_crn_parser[0].service_instance : local.enable_secrets_manager_cluster ? module.secrets_manager[0].secrets_manager_guid : "" existing_secrets_manager_instance_region = var.existing_secrets_manager_crn != null ? module.secrets_manager_crn_parser[0].region : local.enable_secrets_manager_cluster ? module.secrets_manager[0].secrets_manager_region : "" - service_credential_secrets = [ + cos_service_credential_secrets = [ for service_credentials in var.service_cred : { secret_group_name = service_credentials.secret_group_name secret_group_description = service_credentials.secret_group_description @@ -267,7 +477,7 @@ module "cos" { ################################################################################# # create s2s auth policy with Secrets Manager -resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" { +resource "ibm_iam_authorization_policy" "cos_secrets_manager_key_manager" { count = !var.skip_secrets_manager_cos_iam_auth_policy && (var.existing_secrets_manager_crn != null || local.enable_secrets_manager_cluster) ? 1 : 0 source_service_name = "secrets-manager" source_resource_instance_id = local.existing_secrets_manager_instance_guid @@ -279,84 +489,20 @@ resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" { # workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 resource "time_sleep" "wait_for_cos_authorization_policy" { - count = length(local.service_credential_secrets) > 0 ? 1 : 0 - depends_on = [ibm_iam_authorization_policy.secrets_manager_key_manager] + count = length(local.cos_service_credential_secrets) > 0 ? 1 : 0 + depends_on = [ibm_iam_authorization_policy.cos_secrets_manager_key_manager] create_duration = "30s" } -module "secrets_manager_service_credentials" { - count = length(local.service_credential_secrets) > 0 ? 1 : 0 +module "cos_secrets_manager_service_credentials" { + count = length(local.cos_service_credential_secrets) > 0 ? 1 : 0 depends_on = [time_sleep.wait_for_cos_authorization_policy] source = "terraform-ibm-modules/secrets-manager/ibm//modules/secrets" version = "2.11.9" existing_sm_instance_guid = local.existing_secrets_manager_instance_guid existing_sm_instance_region = local.existing_secrets_manager_instance_region endpoint_type = var.secrets_manager_endpoint_type - secrets = local.service_credential_secrets -} - -################################################################################# -# Cloud Monitoring -################################################################################# - -module "existing_cloud_monitoring_crn_parser" { - count = var.existing_cloud_monitoring_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_cloud_monitoring_crn -} - -locals { - create_cloud_monitoring = var.existing_cloud_monitoring_crn == null - cloud_monitoring_crn = local.create_cloud_monitoring ? module.cloud_monitoring[0].crn : var.existing_cloud_monitoring_crn - cloud_monitoring_instance_name = "${local.prefix}${var.cloud_monitoring_instance_name}" - metrics_router_target_name = "${local.prefix}${var.metrics_routing_target_name}" - metrics_router_route_name = "${local.prefix}${var.metrics_routing_route_name}" - - default_metrics_router_route = var.enable_metrics_routing_to_cloud_monitoring ? [{ - name = local.metrics_router_route_name - rules = [{ - action = "send" - targets = [{ - id = module.metrics_routing[0].metrics_router_targets[local.metrics_router_target_name].id - }] - inclusion_filters = [] - }] - }] : [] -} - -module "cloud_monitoring" { - count = local.create_cloud_monitoring ? 1 : 0 - source = "terraform-ibm-modules/cloud-monitoring/ibm" - version = "1.11.0" - resource_group_id = var.resource_group_id - region = var.region - instance_name = local.cloud_monitoring_instance_name - plan = var.cloud_monitoring_plan - resource_tags = var.cloud_monitoring_resource_tags - access_tags = var.cloud_monitoring_access_tags - resource_keys = var.cloud_monitoring_resource_keys - disable_access_key_creation = var.disable_access_key_creation - service_endpoints = "public-and-private" - enable_platform_metrics = var.enable_platform_metrics - cbr_rules = var.cloud_monitoring_cbr_rules -} - -module "metrics_routing" { - count = var.enable_metrics_routing_to_cloud_monitoring ? 1 : 0 - source = "terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing" - version = "1.11.0" - metrics_router_targets = [ - { - destination_crn = local.cloud_monitoring_crn - target_name = local.metrics_router_target_name - target_region = var.region - skip_metrics_router_auth_policy = false - } - ] - - metrics_router_routes = length(var.metrics_router_routes) != 0 ? var.metrics_router_routes : local.default_metrics_router_route - metrics_router_settings = var.enable_primary_metadata_region ? { primary_metadata_region = var.region } : null + secrets = local.cos_service_credential_secrets } ################################################################################# @@ -409,7 +555,7 @@ module "cloud_logs" { module "cloud_logs_buckets" { source = "terraform-ibm-modules/cos/ibm//modules/buckets" - version = "10.5.7" + version = "10.5.8" bucket_configs = [ { bucket_name = local.data_bucket_name @@ -420,7 +566,7 @@ module "cloud_logs_buckets" { resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id add_bucket_name_suffix = var.append_random_bucket_name_suffix management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = var.cloud_logs_cos_buckets_class + storage_class = var.cos_buckets_class force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." activity_tracking = { read_data_events = true @@ -442,7 +588,7 @@ module "cloud_logs_buckets" { resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id add_bucket_name_suffix = var.append_random_bucket_name_suffix management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = var.cloud_logs_cos_buckets_class + storage_class = var.cos_buckets_class skip_iam_authorization_policy = true force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." activity_tracking = { @@ -571,6 +717,79 @@ module "at_cos_bucket" { ] } +######################################################################################################################## +# App Config +######################################################################################################################## +module "app_config" { + source = "terraform-ibm-modules/app-configuration/ibm" + version = "1.14.2" + resource_group_id = var.resource_group_id + region = var.region + app_config_name = "${local.prefix}${var.app_config_name}" + app_config_plan = var.app_config_plan + app_config_service_endpoints = var.app_config_service_endpoints + app_config_tags = var.app_config_tags + app_config_collections = var.app_config_collections + enable_config_aggregator = var.enable_config_aggregator + config_aggregator_trusted_profile_name = "${local.prefix}${var.config_aggregator_trusted_profile_name}" + config_aggregator_resource_collection_regions = var.config_aggregator_resource_collection_regions + config_aggregator_enterprise_id = var.config_aggregator_enterprise_id + config_aggregator_enterprise_trusted_profile_name = "${local.prefix}${var.config_aggregator_enterprise_trusted_profile_name}" + config_aggregator_enterprise_trusted_profile_template_name = "${local.prefix}${var.config_aggregator_enterprise_trusted_profile_template_name}" + config_aggregator_enterprise_account_group_ids_to_assign = var.config_aggregator_enterprise_account_group_ids_to_assign + config_aggregator_enterprise_account_ids_to_assign = var.config_aggregator_enterprise_account_ids_to_assign + cbr_rules = var.apprapp_cbr_rules + kms_encryption_enabled = var.kms_encryption_enabled_cluster + skip_app_config_kms_auth_policy = var.skip_app_config_kms_auth_policy + existing_kms_instance_crn = var.existing_kms_instance_crn != null ? var.existing_kms_instance_crn : module.kms[0].key_protect_crn + kms_endpoint_url = (var.kms_encryption_enabled_boot_volume && var.existing_boot_volume_kms_key_crn == null) || (var.kms_encryption_enabled_cluster && var.existing_cluster_kms_key_crn == null) ? var.kms_endpoint_type == "private" ? module.kms[0].kms_private_endpoint : module.kms[0].kms_public_endpoint : var.kms_endpoint_url + root_key_id = local.cluster_kms_key_id + enable_event_notifications = true + skip_app_config_event_notifications_auth_policy = var.skip_app_config_event_notifications_auth_policy + existing_event_notifications_instance_crn = local.eventnotification_crn + event_notifications_endpoint_url = var.existing_event_notifications_instance_crn != null ? var.event_notifications_endpoint_url : var.en_service_endpoints == "private" ? module.event_notifications[0].event_notifications_private_endpoint : module.event_notifications[0].event_notifications_public_endpoint + app_config_event_notifications_source_name = "${local.prefix}${var.app_config_event_notifications_source_name}" + event_notifications_integration_description = "The App Configuration integration to send notifications of events to users from the Event Notifications instance GUID ${local.existing_en_guid}" +} + +####################################################################################################################### +# App Configuration Event Notifications Configuration +####################################################################################################################### + +data "ibm_en_destinations" "en_apprapp_destinations" { + instance_guid = local.existing_en_guid +} + +resource "ibm_en_topic" "en_apprapp_topic" { + depends_on = [module.app_config] + instance_guid = local.existing_en_guid + name = "Topic for App Configuration instance ${module.app_config.app_config_guid}" + description = "Topic for App Configuration events routing" + sources { + id = module.app_config.app_config_crn + rules { + enabled = true + event_type_filter = "$.*" + } + } +} + +resource "ibm_en_subscription_email" "apprapp_email_subscription" { + count = length(var.event_notifications_email_list) > 0 ? 1 : 0 + instance_guid = local.existing_en_guid + name = "Email for App Configuration Subscription" + description = "Subscription for App Configuration Events" + destination_id = [for s in toset(data.ibm_en_destinations.en_apprapp_destinations[count.index].destinations) : s.id if s.type == "smtp_ibm"][0] + topic_id = ibm_en_topic.en_apprapp_topic[count.index].topic_id + attributes { + add_notification_payload = true + reply_to_mail = var.event_notifications_reply_to_email + reply_to_name = "App Configuration Event Notifications Bot" + from_name = var.event_notifications_from_email + invited = var.event_notifications_email_list + } +} + ################################################################################# # SCC Workload Protection ################################################################################# @@ -592,14 +811,12 @@ module "scc_wp" { cloud_monitoring_instance_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn access_tags = var.scc_workload_protection_access_tags scc_wp_service_plan = var.scc_workload_protection_service_plan - app_config_crn = var.app_config_crn + app_config_crn = module.app_config.app_config_crn scc_workload_protection_trusted_profile_name = "${local.prefix}${var.scc_workload_protection_trusted_profile_name}" cbr_rules = var.scc_wp_cbr_rules cspm_enabled = var.cspm_enabled } - - ############################################################################# # COS Bucket for VPC flow logs ############################################################################# @@ -617,7 +834,7 @@ locals { kms_key_crn = local.cluster_kms_key_crn skip_iam_authorization_policy = true management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = var.cloud_logs_cos_buckets_class + storage_class = var.cos_buckets_class resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id region_location = var.region force_delete = true diff --git a/modules/monolith/outputs.tf b/modules/monolith/outputs.tf index d43df4a98..b66be2b21 100644 --- a/modules/monolith/outputs.tf +++ b/modules/monolith/outputs.tf @@ -145,6 +145,21 @@ output "boot_volume_kms_account_id" { value = local.boot_volume_kms_account_id } +############################################################################## +# EN Outputs +############################################################################## + +output "en_crn" { + description = "Event Notification crn" + value = local.eventnotification_crn +} + +output "en_guid" { + description = "Event Notification guid" + value = local.eventnotification_guid +} + + ############################################################################## # SM Outputs ############################################################################## diff --git a/modules/monolith/variables.tf b/modules/monolith/variables.tf index 73ca707b8..4025f2ec9 100644 --- a/modules/monolith/variables.tf +++ b/modules/monolith/variables.tf @@ -253,6 +253,178 @@ variable "kms_cbr_rules" { } } +######################################################################################################################## +# Event Notifications +######################################################################################################################## + +variable "event_notifications_instance_name" { + type = string + description = "The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "event-notifications" +} + +variable "en_service_plan" { + type = string + description = "The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard`." + default = "standard" + validation { + condition = contains(["lite", "standard"], var.en_service_plan) + error_message = "The specified pricing plan is not available. The following plans are supported: `Lite`, `Standard`" + } +} + +variable "en_service_endpoints" { + type = string + description = "Specify whether you want to enable public, private, or both public and private service endpoints. Possible values: `public`, `private`, `public-and-private`." + default = "private" + validation { + condition = contains(["public", "private", "public-and-private"], var.en_service_endpoints) + error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`, `public-and-private`" + } +} + +variable "en_resource_tags" { + type = list(string) + description = "The list of tags to add to the Event Notifications instance." + default = [] +} + +variable "en_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Event Notifications instance created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." + default = [] + + validation { + condition = alltrue([ + for tag in var.en_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\". For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limit)." + } +} + +variable "en_service_credential_names" { + type = map(string) + description = "A mapping of names and associated roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/blob/main/solutions/fully-configurable/DA-types.md#service-credentials-)." + default = {} + + validation { + condition = alltrue([for name, role in var.en_service_credential_names : contains(["Manager", "Writer", "Reader", "Event Source Manager", "Channel Editor", "Event Notification Publisher", "Status Reporter", "Device Manager", "Email Sender", "Custom Email Status Reporter"], role)]) + error_message = "The specified service credential role is not valid. The following values are valid for service credential roles: 'Manager', 'Writer', 'Reader', 'Event Source Manager', 'Channel Editor', 'Event Notification Publisher', 'Status Reporter', 'Device Manager', 'Email Sender', 'Custom Email Status Reporter'" + } +} + +variable "kms_endpoint_url" { + type = string + description = "The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input." + default = null +} + +variable "skip_event_notifications_kms_auth_policy" { + type = bool + description = "Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." + default = false +} + +variable "enable_collecting_failed_events" { + type = bool + description = "Set to true to enable Cloud Object Storage integration. If enabled, you must also provide a Cloud Object Storage instance (for storing failed events) using the `existing_cos_instance_crn` variable. For more information, [see here](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-cfe-integrations)." + default = true +} + +variable "en_cos_bucket_name" { + type = string + description = "The name to use when creating the Object Storage bucket for the storage of failed delivery events. Bucket names are globally unique. If `add_bucket_name_suffix` is set to `true`, a random 4 character string is added to this name to help ensure that the bucket name is unique. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "base-event-notifications-bucket" +} + +variable "en_cos_bucket_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Cloud Object Storage bucket created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." + default = [] + + validation { + condition = alltrue([ + for tag in var.en_cos_bucket_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\". For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits)." + } +} + +variable "skip_event_notifications_secrets_manager_auth_policy" { + type = bool + default = false + description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing_secrets_manager_crn' is not passed." +} + +variable "en_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md)." + default = [] +} + +variable "en_service_credential_secrets" { # pragma: allowlist secret + type = list(object({ + secret_group_name = string # pragma: allowlist secret + secret_group_description = optional(string) # pragma: allowlist secret + existing_secret_group = optional(bool) # pragma: allowlist secret + service_credentials = list(object({ # pragma: allowlist secret + secret_name = string # pragma: allowlist secret + service_credentials_source_service_role_crn = string # pragma: allowlist secret + secret_labels = optional(list(string)) # pragma: allowlist secret + secret_auto_rotation = optional(bool) # pragma: allowlist secret + secret_auto_rotation_unit = optional(string) # pragma: allowlist secret + secret_auto_rotation_interval = optional(number) # pragma: allowlist secret + service_credentials_ttl = optional(string) # pragma: allowlist secret + service_credential_secret_description = optional(string) # pragma: allowlist secret + + })) + })) + default = [] + description = "Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets)." + + validation { + # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select Event Notifications and select the role + condition = alltrue([ + for group in var.en_service_credential_secrets : alltrue([ + # crn:v?:bluemix; two non-empty segments; three possibly empty segments; :serviceRole or role: non-empty segment + for credential in group.service_credentials : can(regex("^crn:v[0-9]:bluemix(:..*){2}(:.*){3}:(serviceRole|role):..*$", credential.service_credentials_source_service_role_crn)) + ]) + ]) + error_message = "Provided value of `service_credentials_source_service_role_crn` is not valid. Refer [this](https://cloud.ibm.com/iam/roles) for allowed role/values." + } + validation { + condition = length(var.en_service_credential_secrets) > 0 ? var.existing_secrets_manager_crn != null : true + error_message = "'existing_secrets_manager_crn' is required when adding service credentials with the 'service_credential_secrets' input." + } + +} + +variable "skip_event_notifications_cos_auth_policy" { + type = bool + description = "Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy." + default = false +} + +variable "event_notifications_endpoint_url" { + type = string + description = "The URL of the Event Notifications service endpoint to use for notifying configuration changes. For more information on the endpoint URL for Event Notifications, go to [Service endpoints](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-regions-endpoints#en-service-endpoints). It is required if `enable_event_notifications` is set to true." + default = null +} + ############################################################## # Secrets Manager ############################################################## @@ -783,12 +955,12 @@ variable "management_endpoint_type_for_buckets" { } } -variable "cloud_logs_cos_buckets_class" { +variable "cos_buckets_class" { type = string default = "smart" description = "The storage class of the newly provisioned IBM Cloud Logs Object Storage buckets. Possible values: `standard` or `smart`. Applies only if `existing_cloud_logs_crn` is not provided." validation { - condition = contains(["standard", "smart"], var.cloud_logs_cos_buckets_class) + condition = contains(["standard", "smart"], var.cos_buckets_class) error_message = "Allowed values for cos_bucket_class are \"standard\" or \"smart\"." } } @@ -1018,6 +1190,186 @@ variable "skip_activity_tracker_cos_auth_policy" { default = false } +######################################################################################################################## +# App Config variables +######################################################################################################################## + +variable "app_config_name" { + type = string + description = "Name for the App Configuration service instance." + default = "app-config" + nullable = false +} + +variable "app_config_plan" { + type = string + description = "Plan for the App Configuration service instance." + default = "enterprise" + nullable = false +} + +variable "app_config_service_endpoints" { + type = string + description = "Service Endpoints for the App Configuration service instance, valid endpoints are public or public-and-private." + default = "public-and-private" + nullable = false + + validation { + condition = contains(["public", "public-and-private"], var.app_config_service_endpoints) + error_message = "Value for service endpoints must be one of the following: \"public\" or \"public-and-private\"." + } +} + +variable "app_config_collections" { + description = "(Optional, list) A list of collections to be added to the App Configuration instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-app-configuration/tree/main/solutions/fully-configurable/DA-collections.md)." + type = list(object({ + name = string + collection_id = string + description = optional(string, null) + tags = optional(string, null) + })) + default = [] + + validation { + condition = ( + var.app_config_plan != "lite" || + length(var.app_config_collections) <= 1 + ) + error_message = "When using the 'lite' plan, you can define at most 1 App Configuration collection." + } +} + +variable "app_config_tags" { + type = list(string) + description = "Optional list of tags to be added to the App Config instance." + default = [] +} + +variable "enable_config_aggregator" { + description = "Set to true to enable configuration aggregator. By setting to true a trusted profile will be created with the required access to record configuration data from all resources across regions in your account. [Learn more](https://cloud.ibm.com/docs/app-configuration?topic=app-configuration-ac-configuration-aggregator)." + type = bool + default = true + nullable = false + + # Lite plan does not support enabling Config Aggregator as mention in doc : https://cloud.ibm.com/docs/app-configuration?topic=app-configuration-ac-configuration-aggregator + validation { + condition = !(var.enable_config_aggregator && var.app_config_plan == "lite") + error_message = "The configuration aggregator cannot be enabled when the app_config_plan is set to 'lite'. Please use a different plan (e.g., 'basic', 'standardv2', or 'enterprise')." + } +} + +variable "config_aggregator_trusted_profile_name" { + description = "The name to give the trusted profile that will be created if `enable_config_aggregator` is set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + type = string + default = "config-aggregator-trusted-profile" + + validation { + condition = var.enable_config_aggregator ? var.config_aggregator_trusted_profile_name != null : true + error_message = "'config_aggregator_trusted_profile_name' cannot be null if 'enable_config_aggregator' is true." + } +} + +variable "config_aggregator_resource_collection_regions" { + type = list(string) + description = "From which region do you want to collect configuration data? Only applies if `enable_config_aggregator` is set to true." + default = ["all"] +} + +variable "config_aggregator_enterprise_id" { + type = string + description = "If the account is an enterprise account, this value should be set to the enterprise ID (NOTE: This is different to the account ID). " + default = null + + validation { + condition = !var.enable_config_aggregator ? var.config_aggregator_enterprise_id == null : true + error_message = "A value can only be passed for 'config_aggregator_enterprise_id' if 'enable_config_aggregator' is true." + } +} + +variable "config_aggregator_enterprise_trusted_profile_name" { + description = "The name to give the enterprise viewer trusted profile with that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + type = string + default = "config-aggregator-enterprise-trusted-profile" + + validation { + condition = var.enable_config_aggregator && var.config_aggregator_enterprise_id != null ? var.config_aggregator_enterprise_trusted_profile_name != null : true + error_message = "'config_aggregator_enterprise_trusted_profile_name' cannot be null if 'enable_config_aggregator' is true and a value is being passed for 'config_aggregator_enterprise_id'." + } +} + +variable "config_aggregator_enterprise_trusted_profile_template_name" { + description = "The name to give the trusted profile template that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + type = string + default = "config-aggregator-trusted-profile-template" + + validation { + condition = var.enable_config_aggregator && var.config_aggregator_enterprise_id != null ? var.config_aggregator_enterprise_trusted_profile_template_name != null : true + error_message = "'config_aggregator_enterprise_trusted_profile_template_name' cannot be null if 'enable_config_aggregator' is true and a value is being passed for 'config_aggregator_enterprise_id'." + } +} + +variable "config_aggregator_enterprise_account_group_ids_to_assign" { + type = list(string) + default = ["all"] + description = "A list of enterprise account group IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all account groups. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`." + nullable = false + + validation { + condition = contains(var.config_aggregator_enterprise_account_group_ids_to_assign, "all") ? length(var.config_aggregator_enterprise_account_group_ids_to_assign) == 1 : true + error_message = "When specifying 'all' in the list, you cannot add any other values to the list" + } +} + +variable "config_aggregator_enterprise_account_ids_to_assign" { + type = list(string) + default = [] + description = "A list of enterprise account IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all accounts. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`." + nullable = false + + validation { + condition = contains(var.config_aggregator_enterprise_account_ids_to_assign, "all") ? length(var.config_aggregator_enterprise_account_ids_to_assign) == 1 : true + error_message = "When specifying 'all' in the list, you cannot add any other values to the list" + } +} + +variable "skip_app_config_kms_auth_policy" { + type = bool + description = "Set to true to skip the creation of an IAM authorization policy that permits App configuration instances in the resource group to read the encryption key from the KMS instance in the same account. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the other account." + default = false +} + +variable "skip_app_config_event_notifications_auth_policy" { + type = bool + description = "Set to true to skip the creation of an IAM authorization policy that permits App configuration instances to integrate with Event Notification in the same account." + default = false +} + +variable "app_config_event_notifications_source_name" { + type = string + description = "The name by which Event Notifications source will be created in the existing Event Notification instance." + default = "app-config-en" +} + +variable "apprapp_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md)." + default = [] +} + ####################################################################################################################### # SCC Workload Protection ####################################################################################################################### @@ -1083,27 +1435,10 @@ variable "scc_workload_protection_service_plan" { variable "cspm_enabled" { description = "Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service." type = bool - default = false + default = true nullable = false } -variable "app_config_crn" { - description = "The CRN of an existing App Config instance to use with the SCC Workload Protection instance. Required if `cspm_enabled` is true. NOTE: Ensure the App Config instance has configuration aggregator enabled." - type = string - default = null - validation { - condition = var.cspm_enabled ? var.app_config_crn != null : true - error_message = "Cannot be `null` if CSPM is enabled." - } - validation { - condition = anytrue([ - can(regex("^crn:(.*:){3}apprapp:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.app_config_crn)), - var.app_config_crn == null, - ]) - error_message = "The provided CRN is not a valid App Config CRN." - } -} - variable "scc_wp_cbr_rules" { type = list(object({ description = string diff --git a/tests/other_test.go b/tests/other_test.go index 8a26d9a1a..7e581746e 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -2,18 +2,11 @@ package test import ( - "fmt" - "os" - "strings" "testing" "github.com/IBM/go-sdk-core/v5/core" - "github.com/gruntwork-io/terratest/modules/files" - "github.com/gruntwork-io/terratest/modules/logger" - "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/cloudinfo" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testaddons" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" @@ -201,99 +194,45 @@ func TestFSCloudInSchematic(t *testing.T) { assert.Nil(t, err, "This should not have errored") } -func provisionPreReq(t *testing.T, p string) (string, *terraform.Options, error) { - // ------------------------------------------------------------------------------------ - // Provision existing resources first - // ------------------------------------------------------------------------------------ - prefix := fmt.Sprintf("%s-%s", p, strings.ToLower(random.UniqueId())) - realTerraformDir := "./existing-resources-monolith" - tempTerraformDir, _ := files.CopyTerraformFolderToTemp(realTerraformDir, prefix) - - // Verify ibmcloud_api_key variable is set - checkVariable := "TF_VAR_ibmcloud_api_key" - val, present := os.LookupEnv(checkVariable) - require.True(t, present, checkVariable+" environment variable not set") - require.NotEqual(t, "", val, checkVariable+" environment variable is empty") - - logger.Log(t, "Tempdir: ", tempTerraformDir) - existingTerraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ - TerraformDir: tempTerraformDir, - Vars: map[string]interface{}{ - "prefix": prefix, - }, - // Set Upgrade to true to ensure latest version of providers and modules are used by terratest. - // This is the same as setting the -upgrade=true flag with terraform. - Upgrade: true, - }) - - terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix) - _, existErr := terraform.InitAndApplyE(t, existingTerraformOptions) - if existErr != nil { - // assert.True(t, existErr == nil, "Init and Apply of temp existing resource failed") - return "", nil, existErr - } - return prefix, existingTerraformOptions, nil -} - func TestMonolithExample(t *testing.T) { t.Parallel() - prefix, existingTerraformOptions, existErr := provisionPreReq(t, "mon-ocp") - - if existErr != nil { - assert.True(t, existErr == nil, "Init and Apply of temp existing resource failed") - } else { - options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ - Testing: t, - Prefix: prefix, - TarIncludePatterns: []string{ - "*.tf", - monolithExampleDir + "/*.tf", - fullyConfigurableTerraformDir + "/scripts/*.*", - "/scripts/*.*", - "kubeconfig/*.*", - "modules/kube-audit/*.*", - "modules/worker-pool/*.*", - "modules/kube-audit/kubeconfig/*.*", - "modules/kube-audit/scripts/*.*", - "modules/kube-audit/helm-charts/kube-audit/*.*", - "modules/kube-audit/helm-charts/kube-audit/templates/*.*", - "modules/monolith/*.tf", - }, - TemplateFolder: monolithExampleDir, - Tags: []string{"monolith-base-ocp-test"}, - DeleteWorkspaceOnFail: false, - WaitJobCompleteMinutes: 240, - IgnoreAdds: testhelper.Exemptions{ - List: []string{"module.monolith_add_ons.module.scc_wp.restapi_object.cspm"}, - }, - IgnoreUpdates: testhelper.Exemptions{ - List: []string{"module.ocp_base.ibm_container_addons.addons"}, - }, - }) - options.TerraformVars = []testschematic.TestSchematicTerraformVar{ - {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, - {Name: "prefix", Value: prefix, DataType: "string"}, - {Name: "existing_resource_group_name", Value: terraform.Output(t, existingTerraformOptions, "resource_group_name"), DataType: "string"}, - {Name: "kms_encryption_enabled_cluster", Value: true, DataType: "bool"}, - {Name: "existing_event_notifications_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "event_notifications_instance_crn"), DataType: "string"}, - } - - err := options.RunSchematicTest() - assert.Nil(t, err, "This should not have errored") + options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ + Testing: t, + Prefix: "mon-ocp", + TarIncludePatterns: []string{ + "*.tf", + monolithExampleDir + "/*.tf", + fullyConfigurableTerraformDir + "/scripts/*.*", + "/scripts/*.*", + "kubeconfig/*.*", + "modules/kube-audit/*.*", + "modules/worker-pool/*.*", + "modules/kube-audit/kubeconfig/*.*", + "modules/kube-audit/scripts/*.*", + "modules/kube-audit/helm-charts/kube-audit/*.*", + "modules/kube-audit/helm-charts/kube-audit/templates/*.*", + "modules/monolith/*.tf", + }, + TemplateFolder: monolithExampleDir, + Tags: []string{"monolith-base-ocp-test"}, + DeleteWorkspaceOnFail: false, + WaitJobCompleteMinutes: 240, + IgnoreAdds: testhelper.Exemptions{ + List: []string{"module.monolith_add_ons.module.scc_wp.restapi_object.cspm"}, + }, + IgnoreUpdates: testhelper.Exemptions{ + List: []string{"module.ocp_base.ibm_container_addons.addons"}, + }, + }) + options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "prefix", Value: options.Prefix, DataType: "string"}, + {Name: "kms_encryption_enabled_cluster", Value: true, DataType: "bool"}, } - // Check if "DO_NOT_DESTROY_ON_FAILURE" is set - envVal, _ := os.LookupEnv("DO_NOT_DESTROY_ON_FAILURE") - // Destroy the temporary existing resources if required - if t.Failed() && strings.ToLower(envVal) == "true" { - fmt.Println("Terratest failed. Debug the test and delete resources manually.") - } else { - logger.Log(t, "START: Destroy (prereq resources)") - terraform.Destroy(t, existingTerraformOptions) - terraform.WorkspaceDelete(t, existingTerraformOptions, prefix) - logger.Log(t, "END: Destroy (prereq resources)") - } + err := options.RunSchematicTest() + assert.Nil(t, err, "This should not have errored") } func TestAddonPermutations(t *testing.T) { From 2e1a549d81e217b01c142246f5cdbdfb3d474aea Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Wed, 3 Dec 2025 12:14:28 +0530 Subject: [PATCH 04/15] remove existing resources --- tests/existing-resources-monolith/README.md | 1 - tests/existing-resources-monolith/main.tf | 24 -------------- tests/existing-resources-monolith/outputs.tf | 18 ----------- tests/existing-resources-monolith/provider.tf | 4 --- .../existing-resources-monolith/variables.tf | 32 ------------------- tests/existing-resources-monolith/version.tf | 9 ------ 6 files changed, 88 deletions(-) delete mode 100644 tests/existing-resources-monolith/README.md delete mode 100644 tests/existing-resources-monolith/main.tf delete mode 100644 tests/existing-resources-monolith/outputs.tf delete mode 100644 tests/existing-resources-monolith/provider.tf delete mode 100644 tests/existing-resources-monolith/variables.tf delete mode 100644 tests/existing-resources-monolith/version.tf diff --git a/tests/existing-resources-monolith/README.md b/tests/existing-resources-monolith/README.md deleted file mode 100644 index 705db15d6..000000000 --- a/tests/existing-resources-monolith/README.md +++ /dev/null @@ -1 +0,0 @@ -The terraform code in this directory is used by the existing resource test in tests/other_test.go diff --git a/tests/existing-resources-monolith/main.tf b/tests/existing-resources-monolith/main.tf deleted file mode 100644 index 3aa2b0abf..000000000 --- a/tests/existing-resources-monolith/main.tf +++ /dev/null @@ -1,24 +0,0 @@ -############################################################################# -# Provision Resource Group -############################################################################# -module "resource_group" { - source = "terraform-ibm-modules/resource-group/ibm" - version = "1.4.0" - resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null - existing_resource_group_name = var.resource_group -} - -############################################################################## -# Event Notification -############################################################################## - -module "event_notifications" { - source = "terraform-ibm-modules/event-notifications/ibm" - version = "2.7.0" - resource_group_id = module.resource_group.resource_group_id - name = "${var.prefix}-en" - tags = var.resource_tags - plan = "lite" - service_endpoints = "public-and-private" - region = var.region -} diff --git a/tests/existing-resources-monolith/outputs.tf b/tests/existing-resources-monolith/outputs.tf deleted file mode 100644 index 4deb3162c..000000000 --- a/tests/existing-resources-monolith/outputs.tf +++ /dev/null @@ -1,18 +0,0 @@ -######################################################################################################################## -# Outputs -######################################################################################################################## - -output "resource_group_id" { - description = "The id of the resource group where resources are created" - value = module.resource_group.resource_group_id -} - -output "resource_group_name" { - description = "The name of the resource group where resources are created" - value = module.resource_group.resource_group_name -} - -output "event_notifications_instance_crn" { - value = module.event_notifications.crn - description = "CRN of created event notification" -} diff --git a/tests/existing-resources-monolith/provider.tf b/tests/existing-resources-monolith/provider.tf deleted file mode 100644 index df45ef50b..000000000 --- a/tests/existing-resources-monolith/provider.tf +++ /dev/null @@ -1,4 +0,0 @@ -provider "ibm" { - ibmcloud_api_key = var.ibmcloud_api_key - region = var.region -} diff --git a/tests/existing-resources-monolith/variables.tf b/tests/existing-resources-monolith/variables.tf deleted file mode 100644 index 4b4575848..000000000 --- a/tests/existing-resources-monolith/variables.tf +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# Input variables -############################################################################## - -variable "ibmcloud_api_key" { - type = string - description = "The IBM Cloud API Key" - sensitive = true -} - -variable "region" { - type = string - description = "Region to provision all resources created by this example" - default = "us-south" -} - -variable "prefix" { - type = string - description = "Prefix to append to all resources created by this example" -} - -variable "resource_group" { - type = string - description = "The name of an existing resource group to provision resources in to. If not set a new resource group will be created using the prefix variable" - default = null -} - -variable "resource_tags" { - type = list(string) - description = "Optional list of tags to be added to created resources" - default = [] -} diff --git a/tests/existing-resources-monolith/version.tf b/tests/existing-resources-monolith/version.tf deleted file mode 100644 index 97b20938f..000000000 --- a/tests/existing-resources-monolith/version.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.3.0" - required_providers { - ibm = { - source = "ibm-cloud/ibm" - version = ">= 1.64.1" - } - } -} From 6e4dbb10bc480791c57615f8b1241cc7c1dec73b Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Mon, 8 Dec 2025 20:35:44 +0530 Subject: [PATCH 05/15] add monitoring and logs agent --- examples/monolith/README.md | 21 +++++---- examples/monolith/main.tf | 84 +++++++++++++++++++++++++++++++++++ modules/monolith/README.md | 4 +- modules/monolith/variables.tf | 54 +++++++++++++--------- tests/other_test.go | 13 +++++- 5 files changed, 142 insertions(+), 34 deletions(-) diff --git a/examples/monolith/README.md b/examples/monolith/README.md index dc3552bfa..4fbe46b56 100644 --- a/examples/monolith/README.md +++ b/examples/monolith/README.md @@ -6,18 +6,21 @@ The following resources are provisioned by this example: - A new resource group, if an existing one is not passed in. - A Key Protect instance with 2 root keys, one for cluster encryption, and one for worker boot volume encryption. - A VPC with subnets across 3 zones. -- A public gateway for all the three zones +- A public gateway for all the three zones. - A multi-zone (3 zone) KMS encrypted OCP VPC cluster, with worker pools in each zone. - An additional worker pool named workerpool is created and attached to the cluster using the worker-pool submodule. - Auto scaling enabled for the default worker pool. - Taints against the workers in zone-2 and zone-3. - Enable Kubernetes API server audit logs. -- A Cloud logs instance -- A Cloud monitoring instance -- An activity tracker event routing instance -- A secrets manager instance +- A Cloud logs instance. +- A Cloud monitoring instance. +- An activity tracker event routing instance. +- A secrets manager instance. - A COS instance along with 3 buckets for VPC flow logs, metrics/data bucket and activity tracker bucket. -- A SCC-WP instance -- A VPC instance -- An event notifications instance -- An app configuration service with aggregator enabled +- A SCC-WP instance. +- A VPC instance. +- An event notifications instance. +- An app configuration service with aggregator enabled. +- Monitoring agent. +- A Trusted Profile with Sender role to logs service. +- Logs agent. diff --git a/examples/monolith/main.tf b/examples/monolith/main.tf index d56c3c17c..425d386e2 100644 --- a/examples/monolith/main.tf +++ b/examples/monolith/main.tf @@ -216,3 +216,87 @@ module "kube_audit" { audit_webhook_listener_image = var.audit_webhook_listener_image audit_webhook_listener_image_tag_digest = var.audit_webhook_listener_image_tag_digest } + +############################################################################## +# Monitoring Agents +############################################################################## + +module "monitoring_agent" { + source = "terraform-ibm-modules/monitoring-agent/ibm" + version = "1.19.0" + cluster_id = module.ocp_base.cluster_id + cluster_resource_group_id = module.resource_group.resource_group_id + is_vpc_cluster = true + access_key = module.monolith_add_ons.cloud_monitoring_access_key + instance_region = var.region + metrics_filter = [{ exclude = "metricA.*" }, { include = "metricB.*" }] + container_filter = [{ type = "exclude", parameter = "kubernetes.namespace.name", name = "kube-system" }] + blacklisted_ports = [22, 2379, 3306] + agent_tags = { "environment" : "test", "custom" : "value" } + agent_mode = "troubleshooting" +} + +############################################################################## +# Logs Agent +############################################################################## + +locals { + logs_agent_namespace = "ibm-observe" + logs_agent_name = "logs-agent" +} + +module "trusted_profile" { + source = "terraform-ibm-modules/trusted-profile/ibm" + version = "3.2.0" + trusted_profile_name = "${var.prefix}-profile" + trusted_profile_description = "Logs agent Trusted Profile" + # As a `Sender`, you can send logs to your IBM Cloud Logs service instance - but not query or tail logs. This role is meant to be used by agent and routers sending logs. + trusted_profile_policies = [{ + roles = ["Sender"] + unique_identifier = "logs-agent" + resources = [{ + service = "logs" + }] + }] + # Set up fine-grained authorization for `logs-agent` running in ROKS cluster in `ibm-observe` namespace. + trusted_profile_links = [{ + cr_type = "ROKS_SA" + unique_identifier = "logs-agent-link" + links = [{ + crn = module.ocp_base.cluster_crn + namespace = local.logs_agent_namespace + name = local.logs_agent_name + }] + } + ] +} + +module "logs_agent" { + source = "terraform-ibm-modules/logs-agent/ibm" + version = "1.10.0" + cluster_id = module.ocp_base.cluster_id + cluster_resource_group_id = module.resource_group.resource_group_id + # Logs agent + logs_agent_trusted_profile_id = module.trusted_profile.trusted_profile.id + logs_agent_namespace = local.logs_agent_namespace + logs_agent_name = local.logs_agent_name + cloud_logs_ingress_endpoint = module.monolith_add_ons.cloud_logs_ingress_private_endpoint + cloud_logs_ingress_port = 3443 + # example of how to add additional metadata to the logs agent + logs_agent_additional_metadata = [{ + key = "cluster_id" + value = module.ocp_base.cluster_id + }] + logs_agent_resources = { + limits = { + cpu = "500m" + memory = "3Gi" + } + requests = { + cpu = "100m" + memory = "1Gi" + } + } + # example of how to add additional log source path + logs_agent_system_logs = ["/logs/*.log"] +} diff --git a/modules/monolith/README.md b/modules/monolith/README.md index f36e5da80..f5932e6b7 100644 --- a/modules/monolith/README.md +++ b/modules/monolith/README.md @@ -13,6 +13,8 @@ The primary goal of this module is to provision an OpenShift cluster on VPC and * `Activity Tracker and Event Routing`: Configure event routing for platform audit logs to a COS bucket or IBM Cloud Logs. * `Security & Compliance`: Optional integration with IBM Cloud Security and Compliance Center (SCC) Workload Protection. * `VPE Gateways`: Optional configuration of Virtual Private Endpoint (VPE) gateways for secure private connectivity to cloud services. +* `Event Notifications`: Optional provision and configuration of IBM Cloud Event Notifications for centralized event routing and management, with support for KMS encryption and failed event collection in COS. +* `App Configuration`: Optional provision and configuration of IBM Cloud App Configuration for centralized feature flag and property management, securely integrated with KMS and Event Notifications. ## Usage @@ -203,7 +205,7 @@ module "monolith_ocp_add_ons" { | [metrics\_router\_routes](#input\_metrics\_router\_routes) | Routes for IBM Cloud Metrics Routing. |
list(object({
name = string
rules = list(object({
action = string
targets = list(object({
id = string
}))
inclusion_filters = list(object({
operand = string
operator = string
values = list(string)
}))
}))
}))
| `[]` | no | | [metrics\_routing\_route\_name](#input\_metrics\_routing\_route\_name) | The name of the IBM Cloud Metrics Routing route for the default route that indicate what metrics are routed in a region and where to store them. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"metrics-routing-route"` | no | | [metrics\_routing\_target\_name](#input\_metrics\_routing\_target\_name) | The name of the IBM Cloud Metrics Routing target where metrics are collected. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"cloud-monitoring-target"` | no | -| [network\_acls](#input\_network\_acls) | The list of ACLs to create. Provide at least one rule for each ACL. |
list(
object({
name = string
add_ibm_cloud_internal_rules = optional(bool)
add_vpc_connectivity_rules = optional(bool)
prepend_ibm_rules = optional(bool)
rules = list(
object({
name = string
action = string
destination = string
direction = string
source = string
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
})
)
|
[
{
"add_ibm_cloud_internal_rules": true,
"add_vpc_connectivity_rules": true,
"name": "vpc-acl",
"prepend_ibm_rules": true,
"rules": [
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-443-inbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443,
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-80-inbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 80,
"port_min": 80,
"source_port_max": 80,
"source_port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-22-inbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 22,
"port_min": 22,
"source_port_max": 22,
"source_port_min": 22
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-443-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443,
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-80-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 80,
"port_min": 80,
"source_port_max": 80,
"source_port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-22-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 22,
"port_min": 22,
"source_port_max": 22,
"source_port_min": 22
}
}
]
}
]
| no | +| [network\_acls](#input\_network\_acls) | The list of ACLs to create. Provide at least one rule for each ACL. |
list(
object({
name = string
add_ibm_cloud_internal_rules = optional(bool)
add_vpc_connectivity_rules = optional(bool)
prepend_ibm_rules = optional(bool)
rules = list(
object({
name = string
action = string
destination = string
direction = string
source = string
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
})
)
|
[
{
"add_ibm_cloud_internal_rules": true,
"add_vpc_connectivity_rules": true,
"name": "vpc-acl",
"prepend_ibm_rules": true,
"rules": [
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-443-inbound-source",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-443-inbound-dest",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-80-inbound",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 80,
"source_port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-ingress-inbound",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 32767,
"source_port_min": 30000
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-443-outbound-source",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-443-outbound-dest",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-80-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 80,
"port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-ingress-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 32767,
"port_min": 30000
}
}
]
}
]
| no | | [prefix](#input\_prefix) | The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string. | `string` | n/a | yes | | [region](#input\_region) | The region to provision all resources in. | `string` | `"us-south"` | no | | [resource\_group\_id](#input\_resource\_group\_id) | The ID of an existing IBM Cloud resource group where the cluster is grouped. | `string` | n/a | yes | diff --git a/modules/monolith/variables.tf b/modules/monolith/variables.tf index 4025f2ec9..fb231cf43 100644 --- a/modules/monolith/variables.tf +++ b/modules/monolith/variables.tf @@ -1704,25 +1704,32 @@ variable "network_acls" { prepend_ibm_rules = true rules = [ { - name = "allow-all-443-inbound" + name = "allow-443-inbound-source" action = "allow" direction = "inbound" tcp = { - port_min = 443 - port_max = 443 source_port_min = 443 source_port_max = 443 } destination = "0.0.0.0/0" source = "0.0.0.0/0" }, + { + name = "allow-443-inbound-dest" + action = "allow" + direction = "inbound" + tcp = { + port_max = 443 + port_min = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, { name = "allow-all-80-inbound" action = "allow" direction = "inbound" tcp = { - port_min = 80 - port_max = 80 source_port_min = 80 source_port_max = 80 } @@ -1730,27 +1737,34 @@ variable "network_acls" { source = "0.0.0.0/0" }, { - name = "allow-all-22-inbound" + name = "allow-all-ingress-inbound" action = "allow" direction = "inbound" tcp = { - port_min = 22 - port_max = 22 - source_port_min = 22 - source_port_max = 22 + source_port_min = 30000 + source_port_max = 32767 } destination = "0.0.0.0/0" source = "0.0.0.0/0" }, { - name = "allow-all-443-outbound" + name = "allow-443-outbound-source" action = "allow" direction = "outbound" tcp = { source_port_min = 443 source_port_max = 443 - port_min = 443 - port_max = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-443-outbound-dest" + action = "allow" + direction = "outbound" + tcp = { + port_min = 443 + port_max = 443 } destination = "0.0.0.0/0" source = "0.0.0.0/0" @@ -1760,23 +1774,19 @@ variable "network_acls" { action = "allow" direction = "outbound" tcp = { - source_port_min = 80 - source_port_max = 80 - port_min = 80 - port_max = 80 + port_min = 80 + port_max = 80 } destination = "0.0.0.0/0" source = "0.0.0.0/0" }, { - name = "allow-all-22-outbound" + name = "allow-all-ingress-outbound" action = "allow" direction = "outbound" tcp = { - source_port_min = 22 - source_port_max = 22 - port_min = 22 - port_max = 22 + port_min = 30000 + port_max = 32767 } destination = "0.0.0.0/0" source = "0.0.0.0/0" diff --git a/tests/other_test.go b/tests/other_test.go index 7e581746e..c0ef925f0 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -219,10 +219,19 @@ func TestMonolithExample(t *testing.T) { DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 240, IgnoreAdds: testhelper.Exemptions{ - List: []string{"module.monolith_add_ons.module.scc_wp.restapi_object.cspm"}, + List: []string{ + "module.monolith_add_ons.module.scc_wp.restapi_object.cspm", + }, }, IgnoreUpdates: testhelper.Exemptions{ - List: []string{"module.ocp_base.ibm_container_addons.addons"}, + List: []string{ + "module.ocp_base.ibm_container_addons.addons", + "module.logs_agent.helm_release.logs_agent", + "module.monitoring_agent.helm_release.cloud_monitoring_agent", + // Have to ignore account settings as other tests may be updating them concurrently + // which can cause consistency test to fail if not ignored. + "module.monolith_add_ons.module.metrics_routing[0].ibm_metrics_router_settings.metrics_router_settings[0]", + }, }, }) options.TerraformVars = []testschematic.TestSchematicTerraformVar{ From 5119f27cd8d8040012a461817b591cc7849684d1 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Wed, 10 Dec 2025 18:02:28 +0530 Subject: [PATCH 06/15] PR changes --- examples/monolith/README.md | 21 +- examples/monolith/main.tf | 220 ++----------- examples/monolith/outputs.tf | 94 +++--- examples/monolith/provider.tf | 12 +- examples/monolith/variables.tf | 544 --------------------------------- modules/monolith/README.md | 82 ++++- modules/monolith/main.tf | 147 +++++++++ modules/monolith/outputs.tf | 44 ++- modules/monolith/variables.tf | 323 ++++++++++++++++++++ tests/other_test.go | 5 +- 10 files changed, 649 insertions(+), 843 deletions(-) diff --git a/examples/monolith/README.md b/examples/monolith/README.md index 4fbe46b56..5326bad34 100644 --- a/examples/monolith/README.md +++ b/examples/monolith/README.md @@ -2,25 +2,8 @@ A simple example that shows how to provision a multi zone OCP VPC cluster as well as all foundational infrastructure and supporting services required for a secure and compliant OpenShift (OCP) cluster deployment on IBM Cloud VPC. -The following resources are provisioned by this example: -- A new resource group, if an existing one is not passed in. -- A Key Protect instance with 2 root keys, one for cluster encryption, and one for worker boot volume encryption. -- A VPC with subnets across 3 zones. -- A public gateway for all the three zones. -- A multi-zone (3 zone) KMS encrypted OCP VPC cluster, with worker pools in each zone. -- An additional worker pool named workerpool is created and attached to the cluster using the worker-pool submodule. -- Auto scaling enabled for the default worker pool. -- Taints against the workers in zone-2 and zone-3. -- Enable Kubernetes API server audit logs. -- A Cloud logs instance. -- A Cloud monitoring instance. -- An activity tracker event routing instance. -- A secrets manager instance. -- A COS instance along with 3 buckets for VPC flow logs, metrics/data bucket and activity tracker bucket. -- A SCC-WP instance. -- A VPC instance. -- An event notifications instance. -- An app configuration service with aggregator enabled. +- Refer [here](../../modules/monolith/README.md) to check all the resources are provisioned by this example by calling the monolith module. +- A new resource group if an existing resource group is not passed. - Monitoring agent. - A Trusted Profile with Sender role to logs service. - Logs agent. diff --git a/examples/monolith/main.tf b/examples/monolith/main.tf index 425d386e2..3dd13f678 100644 --- a/examples/monolith/main.tf +++ b/examples/monolith/main.tf @@ -12,209 +12,43 @@ module "resource_group" { # Add-ons ######################################################################################################################## -module "monolith_add_ons" { +module "ocp_cluster_with_add_ons" { source = "../../modules/monolith" prefix = var.prefix region = var.region + ibmcloud_api_key = var.ibmcloud_api_key + provider_visibility = var.provider_visibility resource_group_id = module.resource_group.resource_group_id - kms_encryption_enabled_cluster = var.kms_encryption_enabled_cluster + kms_encryption_enabled_cluster = true existing_kms_instance_crn = var.existing_kms_instance_crn existing_cluster_kms_key_crn = var.existing_cluster_kms_key_crn - kms_endpoint_type = var.kms_endpoint_type - key_protect_allowed_network = var.key_protect_allowed_network - kms_encryption_enabled_boot_volume = var.kms_encryption_enabled_boot_volume + kms_endpoint_type = "private" + key_protect_allowed_network = "private-only" + kms_encryption_enabled_boot_volume = true existing_boot_volume_kms_key_crn = var.existing_boot_volume_kms_key_crn - kms_plan = var.kms_plan - en_service_plan = var.en_service_plan - en_service_endpoints = var.en_service_endpoints + kms_plan = "tiered-pricing" + en_service_plan = "standard" + en_service_endpoints = "public-and-private" existing_secrets_manager_crn = var.existing_secrets_manager_crn - secrets_manager_service_plan = var.secrets_manager_service_plan - secrets_manager_endpoint_type = var.secrets_manager_endpoint_type - secrets_manager_allowed_network = var.secrets_manager_allowed_network + secrets_manager_service_plan = "standard" + secrets_manager_endpoint_type = "private" existing_event_notifications_instance_crn = var.existing_event_notifications_instance_crn existing_cos_instance_crn = var.existing_cos_instance_crn - cos_instance_plan = var.cos_instance_plan - management_endpoint_type_for_buckets = var.management_endpoint_type_for_buckets + cos_instance_plan = "standard" + management_endpoint_type_for_buckets = "direct" existing_cloud_monitoring_crn = var.existing_cloud_monitoring_crn - cloud_monitoring_plan = var.cloud_monitoring_plan + cloud_monitoring_plan = "graduated-tier" existing_cloud_logs_crn = var.existing_cloud_logs_crn - scc_workload_protection_service_plan = var.scc_workload_protection_service_plan - enable_vpc_flow_logs = var.enable_vpc_flow_logs - app_config_plan = var.app_config_plan - app_config_service_endpoints = var.app_config_service_endpoints -} - -######################################################################################################################## -# OCP VPC cluster -######################################################################################################################## - -locals { - vpc_subnets = { - # The default behavior is to deploy the worker pool across all subnets within the VPC. - "default" = [ - for subnet in module.monolith_add_ons.subnet_zone_list : - { - id = subnet.id - zone = subnet.zone - cidr_block = subnet.cidr - } - ] - } - - worker_pools = concat([ - { - subnet_prefix = "default" - pool_name = "default" - machine_type = var.default_worker_pool_machine_type - workers_per_zone = var.default_worker_pool_workers_per_zone - resource_group_id = module.resource_group.resource_group_id - operating_system = var.default_worker_pool_operating_system - labels = var.default_worker_pool_labels - minSize = var.default_pool_minimum_number_of_nodes - maxSize = var.default_pool_maximum_number_of_nodes - enableAutoscaling = var.enable_autoscaling_for_default_pool - boot_volume_encryption_kms_config = { - crk = module.monolith_add_ons.boot_volume_kms_key_id - kms_instance_id = module.monolith_add_ons.boot_volume_existing_kms_guid - kms_account_id = module.monolith_add_ons.boot_volume_kms_account_id - } - additional_security_group_ids = var.additional_security_group_ids - } - ], [for pool in var.additional_worker_pools : merge(pool, { resource_group_id = module.resource_group.resource_group_id - boot_volume_encryption_kms_config = { - crk = module.monolith_add_ons.boot_volume_kms_key_id - kms_instance_id = module.monolith_add_ons.boot_volume_existing_kms_guid - kms_account_id = module.monolith_add_ons.boot_volume_kms_account_id - } }) if length(pool.vpc_subnets) > 0], - [for pool in var.additional_worker_pools : { - pool_name = pool.pool_name - machine_type = pool.machine_type - workers_per_zone = pool.workers_per_zone - resource_group_id = module.resource_group.resource_group_id - operating_system = pool.operating_system - labels = pool.labels - minSize = pool.minSize - secondary_storage = pool.secondary_storage - maxSize = pool.maxSize - enableAutoscaling = pool.enableAutoscaling - boot_volume_encryption_kms_config = { - crk = module.monolith_add_ons.boot_volume_kms_key_id - kms_instance_id = module.monolith_add_ons.boot_volume_existing_kms_guid - kms_account_id = module.monolith_add_ons.boot_volume_kms_account_id - } - additional_security_group_ids = pool.additional_security_group_ids - subnet_prefix = "default" - } if length(pool.vpc_subnets) == 0]) - - # Managing the ODF version accordingly, as it changes with each OCP version. - addons = lookup(var.addons, "openshift-data-foundation", null) != null ? lookup(var.addons["openshift-data-foundation"], "version", null) == null ? { for key, value in var.addons : - key => value != null ? { - version = lookup(value, "version", null) == null && key == "openshift-data-foundation" ? "${var.openshift_version}.0" : lookup(value, "version", null) - parameters_json = lookup(value, "parameters_json", null) - } : null } : var.addons : var.addons -} - -module "ocp_base" { - depends_on = [module.monolith_add_ons] - source = "../.." - resource_group_id = module.resource_group.resource_group_id - region = var.region - tags = var.cluster_resource_tags - cluster_name = "${var.prefix}-${var.cluster_name}" - force_delete_storage = true - use_existing_cos = true - existing_cos_id = module.monolith_add_ons.cos_instance_id - vpc_id = module.monolith_add_ons.vpc_id - vpc_subnets = local.vpc_subnets - ocp_version = var.openshift_version - worker_pools = local.worker_pools - access_tags = var.access_tags - ocp_entitlement = var.ocp_entitlement - additional_lb_security_group_ids = var.additional_lb_security_group_ids - additional_vpe_security_group_ids = var.additional_vpe_security_group_ids - addons = local.addons - allow_default_worker_pool_replacement = var.allow_default_worker_pool_replacement - attach_ibm_managed_security_group = var.attach_ibm_managed_security_group - cluster_config_endpoint_type = var.cluster_config_endpoint_type - cbr_rules = var.ocp_cbr_rules - cluster_ready_when = var.cluster_ready_when - custom_security_group_ids = var.custom_security_group_ids - disable_outbound_traffic_protection = var.allow_outbound_traffic - disable_public_endpoint = !var.allow_public_access_to_cluster_management - enable_ocp_console = var.enable_ocp_console - ignore_worker_pool_size_changes = var.ignore_worker_pool_size_changes - kms_config = module.monolith_add_ons.kms_config - manage_all_addons = var.manage_all_addons - number_of_lbs = var.number_of_lbs - pod_subnet_cidr = var.pod_subnet_cidr - service_subnet_cidr = var.service_subnet_cidr - verify_worker_network_readiness = var.verify_worker_network_readiness - worker_pools_taints = var.worker_pools_taints - enable_secrets_manager_integration = var.enable_secrets_manager_integration - existing_secrets_manager_instance_crn = module.monolith_add_ons.secrets_manager_crn - secrets_manager_secret_group_id = var.secrets_manager_secret_group_id != null ? var.secrets_manager_secret_group_id : (var.enable_secrets_manager_integration ? module.secret_group[0].secret_group_id : null) - skip_ocp_secrets_manager_iam_auth_policy = var.skip_ocp_secrets_manager_iam_auth_policy -} - -resource "terraform_data" "delete_secrets" { - depends_on = [module.monolith_add_ons] - count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 - input = { - secret_id = module.secret_group[0].secret_group_id - provider_visibility = var.provider_visibility - secrets_manager_instance_id = module.monolith_add_ons.secrets_manager_guid - secrets_manager_region = module.monolith_add_ons.secrets_manager_region - secrets_manager_endpoint = var.secrets_manager_endpoint_type - } - # api key in triggers_replace to avoid it to be printed out in clear text in terraform_data output - triggers_replace = { - api_key = var.ibmcloud_api_key - } - provisioner "local-exec" { - when = destroy - command = "${path.module}/../../solutions/fully-configurable/scripts/delete_secrets.sh ${self.input.secret_id} ${self.input.provider_visibility} ${self.input.secrets_manager_instance_id} ${self.input.secrets_manager_region} ${self.input.secrets_manager_endpoint}" - interpreter = ["/bin/bash", "-c"] - - environment = { - API_KEY = self.triggers_replace.api_key - } - } -} - -module "secret_group" { - count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 - source = "terraform-ibm-modules/secrets-manager-secret-group/ibm" - version = "1.3.15" - region = module.monolith_add_ons.secrets_manager_region - secrets_manager_guid = module.monolith_add_ons.secrets_manager_guid - secret_group_name = module.ocp_base.cluster_id - secret_group_description = "Secret group for storing ingress certificates for cluster ${var.cluster_name} with id: ${module.ocp_base.cluster_id}" - endpoint_type = var.secrets_manager_endpoint_type + scc_workload_protection_service_plan = "graduated-tier" + enable_vpc_flow_logs = true + app_config_plan = "enterprise" + app_config_service_endpoints = "public-and-private" } data "ibm_container_cluster_config" "cluster_config" { - count = var.enable_kube_audit ? 1 : 0 - cluster_name_id = module.ocp_base.cluster_id + cluster_name_id = module.ocp_cluster_with_add_ons.cluster_id + resource_group_id = module.resource_group.resource_group_id config_dir = "${path.module}/../../kubeconfig" - admin = true - resource_group_id = module.ocp_base.resource_group_id - endpoint_type = var.cluster_config_endpoint_type != "default" ? var.cluster_config_endpoint_type : null -} - -module "kube_audit" { - count = var.enable_kube_audit ? 1 : 0 - ibmcloud_api_key = var.ibmcloud_api_key - source = "../../modules/kube-audit" - cluster_id = module.ocp_base.cluster_id - cluster_resource_group_id = module.ocp_base.resource_group_id - region = module.ocp_base.region - use_private_endpoint = var.use_private_endpoint - cluster_config_endpoint_type = var.cluster_config_endpoint_type - audit_log_policy = var.audit_log_policy - audit_namespace = var.audit_namespace - audit_deployment_name = var.audit_deployment_name - audit_webhook_listener_image = var.audit_webhook_listener_image - audit_webhook_listener_image_tag_digest = var.audit_webhook_listener_image_tag_digest } ############################################################################## @@ -224,10 +58,10 @@ module "kube_audit" { module "monitoring_agent" { source = "terraform-ibm-modules/monitoring-agent/ibm" version = "1.19.0" - cluster_id = module.ocp_base.cluster_id + cluster_id = module.ocp_cluster_with_add_ons.cluster_id cluster_resource_group_id = module.resource_group.resource_group_id is_vpc_cluster = true - access_key = module.monolith_add_ons.cloud_monitoring_access_key + access_key = module.ocp_cluster_with_add_ons.cloud_monitoring_access_key instance_region = var.region metrics_filter = [{ exclude = "metricA.*" }, { include = "metricB.*" }] container_filter = [{ type = "exclude", parameter = "kubernetes.namespace.name", name = "kube-system" }] @@ -263,7 +97,7 @@ module "trusted_profile" { cr_type = "ROKS_SA" unique_identifier = "logs-agent-link" links = [{ - crn = module.ocp_base.cluster_crn + crn = module.ocp_cluster_with_add_ons.cluster_crn namespace = local.logs_agent_namespace name = local.logs_agent_name }] @@ -274,18 +108,18 @@ module "trusted_profile" { module "logs_agent" { source = "terraform-ibm-modules/logs-agent/ibm" version = "1.10.0" - cluster_id = module.ocp_base.cluster_id + cluster_id = module.ocp_cluster_with_add_ons.cluster_id cluster_resource_group_id = module.resource_group.resource_group_id # Logs agent logs_agent_trusted_profile_id = module.trusted_profile.trusted_profile.id logs_agent_namespace = local.logs_agent_namespace logs_agent_name = local.logs_agent_name - cloud_logs_ingress_endpoint = module.monolith_add_ons.cloud_logs_ingress_private_endpoint + cloud_logs_ingress_endpoint = module.ocp_cluster_with_add_ons.cloud_logs_ingress_private_endpoint cloud_logs_ingress_port = 3443 # example of how to add additional metadata to the logs agent logs_agent_additional_metadata = [{ key = "cluster_id" - value = module.ocp_base.cluster_id + value = module.ocp_cluster_with_add_ons.cluster_id }] logs_agent_resources = { limits = { diff --git a/examples/monolith/outputs.tf b/examples/monolith/outputs.tf index d18185c01..ebdf3b8c5 100644 --- a/examples/monolith/outputs.tf +++ b/examples/monolith/outputs.tf @@ -9,17 +9,17 @@ output "vpc_name" { description = "Name of the VPC created." - value = module.monolith_add_ons.vpc_name + value = module.ocp_cluster_with_add_ons.vpc_name } output "vpc_id" { description = "ID of the VPC created." - value = module.monolith_add_ons.vpc_id + value = module.ocp_cluster_with_add_ons.vpc_id } output "vpc_crn" { description = "CRN of the VPC created." - value = module.monolith_add_ons.vpc_crn + value = module.ocp_cluster_with_add_ons.vpc_crn } ############################################################################## @@ -28,7 +28,7 @@ output "vpc_crn" { output "public_gateways" { description = "Map of the public gateways by zone." - value = module.monolith_add_ons.public_gateways + value = module.ocp_cluster_with_add_ons.public_gateways } ############################################################################## @@ -37,7 +37,7 @@ output "public_gateways" { output "vpc_flow_logs" { description = "Details of the VPC flow logs collector." - value = module.monolith_add_ons.vpc_flow_logs + value = module.ocp_cluster_with_add_ons.vpc_flow_logs } ############################################################################## @@ -46,7 +46,7 @@ output "vpc_flow_logs" { output "network_acls" { description = "List of shortnames and IDs of network ACLs." - value = module.monolith_add_ons.network_acls + value = module.ocp_cluster_with_add_ons.network_acls } ############################################################################## @@ -55,27 +55,27 @@ output "network_acls" { output "subnet_ids" { description = "The IDs of the subnets." - value = module.monolith_add_ons.subnet_ids + value = module.ocp_cluster_with_add_ons.subnet_ids } output "private_path_subnet_id" { description = "The IDs of the subnets." - value = length(module.monolith_add_ons.subnet_ids) > 0 ? module.monolith_add_ons.subnet_ids[0] : null + value = length(module.ocp_cluster_with_add_ons.subnet_ids) > 0 ? module.ocp_cluster_with_add_ons.subnet_ids[0] : null } output "subnet_detail_list" { description = "A list of subnets containing names, CIDR blocks, and zones." - value = module.monolith_add_ons.subnet_detail_list + value = module.ocp_cluster_with_add_ons.subnet_detail_list } output "subnet_zone_list" { description = "A list of subnet IDs and subnet zones." - value = module.monolith_add_ons.subnet_zone_list + value = module.ocp_cluster_with_add_ons.subnet_zone_list } output "subnet_detail_map" { description = "A map of subnets containing IDs, CIDR blocks, and zones." - value = module.monolith_add_ons.subnet_detail_map + value = module.ocp_cluster_with_add_ons.subnet_detail_map } ############################################################################## @@ -84,12 +84,12 @@ output "subnet_detail_map" { output "vpn_gateways_name" { description = "List of names of VPN gateways." - value = module.monolith_add_ons.vpn_gateways_name + value = module.ocp_cluster_with_add_ons.vpn_gateways_name } output "vpn_gateways_data" { description = "Details of VPN gateways data." - value = module.monolith_add_ons.vpn_gateways_data + value = module.ocp_cluster_with_add_ons.vpn_gateways_data } ############################################################################## @@ -98,12 +98,12 @@ output "vpn_gateways_data" { output "vpe_ips" { description = "The reserved IPs for endpoint gateways." - value = module.monolith_add_ons.vpe_ips + value = module.ocp_cluster_with_add_ons.vpe_ips } output "vpe_crn" { description = "The CRN of the endpoint gateway." - value = module.monolith_add_ons.vpe_crn + value = module.ocp_cluster_with_add_ons.vpe_crn } ############################################################################## @@ -112,21 +112,21 @@ output "vpe_crn" { output "kms_guid" { description = "Key Protect instance GUID or the KMS instance GUID if existing_kms_instance_crn was set" - value = module.monolith_add_ons.kms_guid + value = module.ocp_cluster_with_add_ons.kms_guid } output "kms_account_id" { description = "The account ID of the KMS instance." - value = module.monolith_add_ons.kms_account_id + value = module.ocp_cluster_with_add_ons.kms_account_id } output "key_protect_id" { description = "Key Protect instance ID when an instance is created, otherwise null" - value = module.monolith_add_ons.key_protect_id + value = module.ocp_cluster_with_add_ons.key_protect_id } output "kms_instance_crn" { - value = module.monolith_add_ons.kms_instance_crn + value = module.ocp_cluster_with_add_ons.kms_instance_crn description = "The CRN of the Hyper Protect Crypto Service instance or Key Protect instance" } @@ -136,12 +136,12 @@ output "kms_instance_crn" { output "en_crn" { description = "Event Notification crn" - value = module.monolith_add_ons.en_crn + value = module.ocp_cluster_with_add_ons.en_crn } output "en_guid" { description = "Event Notification guid" - value = module.monolith_add_ons.en_guid + value = module.ocp_cluster_with_add_ons.en_guid } ############################################################################## @@ -150,16 +150,16 @@ output "en_guid" { output "secrets_manager_guid" { description = "GUID of Secrets Manager instance" - value = module.monolith_add_ons.secrets_manager_guid + value = module.ocp_cluster_with_add_ons.secrets_manager_guid } output "secrets_manager_crn" { - value = module.monolith_add_ons.secrets_manager_crn + value = module.ocp_cluster_with_add_ons.secrets_manager_crn description = "CRN of the Secrets Manager instance" } output "secrets_manager_region" { - value = module.monolith_add_ons.secrets_manager_region + value = module.ocp_cluster_with_add_ons.secrets_manager_region description = "Region of the Secrets Manager instance" } @@ -169,12 +169,12 @@ output "secrets_manager_region" { output "cos_instance_crn" { description = "COS instance crn" - value = module.monolith_add_ons.cos_instance_crn + value = module.ocp_cluster_with_add_ons.cos_instance_crn } output "cos_instance_guid" { description = "COS instance guid" - value = module.monolith_add_ons.cos_instance_guid + value = module.ocp_cluster_with_add_ons.cos_instance_guid } ############################################################################## @@ -182,26 +182,26 @@ output "cos_instance_guid" { ############################################################################## output "cloud_monitoring_crn" { - value = module.monolith_add_ons.cloud_monitoring_crn + value = module.ocp_cluster_with_add_ons.cloud_monitoring_crn description = "The id of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_name" { - value = module.monolith_add_ons.cloud_monitoring_name + value = module.ocp_cluster_with_add_ons.cloud_monitoring_name description = "The name of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_guid" { - value = module.monolith_add_ons.cloud_monitoring_guid + value = module.ocp_cluster_with_add_ons.cloud_monitoring_guid description = "The guid of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_access_key_name" { - value = module.monolith_add_ons.cloud_monitoring_access_key_name + value = module.ocp_cluster_with_add_ons.cloud_monitoring_access_key_name description = "The name of the IBM Cloud Monitoring access key for agents to use" } output "cloud_monitoring_access_key" { - value = module.monolith_add_ons.cloud_monitoring_access_key + value = module.ocp_cluster_with_add_ons.cloud_monitoring_access_key description = "The IBM Cloud Monitoring access key for agents to use" sensitive = true } @@ -211,28 +211,28 @@ output "cloud_monitoring_access_key" { ############################################################################## output "cloud_logs_crn" { - value = module.monolith_add_ons.cloud_logs_crn + value = module.ocp_cluster_with_add_ons.cloud_logs_crn description = "The id of the provisioned IBM Cloud Logs instance." } output "cloud_logs_guid" { - value = module.monolith_add_ons.cloud_logs_guid + value = module.ocp_cluster_with_add_ons.cloud_logs_guid description = "The guid of the provisioned IBM Cloud Logs instance." } output "cloud_logs_name" { - value = module.monolith_add_ons.cloud_logs_name + value = module.ocp_cluster_with_add_ons.cloud_logs_name description = "The name of the provisioned IBM Cloud Logs instance." } output "logs_bucket_crn" { description = "Logs Cloud Object Storage bucket CRN" - value = module.monolith_add_ons.logs_bucket_crn + value = module.ocp_cluster_with_add_ons.logs_bucket_crn } output "metrics_bucket_crn" { description = "Metrics Cloud Object Storage bucket CRN" - value = module.monolith_add_ons.metrics_bucket_crn + value = module.ocp_cluster_with_add_ons.metrics_bucket_crn } ############################################################################## @@ -240,17 +240,17 @@ output "metrics_bucket_crn" { ############################################################################## output "activity_tracker_cos_target_bucket_name" { - value = module.monolith_add_ons.activity_tracker_cos_target_bucket_name + value = module.ocp_cluster_with_add_ons.activity_tracker_cos_target_bucket_name description = "he name of the object storage bucket which is set as activity tracker event routing target to collect audit events." } output "activity_tracker_targets" { - value = module.monolith_add_ons.activity_tracker_targets + value = module.ocp_cluster_with_add_ons.activity_tracker_targets description = "The map of created Activity Tracker Event Routing targets" } output "activity_tracker_routes" { - value = module.monolith_add_ons.activity_tracker_routes + value = module.ocp_cluster_with_add_ons.activity_tracker_routes description = "The map of created Activity Tracker Event Routing routes" } @@ -260,17 +260,17 @@ output "activity_tracker_routes" { output "scc_workload_protection_id" { description = "SCC Workload Protection instance ID" - value = module.monolith_add_ons.scc_workload_protection_id + value = module.ocp_cluster_with_add_ons.scc_workload_protection_id } output "scc_workload_protection_crn" { description = "SCC Workload Protection instance CRN" - value = module.monolith_add_ons.scc_workload_protection_crn + value = module.ocp_cluster_with_add_ons.scc_workload_protection_crn } output "scc_workload_protection_name" { description = "SCC Workload Protection instance name" - value = module.monolith_add_ons.scc_workload_protection_name + value = module.ocp_cluster_with_add_ons.scc_workload_protection_name } ############################################################################## @@ -278,26 +278,26 @@ output "scc_workload_protection_name" { ############################################################################## output "cluster_name" { - value = module.ocp_base.cluster_name + value = module.ocp_cluster_with_add_ons.cluster_name description = "The name of the provisioned OpenShift cluster." } output "cluster_id" { - value = module.ocp_base.cluster_id + value = module.ocp_cluster_with_add_ons.cluster_id description = "The unique identifier assigned to the provisioned OpenShift cluster." } output "cluster_crn" { description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." - value = module.ocp_base.cluster_crn + value = module.ocp_cluster_with_add_ons.cluster_crn } output "workerpools" { description = "A list of worker pools associated with the provisioned cluster" - value = module.ocp_base.workerpools + value = module.ocp_cluster_with_add_ons.workerpools } output "ocp_version" { description = "The version of OpenShift running on the provisioned cluster." - value = module.ocp_base.ocp_version + value = module.ocp_cluster_with_add_ons.ocp_version } diff --git a/examples/monolith/provider.tf b/examples/monolith/provider.tf index df39925fa..af8cd0bf5 100644 --- a/examples/monolith/provider.tf +++ b/examples/monolith/provider.tf @@ -15,14 +15,14 @@ provider "restapi" { provider "helm" { kubernetes = { - host = data.ibm_container_cluster_config.cluster_config[0].host - token = data.ibm_container_cluster_config.cluster_config[0].token - cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config[0].ca_certificate + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token + cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config.ca_certificate } } provider "kubernetes" { - host = data.ibm_container_cluster_config.cluster_config[0].host - token = data.ibm_container_cluster_config.cluster_config[0].token - cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config[0].ca_certificate + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token + cluster_ca_certificate = data.ibm_container_cluster_config.cluster_config.ca_certificate } diff --git a/examples/monolith/variables.tf b/examples/monolith/variables.tf index 586793129..dd24ca953 100644 --- a/examples/monolith/variables.tf +++ b/examples/monolith/variables.tf @@ -46,23 +46,6 @@ variable "existing_event_notifications_instance_crn" { default = null } -variable "kms_encryption_enabled_cluster" { - description = "Set to true to enable KMS encryption for the cluster's Object Storage bucket. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn`." - type = bool - default = true - nullable = false - - validation { - condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_cluster : true - error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_cluster' to true." - } - - validation { - condition = var.existing_cluster_kms_key_crn != null ? var.kms_encryption_enabled_cluster : true - error_message = "If passing a value for 'existing_cluster_kms_key_crn', you should set 'kms_encryption_enabled_cluster' to true." - } -} - variable "existing_kms_instance_crn" { type = string default = null @@ -96,44 +79,6 @@ variable "existing_cluster_kms_key_crn" { } } -variable "kms_endpoint_type" { - type = string - description = "The endpoint for communicating with the KMS instance. Possible values: `public`, `private`. Applies only if `kms_encryption_enabled_cluster` is true" - default = "private" - nullable = false - validation { - condition = can(regex("^(public|private)$", var.kms_endpoint_type)) - error_message = "The kms_endpoint_type value must be 'public' or 'private'." - } -} - -variable "key_protect_allowed_network" { - type = string - description = "Allowed network types for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create_key_protect_instance' is set to `true`." - default = "private-only" - validation { - condition = can(regex("private-only|public-and-private", var.key_protect_allowed_network)) - error_message = "The `key_protect_allowed_network` value must be 'private-only' or 'public-and-private'." - } -} - -variable "kms_encryption_enabled_boot_volume" { - type = bool - description = "Set this to true to control the encryption keys used to encrypt the data that for the block storage volumes for VPC. If set to false, the data is encrypted by using randomly generated keys. For more info on encrypting block storage volumes, see https://cloud.ibm.com/docs/vpc?topic=vpc-creating-instances-byok" - default = true - nullable = false - - validation { - condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_boot_volume || var.kms_encryption_enabled_cluster : true - error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_boot_volume' to true." - } - - validation { - condition = var.existing_boot_volume_kms_key_crn != null ? var.kms_encryption_enabled_boot_volume : true - error_message = "If passing a value for 'existing_boot_volume_kms_key_crn', you should set 'kms_encryption_enabled_boot_volume' to true." - } -} - variable "existing_boot_volume_kms_key_crn" { type = string default = null @@ -148,68 +93,12 @@ variable "existing_boot_volume_kms_key_crn" { } } -variable "kms_plan" { - type = string - description = "Plan for the Key Protect instance. Supported values are 'tiered-pricing' and 'cross-region-resiliency'. Only used if 'create_key_protect_instance' is set to `true`." - default = "tiered-pricing" - # validation performed in terraform-ibm-key-protect module -} - -variable "en_service_plan" { - type = string - description = "The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard`." - default = "standard" - validation { - condition = contains(["lite", "standard"], var.en_service_plan) - error_message = "The specified pricing plan is not available. The following plans are supported: `Lite`, `Standard`" - } -} - -variable "en_service_endpoints" { - type = string - description = "Specify whether you want to enable public, private, or both public and private service endpoints. Possible values: `public`, `private`, `public-and-private`." - default = "public-and-private" - validation { - condition = contains(["public", "private", "public-and-private"], var.en_service_endpoints) - error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`, `public-and-private`" - } -} - variable "existing_secrets_manager_crn" { type = string description = "The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created." default = null } -variable "secrets_manager_service_plan" { - type = string - description = "The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. You can create only one Trial instance of Secrets Manager per account. Before you can create a new Trial instance, you must delete the existing Trial instance and its reclamation." - default = "standard" - validation { - condition = var.existing_secrets_manager_crn == null ? contains(["standard", "trial"], var.secrets_manager_service_plan) : true - error_message = "Only 'standard' and 'trial' are allowed values for 'secrets_manager_service_plan'. Applies only if not providing a value for the 'existing_secrets_manager_crn' input." - } -} - -variable "secrets_manager_allowed_network" { - type = string - description = "The types of service endpoints to set on the Secrets Manager instance. Possible values are `private-only` or `public-and-private`." - default = "private-only" - validation { - condition = contains(["private-only", "public-and-private"], var.secrets_manager_allowed_network) - error_message = "The specified allowed_network is not a valid selection!" - } -} - -variable "secrets_manager_endpoint_type" { - type = string - description = "The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications." - default = "private" - validation { - condition = contains(["public", "private"], var.secrets_manager_endpoint_type) - error_message = "The specified service endpoint is not a valid selection!" - } -} variable "existing_cos_instance_crn" { type = string @@ -217,447 +106,14 @@ variable "existing_cos_instance_crn" { default = null } -variable "cos_instance_plan" { - description = "The plan to use when Object Storage instances are created." - type = string - default = "standard" - validation { - condition = contains(["standard", "cos-one-rate-plan"], var.cos_instance_plan) - error_message = "The specified plan is not a valid selection!" - } -} - -variable "management_endpoint_type_for_buckets" { - description = "The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Possible values: `public`, `private`, `direct`. If you specify `private`, enable virtual routing and forwarding in your account, and the Terraform runtime must have access to the the IBM Cloud private network." - type = string - default = "direct" - validation { - condition = contains(["public", "private", "direct"], var.management_endpoint_type_for_buckets) - error_message = "The specified management_endpoint_type_for_buckets is not a valid selection!" - } -} - variable "existing_cloud_monitoring_crn" { type = string default = null description = "The CRN of an existing Cloud Monitoring instance. If not supplied, a new instance will be created." } -variable "cloud_monitoring_plan" { - type = string - description = "The IBM Cloud Monitoring plan to provision. Available values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." - default = "graduated-tier" - - validation { - condition = can(regex("^lite$|^graduated-tier$|^graduated-tier-sysdig-secure-plus-monitor$", var.cloud_monitoring_plan)) - error_message = "The plan value must be one of the following: lite, graduated-tier and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." - } - - validation { - condition = (var.cloud_monitoring_plan != "graduated-tier-sysdig-secure-plus-monitor") || var.region == "eu-fr2" - error_message = "When cloud_monitoring_plan is graduated-tier-sysdig-secure-plus-monitor region should be set to eu-fr2." - } -} - variable "existing_cloud_logs_crn" { type = string default = null description = "The CRN of an existing Cloud Logs instance. If not supplied, a new instance will be created." } - -variable "scc_workload_protection_service_plan" { - description = "The pricing plan for the Workload Protection instance service. Possible values: `free-trial`, `graduated-tier`." - type = string - default = "graduated-tier" - validation { - error_message = "Plan for Workload Protection instances can only be `free-trial` or `graduated-tier`." - condition = contains( - ["free-trial", "graduated-tier"], - var.scc_workload_protection_service_plan - ) - } -} - -variable "enable_vpc_flow_logs" { - description = "To enable VPC Flow logs, set this to true." - type = bool - nullable = false - default = true -} - -variable "app_config_plan" { - type = string - description = "Plan for the App Configuration service instance." - default = "enterprise" - nullable = false -} - -variable "app_config_service_endpoints" { - type = string - description = "Service Endpoints for the App Configuration service instance, valid endpoints are public or public-and-private." - default = "public" - nullable = false - - validation { - condition = contains(["public", "public-and-private"], var.app_config_service_endpoints) - error_message = "Value for service endpoints must be one of the following: \"public\" or \"public-and-private\"." - } -} - -######################################################################################################################## -# OCP VPC cluster -######################################################################################################################## - -variable "cluster_name" { - type = string - description = "The name of the new IBM Cloud OpenShift Cluster. If a `prefix` input variable is specified, it is added to this name in the `-value` format." - default = "openshift" -} - -variable "default_worker_pool_machine_type" { - type = string - description = "The machine type for worker nodes." - default = "bx2.4x16" - validation { - condition = length(regexall("^[a-z0-9]+(?:\\.[a-z0-9]+)*\\.\\d+x\\d+(?:\\.[a-z0-9]+)?$", var.default_worker_pool_machine_type)) > 0 - error_message = "Invalid value provided for the machine type." - } -} - -variable "default_worker_pool_workers_per_zone" { - type = number - description = "Number of worker nodes in each zone of the cluster." - default = 1 -} - -variable "default_worker_pool_operating_system" { - type = string - description = "The operating system installed on the worker nodes." - default = "RHCOS" -} - -variable "default_worker_pool_labels" { - type = map(string) - description = "A set of key-value labels assigned to the worker pool for identification." - default = {} -} - -variable "default_pool_minimum_number_of_nodes" { - type = number - description = "The minimum number of worker nodes allowed in the pool, ensuring at least one worker is always running." - default = 1 -} - -variable "default_pool_maximum_number_of_nodes" { - type = number - description = "The maximum number of worker nodes allowed in the pool, preventing the pool from exceeding three workers." - default = 3 -} - -variable "additional_security_group_ids" { - type = list(string) - description = "A list of security group IDs that are attached to the worker nodes for additional network security controls." - default = [] -} - -variable "additional_worker_pools" { - type = list(object({ - vpc_subnets = optional(list(object({ - id = string - zone = string - cidr_block = string - })), []) - pool_name = string - machine_type = string - workers_per_zone = number - operating_system = string - labels = optional(map(string)) - minSize = optional(number) - secondary_storage = optional(string) - maxSize = optional(number) - enableAutoscaling = optional(bool) - additional_security_group_ids = optional(list(string)) - })) - description = "List of additional worker pools." - default = [] -} - -variable "enable_autoscaling_for_default_pool" { - type = bool - description = "Set `true` to enable automatic scaling of worker based on workload demand." - default = false -} - -variable "addons" { - type = object({ - debug-tool = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - image-key-synchronizer = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - openshift-data-foundation = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - vpc-file-csi-driver = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - static-route = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - cluster-autoscaler = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - vpc-block-csi-driver = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - ibm-storage-operator = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - openshift-ai = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - }) - description = "Map of OCP cluster add-on versions to install (NOTE: The 'vpc-block-csi-driver' add-on is installed by default for VPC clusters and 'ibm-storage-operator' is installed by default in OCP 4.15 and later, however you can explicitly specify it here if you wish to choose a later version than the default one). [Check supported addons and versions here](https://cloud.ibm.com/docs/containers?topic=containers-supported-cluster-addon-versions)." - nullable = false - default = {} -} - -variable "openshift_version" { - type = string - description = "Version of the OpenShift cluster to provision." - default = "4.19" -} - -variable "cluster_resource_tags" { - type = list(string) - description = "Metadata labels describing this cluster deployment, i.e. test." - default = [] -} - -variable "access_tags" { - type = list(string) - description = "A list of access tags to apply to the resources created by the module." - default = [] -} - -variable "ocp_entitlement" { - type = string - description = "Value that is applied to the entitlements for OCP cluster provisioning." - default = null -} - -variable "additional_lb_security_group_ids" { - description = "List of additional security group IDs to add to the load balancers associated with the cluster. Ensure that the `number_of_lbs` variable is set to the number of Load Balancers associated with the cluster. This comes in addition to the IBM maintained security group." - type = list(string) - default = [] - nullable = false -} - -variable "number_of_lbs" { - description = "The total number of Load Balancers in the cluster that should be associated with the security groups defined in `additional_lb_security_group_ids` variable." - type = number - default = 1 - nullable = false -} - -variable "additional_vpe_security_group_ids" { - description = "Additional security groups to add to all existing load balancers. This comes in addition to the IBM maintained security group." - type = object({ - master = optional(list(string), []) - registry = optional(list(string), []) - api = optional(list(string), []) - }) - default = {} -} - -variable "allow_default_worker_pool_replacement" { - type = bool - description = "Set to true to allow the module to recreate a default worker pool. Only use in the case where you are getting an error indicating that the default worker pool cannot be replaced on apply. Once the default worker pool is handled separately, if you wish to make any change to the default worker pool which requires the re-creation of the default pool set this variable to true." - default = false - nullable = false -} - -variable "attach_ibm_managed_security_group" { - description = "Specify whether to attach the IBM-defined default security group (whose name is kube-) to all worker nodes. Only applicable if `custom_security_group_ids` is set." - type = bool - default = true -} - -variable "cluster_config_endpoint_type" { - description = "Specify which type of endpoint to use for cluster config access: 'default', 'private', 'vpe', 'link'. A 'default' value uses the default endpoint of the cluster." - type = string - default = "default" - nullable = false -} - -variable "verify_worker_network_readiness" { - type = bool - description = "By setting this to true, a script runs kubectl commands to verify that all worker nodes can communicate successfully with the master. If the runtime does not have access to the kube cluster to run kubectl commands, set this value to false." - default = true -} - -variable "cluster_ready_when" { - type = string - description = "The cluster is ready based on one of the following:: MasterNodeReady (not recommended), OneWorkerNodeReady, Normal, IngressReady." - default = "IngressReady" -} - -variable "custom_security_group_ids" { - description = "Security groups to add to all worker nodes. This comes in addition to the IBM maintained security group if `attach_ibm_managed_security_group` is set to true. If this variable is set, the default VPC security group is NOT assigned to the worker nodes." - type = list(string) - default = null -} - -variable "allow_outbound_traffic" { - type = bool - description = "Set to true to allow public outbound access from the cluster workers." - default = true -} - -variable "allow_public_access_to_cluster_management" { - type = bool - description = "Set to true to access the cluster through a public cloud service endpoint." - default = true -} - -variable "enable_ocp_console" { - description = "Flag to specify whether to enable or disable the OpenShift console. If set to `null` the module does not modify the current setting on the cluster. Keep in mind that when this input is set to `true` or `false` on a cluster with private only endpoint enabled, the runtime must be able to access the private endpoint." - type = bool - default = null - nullable = true -} - -variable "ignore_worker_pool_size_changes" { - type = bool - description = "Enable if using worker autoscaling. Stops Terraform managing worker count." - default = false -} - -variable "manage_all_addons" { - type = bool - default = false - nullable = false - description = "Instructs deployable architecture to manage all cluster addons, even if addons were installed outside of the module. If set to 'true' this deployable architecture destroys any addons that were installed by other sources." -} - -variable "pod_subnet_cidr" { - type = string - description = "Specify a custom subnet CIDR to provide private IP addresses for pods. The subnet must have a CIDR of at least `/23` or larger. Default value is `172.30.0.0/16` when the variable is set to `null`." - default = null -} - -variable "service_subnet_cidr" { - type = string - description = "Specify a custom subnet CIDR to provide private IP addresses for services. The subnet must be at least `/24` or larger. Default value is `172.21.0.0/16` when the variable is set to `null`." - default = null -} - -variable "worker_pools_taints" { - type = map(list(object({ key = string, value = string, effect = string }))) - description = "Optional, Map of lists containing node taints by node-pool name." - default = null -} - -variable "enable_secrets_manager_integration" { - type = bool - description = "Integrate with IBM Cloud Secrets Manager so you can centrally manage Ingress subdomain certificates and other secrets." - default = true - nullable = false -} - -variable "secrets_manager_secret_group_id" { - type = string - description = "Secret group ID where Ingress secrets are stored in the Secrets Manager instance. If 'enable_secrets_manager_integration' is set to true and 'secrets_manager_secret_group_id' is not provided, a new group will be created with the same name as cluster_id." - default = null -} - -variable "skip_ocp_secrets_manager_iam_auth_policy" { - type = bool - description = "To skip creating auth policy that allows OCP cluster 'Manager' role access in the existing Secrets Manager instance for managing ingress certificates." - default = false -} - -############################################################## -# Kube Audit -############################################################## - -variable "enable_kube_audit" { - type = bool - description = "Kubernetes audit logging provides a chronological record of operations performed on the cluster, including by users, administrators, and system components. It is useful for compliance, and security monitoring. Set true to enable kube audit by default." - default = true -} - -variable "audit_log_policy" { - type = string - description = "Specify the amount of information that is logged to the API server audit logs by choosing the audit log policy profile to use. Supported values are `default` and `WriteRequestBodies`." - default = "default" - - validation { - error_message = "Invalid Audit log policy Type! Valid values are 'default' or 'WriteRequestBodies'" - condition = contains(["default", "WriteRequestBodies"], var.audit_log_policy) - } -} - -variable "audit_namespace" { - type = string - description = "The name of the namespace where log collection service and a deployment will be created." - default = "ibm-kube-audit" -} - -variable "audit_deployment_name" { - type = string - description = "The name of log collection deployment and service." - default = "ibmcloud-kube-audit" -} - -variable "audit_webhook_listener_image" { - type = string - description = "The audit webhook listener image reference in the format of `[registry-url]/[namespace]/[image]`. This solution uses the `icr.io/ibm/ibmcloud-kube-audit-to-ibm-cloud-logs` image to forward logs to IBM Cloud Logs. This image is for demonstration purposes only. For a production solution, configure and maintain your own log forwarding image." - default = "icr.io/ibm/ibmcloud-kube-audit-to-ibm-cloud-logs" -} - -variable "audit_webhook_listener_image_tag_digest" { - type = string - description = "The tag or digest for the audit webhook listener image to deploy. If changing the value, ensure it is compatible with `audit_webhook_listener_image`." - default = "deaabcb8225e800385413ba420cf3f819d3b0671@sha256:acf123f4dba63534cbc104c6886abedff9d25a22a34ab7b549ede988ed6e7144" -} - -variable "use_private_endpoint" { - type = bool - description = "Set this to true to force all API calls to use the IBM Cloud private endpoints." - default = false -} - -variable "ocp_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - tags = optional(list(object({ - name = string - value = string - })), []) - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The list of context-based restriction rules to create." - default = [] -} diff --git a/modules/monolith/README.md b/modules/monolith/README.md index f5932e6b7..de61c9df7 100644 --- a/modules/monolith/README.md +++ b/modules/monolith/README.md @@ -1,20 +1,27 @@ -# Monolith module +# Landing zone for containerized applications with OpenShift -The module acts as a monolithic wrapper around a collection of smaller, official IBM Terraform modules, simplifying the deployment of a compliant, secure, and fully operational environment with a single configuration. This module integrates essential foundational services for security, monitoring, and logging for creating a fully configurable OCP cluster on an IBM Cloud Virtual Private Cloud. +This module provides a plain vanilla terraform implementation of the secure landing zone architecture- a production-grade Red Hat OpenShift platform on IBM Cloud VPC by providing a fully integrated ecosystem out of the box. Rather than just provisioning compute resources, it orchestrates the critical "operational glue" required for enterprise workloads—automatically wiring together Key Management, Secrets Manager, Cloud Logs, and Cloud Monitoring. This comprehensive approach reduces operational overhead and eliminates manual configuration errors, ensuring your environment is secure, observable, and ready. + +Secure, Compliant, and Scalable Designed to support a wide range of business needs—from rapid sandbox experimentation to highly regulated financial services deployments—the architecture is secure by design and fully configurable. It incorporates robust compliance features, such as SCC Workload Protection and automated audit logging, while allowing you to tailor specific integrations and worker pools to your requirements. This flexibility enables organizations to standardize on a single, reliable architectural pattern that streamlines security approvals and scales effortlessly with business demand. ### Components The primary goal of this module is to provision an OpenShift cluster on VPC and automatically configure the necessary supporting services, including: -* `VPC Infrastructure`: The base VPC, subnets, and network access controls (ACLs) for the OpenShift cluster. -* `Key Management (KMS)`: Optional provision and configuration of an IBM Key Protect or Hyper Protect Crypto Services (HPCS) instance for encrypting cluster and boot volumes. -* `Secrets Management`: Optional provision and configuration of an IBM Secrets Manager instance to securely store service credentials and other secrets. -* `Cloud Object Storage (COS)`: Optional provision and configuration of COS instances and buckets for flow logs, activity tracker, and other data storage needs. -* `Monitoring & Logging`: Optional provision and configuration of IBM Cloud Monitoring and IBM Cloud Logs instances for centralized observability. -* `Activity Tracker and Event Routing`: Configure event routing for platform audit logs to a COS bucket or IBM Cloud Logs. -* `Security & Compliance`: Optional integration with IBM Cloud Security and Compliance Center (SCC) Workload Protection. -* `VPE Gateways`: Optional configuration of Virtual Private Endpoint (VPE) gateways for secure private connectivity to cloud services. -* `Event Notifications`: Optional provision and configuration of IBM Cloud Event Notifications for centralized event routing and management, with support for KMS encryption and failed event collection in COS. -* `App Configuration`: Optional provision and configuration of IBM Cloud App Configuration for centralized feature flag and property management, securely integrated with KMS and Event Notifications. +* `VPC Infrastructure`: The base VPC, subnets, and network access controls (ACLs) for the OpenShift cluster. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/landing-zone-vpc/ibm/8.9.1) about the service module. +* `Key Management (KMS)`: Optional provision and configuration of an IBM Key Protect or Hyper Protect Crypto Services (HPCS) instance for encrypting cluster and boot volumes. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/kms-all-inclusive/ibm/5.4.5) about the service module. +* `Secrets Management`: Optional provision and configuration of an IBM Secrets Manager instance to securely store service credentials and other secrets. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/secrets-manager/ibm/2.11.9) about the service module. +* `Cloud Object Storage (COS)`: Optional provision and configuration of COS instances and buckets for flow logs, activity tracker, and other data storage needs. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/cos/ibm/10.5.9) about the service module. +* `Monitoring & Logging`: Optional provision and configuration of IBM Cloud Monitoring and IBM Cloud Logs instances for centralized observability. Learn more about the [Cloud Monitoring](https://registry.terraform.io/modules/terraform-ibm-modules/cloud-monitoring/ibm/1.11.0) and [Cloud Logs](https://registry.terraform.io/modules/terraform-ibm-modules/cloud-logs/ibm/1.10.0) service module. +* `Activity Tracker and Event Routing`: Configure event routing for platform audit logs to a COS bucket or IBM Cloud Logs. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/activity-tracker/ibm/1.5.0) about the service module. +* `Security & Compliance`: Optional integration with IBM Cloud Security and Compliance Center (SCC) Workload Protection. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/scc-workload-protection/ibm/1.16.4) about the service module. +* `VPE Gateways`: Optional configuration of Virtual Private Endpoint (VPE) gateways for secure private connectivity to cloud services. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/vpe-gateway/ibm/4.6.6) about the service module. +* `Event Notifications`: Optional provision and configuration of IBM Cloud Event Notifications for centralized event routing and management, with support for KMS encryption and failed event collection in COS. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/event-notifications/ibm/2.7.0) about the service module. +* `App Configuration`: Optional provision and configuration of IBM Cloud App Configuration for centralized feature flag and property management, securely integrated with KMS and Event Notifications. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/app-configuration/ibm/1.14.2) about the service module. +* `Context-Based Restrictions (CBR)`: Optional support for defining and attaching network access rules (CBR zones and rules) to all supported services (KMS, COS, Secrets Manager) to enforce zero-trust networking. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/cbr/ibm/1.34.0) about the service module. + +### Reference Architecture + +![Architecture Diagram](../../reference-architectures/deployable-architecture-ocp-cluster.svg) ## Usage @@ -25,9 +32,9 @@ module "monolith_ocp_add_ons" { prefix = "" region = "us-south" resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" - existing_event_notifications_instance_crn = var.existing_event_notifications_instance_crn } ``` +To run this module refer to the example [here](../../examples/monolith) ### Requirements @@ -62,7 +69,9 @@ module "monolith_ocp_add_ons" { | [existing\_sm\_crn\_parser](#module\_existing\_sm\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | | [kms](#module\_kms) | terraform-ibm-modules/kms-all-inclusive/ibm | 5.4.5 | | [metrics\_routing](#module\_metrics\_routing) | terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing | 1.11.0 | +| [ocp\_base](#module\_ocp\_base) | ../.. | n/a | | [scc\_wp](#module\_scc\_wp) | terraform-ibm-modules/scc-workload-protection/ibm | 1.16.4 | +| [secret\_group](#module\_secret\_group) | terraform-ibm-modules/secrets-manager-secret-group/ibm | 1.3.15 | | [secrets\_manager](#module\_secrets\_manager) | terraform-ibm-modules/secrets-manager/ibm | 2.11.9 | | [secrets\_manager\_crn\_parser](#module\_secrets\_manager\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | | [vpc](#module\_vpc) | terraform-ibm-modules/landing-zone-vpc/ibm | 8.9.1 | @@ -79,6 +88,7 @@ module "monolith_ocp_add_ons" { | [ibm_en_topic.en_sm_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | | [ibm_iam_authorization_policy.cos_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | | [ibm_iam_authorization_policy.en_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [terraform_data.delete_secrets](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | | [time_sleep.wait_for_cos_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | | [time_sleep.wait_for_en_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | | [time_sleep.wait_for_secrets_manager](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | @@ -89,13 +99,22 @@ module "monolith_ocp_add_ons" { | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [access\_tags](#input\_access\_tags) | A list of access tags to apply to the resources created by the module. | `list(string)` | `[]` | no | | [activity\_tracker\_cloud\_logs\_route\_name](#input\_activity\_tracker\_cloud\_logs\_route\_name) | Name of the cloud logs route for activity tracker event routing. | `string` | `null` | no | | [activity\_tracker\_cos\_bucket\_access\_tags](#input\_activity\_tracker\_cos\_bucket\_access\_tags) | A list of optional access tags to add to the IBM Cloud Activity Tracker Event Routing Cloud Object Storage bucket. | `list(string)` | `[]` | no | | [activity\_tracker\_cos\_bucket\_retention\_policy](#input\_activity\_tracker\_cos\_bucket\_retention\_policy) | The retention policy of the IBM Cloud Activity Tracker Event Routing COS target bucket. |
object({
default = optional(number, 90)
maximum = optional(number, 350)
minimum = optional(number, 90)
permanent = optional(bool, false)
})
| `null` | no | | [activity\_tracker\_cos\_route\_name](#input\_activity\_tracker\_cos\_route\_name) | Name of the cos route for activity tracker event routing. | `string` | `null` | no | | [activity\_tracker\_cos\_target\_bucket\_class](#input\_activity\_tracker\_cos\_target\_bucket\_class) | The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`. | `string` | `"smart"` | no | | [activity\_tracker\_cos\_target\_bucket\_name](#input\_activity\_tracker\_cos\_target\_bucket\_name) | The name of the Cloud Object Storage bucket to create for the Cloud Object Storage target to store AT events. Cloud Object Storage bucket names are globally unique. If the `add_bucket_name_suffix` variable is set to `true`, 4 random characters are added to this name to ensure that the name of the bucket is globally unique. If the prefix input variable is passed, the name of the instance is prefixed to the value in the `-value` format. | `string` | `"at-events-cos-bucket"` | no | +| [additional\_lb\_security\_group\_ids](#input\_additional\_lb\_security\_group\_ids) | List of additional security group IDs to add to the load balancers associated with the cluster. Ensure that the `number_of_lbs` variable is set to the number of Load Balancers associated with the cluster. This comes in addition to the IBM maintained security group. | `list(string)` | `[]` | no | +| [additional\_security\_group\_ids](#input\_additional\_security\_group\_ids) | A list of security group IDs that are attached to the worker nodes for additional network security controls. | `list(string)` | `[]` | no | +| [additional\_vpe\_security\_group\_ids](#input\_additional\_vpe\_security\_group\_ids) | Additional security groups to add to all existing load balancers. This comes in addition to the IBM maintained security group. |
object({
master = optional(list(string), [])
registry = optional(list(string), [])
api = optional(list(string), [])
})
| `{}` | no | +| [additional\_worker\_pools](#input\_additional\_worker\_pools) | List of additional worker pools. |
list(object({
vpc_subnets = optional(list(object({
id = string
zone = string
cidr_block = string
})), [])
pool_name = string
machine_type = string
workers_per_zone = number
operating_system = string
labels = optional(map(string))
minSize = optional(number)
secondary_storage = optional(string)
maxSize = optional(number)
enableAutoscaling = optional(bool)
additional_security_group_ids = optional(list(string))
}))
| `[]` | no | +| [addons](#input\_addons) | Map of OCP cluster add-on versions to install (NOTE: The 'vpc-block-csi-driver' add-on is installed by default for VPC clusters and 'ibm-storage-operator' is installed by default in OCP 4.15 and later, however you can explicitly specify it here if you wish to choose a later version than the default one). [Check supported addons and versions here](https://cloud.ibm.com/docs/containers?topic=containers-supported-cluster-addon-versions). |
object({
debug-tool = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
image-key-synchronizer = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
openshift-data-foundation = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
vpc-file-csi-driver = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
static-route = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
cluster-autoscaler = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
vpc-block-csi-driver = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
ibm-storage-operator = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
openshift-ai = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
})
| `{}` | no | | [address\_prefixes](#input\_address\_prefixes) | The IP range that will be defined for the VPC for a certain location. Use only with manual address prefixes. |
object({
zone-1 = optional(list(string))
zone-2 = optional(list(string))
zone-3 = optional(list(string))
})
|
{
"zone-1": null,
"zone-2": null,
"zone-3": null
}
| no | +| [allow\_default\_worker\_pool\_replacement](#input\_allow\_default\_worker\_pool\_replacement) | Set to true to allow the module to recreate a default worker pool. Only use in the case where you are getting an error indicating that the default worker pool cannot be replaced on apply. Once the default worker pool is handled separately, if you wish to make any change to the default worker pool which requires the re-creation of the default pool set this variable to true. | `bool` | `false` | no | +| [allow\_outbound\_traffic](#input\_allow\_outbound\_traffic) | Set to true to allow public outbound access from the cluster workers. | `bool` | `true` | no | +| [allow\_public\_access\_to\_cluster\_management](#input\_allow\_public\_access\_to\_cluster\_management) | Set to true to access the cluster through a public cloud service endpoint. | `bool` | `true` | no | | [app\_config\_collections](#input\_app\_config\_collections) | (Optional, list) A list of collections to be added to the App Configuration instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-app-configuration/tree/main/solutions/fully-configurable/DA-collections.md). |
list(object({
name = string
collection_id = string
description = optional(string, null)
tags = optional(string, null)
}))
| `[]` | no | | [app\_config\_event\_notifications\_source\_name](#input\_app\_config\_event\_notifications\_source\_name) | The name by which Event Notifications source will be created in the existing Event Notification instance. | `string` | `"app-config-en"` | no | | [app\_config\_name](#input\_app\_config\_name) | Name for the App Configuration service instance. | `string` | `"app-config"` | no | @@ -104,6 +123,7 @@ module "monolith_ocp_add_ons" { | [app\_config\_tags](#input\_app\_config\_tags) | Optional list of tags to be added to the App Config instance. | `list(string)` | `[]` | no | | [append\_random\_bucket\_name\_suffix](#input\_append\_random\_bucket\_name\_suffix) | Append random generated suffix (4 characters long) to the newly provisioned IBM Cloud Logs Object Storage bucket names. | `bool` | `true` | no | | [apprapp\_cbr\_rules](#input\_apprapp\_cbr\_rules) | The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md). |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [attach\_ibm\_managed\_security\_group](#input\_attach\_ibm\_managed\_security\_group) | Specify whether to attach the IBM-defined default security group (whose name is kube-) to all worker nodes. Only applicable if `custom_security_group_ids` is set. | `bool` | `true` | no | | [boot\_volume\_kms\_key\_name](#input\_boot\_volume\_kms\_key\_name) | The name for the key created for the block storage volumes. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key"` | no | | [boot\_volume\_kms\_key\_ring\_name](#input\_boot\_volume\_kms\_key\_ring\_name) | The name for the key ring created for the block storage volumes key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key-ring"` | no | | [clean\_default\_security\_group\_acl](#input\_clean\_default\_security\_group\_acl) | Remove all rules from the default VPC security group and VPC ACL (less permissive). | `bool` | `true` | no | @@ -121,8 +141,12 @@ module "monolith_ocp_add_ons" { | [cloud\_monitoring\_plan](#input\_cloud\_monitoring\_plan) | The IBM Cloud Monitoring plan to provision. Available values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only). | `string` | `"graduated-tier"` | no | | [cloud\_monitoring\_resource\_keys](#input\_cloud\_monitoring\_resource\_keys) | A list of maps representing resource keys to create for the IBM Cloud Monitoring instance. Each entry defines a single resource key. Use this list to manage custom keys and handle key rotation. |
list(object({
name = string
generate_hmac_credentials = optional(bool, false) # pragma: allowlist secret
role = optional(string, "Manager")
service_id_crn = optional(string, null)
}))
| `[]` | no | | [cloud\_monitoring\_resource\_tags](#input\_cloud\_monitoring\_resource\_tags) | Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings). | `list(string)` | `[]` | no | +| [cluster\_config\_endpoint\_type](#input\_cluster\_config\_endpoint\_type) | Specify which type of endpoint to use for cluster config access: 'default', 'private', 'vpe', 'link'. A 'default' value uses the default endpoint of the cluster. | `string` | `"default"` | no | | [cluster\_kms\_key\_name](#input\_cluster\_kms\_key\_name) | The name of the key to be created for the cluster's Object Storage bucket encryption. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key"` | no | | [cluster\_kms\_key\_ring\_name](#input\_cluster\_kms\_key\_ring\_name) | The name of the key ring to be created for the cluster's Object Storage bucket encryption key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key-ring"` | no | +| [cluster\_name](#input\_cluster\_name) | The name of the new IBM Cloud OpenShift Cluster. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"openshift"` | no | +| [cluster\_ready\_when](#input\_cluster\_ready\_when) | The cluster is ready based on one of the following:: MasterNodeReady (not recommended), OneWorkerNodeReady, Normal, IngressReady. | `string` | `"IngressReady"` | no | +| [cluster\_resource\_tags](#input\_cluster\_resource\_tags) | Metadata labels describing this cluster deployment, i.e. test. | `list(string)` | `[]` | no | | [config\_aggregator\_enterprise\_account\_group\_ids\_to\_assign](#input\_config\_aggregator\_enterprise\_account\_group\_ids\_to\_assign) | A list of enterprise account group IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all account groups. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`. | `list(string)` |
[
"all"
]
| no | | [config\_aggregator\_enterprise\_account\_ids\_to\_assign](#input\_config\_aggregator\_enterprise\_account\_ids\_to\_assign) | A list of enterprise account IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all accounts. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`. | `list(string)` | `[]` | no | | [config\_aggregator\_enterprise\_id](#input\_config\_aggregator\_enterprise\_id) | If the account is an enterprise account, this value should be set to the enterprise ID (NOTE: This is different to the account ID). | `string` | `null` | no | @@ -138,9 +162,16 @@ module "monolith_ocp_add_ons" { | [cos\_instance\_resource\_tags](#input\_cos\_instance\_resource\_tags) | A list of resource tags to apply to the Object Storage instance. | `list(string)` | `[]` | no | | [cos\_target\_name](#input\_cos\_target\_name) | Name of the cos target for activity tracker event routing. | `string` | `null` | no | | [cspm\_enabled](#input\_cspm\_enabled) | Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service. | `bool` | `true` | no | +| [custom\_security\_group\_ids](#input\_custom\_security\_group\_ids) | Security groups to add to all worker nodes. This comes in addition to the IBM maintained security group if `attach_ibm_managed_security_group` is set to true. If this variable is set, the default VPC security group is NOT assigned to the worker nodes. | `list(string)` | `null` | no | | [default\_network\_acl\_name](#input\_default\_network\_acl\_name) | Name of the Default ACL. If null, a name will be automatically generated. | `string` | `null` | no | +| [default\_pool\_maximum\_number\_of\_nodes](#input\_default\_pool\_maximum\_number\_of\_nodes) | The maximum number of worker nodes allowed in the pool, preventing the pool from exceeding three workers. | `number` | `3` | no | +| [default\_pool\_minimum\_number\_of\_nodes](#input\_default\_pool\_minimum\_number\_of\_nodes) | The minimum number of worker nodes allowed in the pool, ensuring at least one worker is always running. | `number` | `1` | no | | [default\_routing\_table\_name](#input\_default\_routing\_table\_name) | Name of the Default Routing Table. If null, a name will be automatically generated. | `string` | `null` | no | | [default\_security\_group\_name](#input\_default\_security\_group\_name) | Name of the Default Security Group. If null, a name will be automatically generated. | `string` | `null` | no | +| [default\_worker\_pool\_labels](#input\_default\_worker\_pool\_labels) | A set of key-value labels assigned to the worker pool for identification. | `map(string)` | `{}` | no | +| [default\_worker\_pool\_machine\_type](#input\_default\_worker\_pool\_machine\_type) | The machine type for worker nodes. | `string` | `"bx2.4x16"` | no | +| [default\_worker\_pool\_operating\_system](#input\_default\_worker\_pool\_operating\_system) | The operating system installed on the worker nodes. | `string` | `"RHCOS"` | no | +| [default\_worker\_pool\_workers\_per\_zone](#input\_default\_worker\_pool\_workers\_per\_zone) | Number of worker nodes in each zone of the cluster. | `number` | `1` | no | | [disable\_access\_key\_creation](#input\_disable\_access\_key\_creation) | When set to true, disables the creation of a default manager access key which is required by agents to ingest metrics. | `bool` | `false` | no | | [dual\_auth\_delete\_enabled](#input\_dual\_auth\_delete\_enabled) | If set to `true`, a dual authorization policy is enabled on the Key Protect instance. After the dual authorization policy is set on the instance, it cannot be reverted. An instance with dual authorization policy enabled cannot be destroyed by using Terraform. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `false` | no | | [en\_access\_tags](#input\_en\_access\_tags) | A list of access tags to apply to the Event Notifications instance created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial). | `list(string)` | `[]` | no | @@ -154,12 +185,15 @@ module "monolith_ocp_add_ons" { | [en\_service\_plan](#input\_en\_service\_plan) | The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard`. | `string` | `"standard"` | no | | [enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs](#input\_enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs) | When set to `true`, you must provide a value for `existing_cloud_logs_crn` to enable event routing from Activity Tracker to a Cloud Logs instance. | `bool` | `true` | no | | [enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket](#input\_enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket) | When set to `true`, you must provide a value for `existing_cos_instance_crn` to enable event routing from Activity Tracker to a Object Storage bucket. | `bool` | `true` | no | +| [enable\_autoscaling\_for\_default\_pool](#input\_enable\_autoscaling\_for\_default\_pool) | Set `true` to enable automatic scaling of worker based on workload demand. | `bool` | `false` | no | | [enable\_collecting\_failed\_events](#input\_enable\_collecting\_failed\_events) | Set to true to enable Cloud Object Storage integration. If enabled, you must also provide a Cloud Object Storage instance (for storing failed events) using the `existing_cos_instance_crn` variable. For more information, [see here](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-cfe-integrations). | `bool` | `true` | no | | [enable\_config\_aggregator](#input\_enable\_config\_aggregator) | Set to true to enable configuration aggregator. By setting to true a trusted profile will be created with the required access to record configuration data from all resources across regions in your account. [Learn more](https://cloud.ibm.com/docs/app-configuration?topic=app-configuration-ac-configuration-aggregator). | `bool` | `true` | no | | [enable\_metrics](#input\_enable\_metrics) | Set to `true` to enable metrics on the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. In order to view metrics, you need an IBM Cloud Monitoring (Sysdig) instance that is located in the same region as the Key Protect instance. After you provision a Monitoring instance, enable platform metrics to monitor your Key Protect instance. | `bool` | `true` | no | | [enable\_metrics\_routing\_to\_cloud\_monitoring](#input\_enable\_metrics\_routing\_to\_cloud\_monitoring) | Whether to enable metrics routing from IBM Cloud Metric Routing to Cloud Monitoring. | `bool` | `true` | no | +| [enable\_ocp\_console](#input\_enable\_ocp\_console) | Flag to specify whether to enable or disable the OpenShift console. If set to `null` the module does not modify the current setting on the cluster. Keep in mind that when this input is set to `true` or `false` on a cluster with private only endpoint enabled, the runtime must be able to access the private endpoint. | `bool` | `null` | no | | [enable\_platform\_metrics](#input\_enable\_platform\_metrics) | When set to `true`, the IBM Cloud Monitoring instance collects the platform metrics. | `bool` | `false` | no | | [enable\_primary\_metadata\_region](#input\_enable\_primary\_metadata\_region) | When set to `true`, sets `primary_metadata_region` to `region`, storing Metrics Router metadata in that region. When `false`, no region is set and the default global region is used. For new accounts, creating targets and routes will fail until primary\_metadata\_region is set, so it is recommended to default enable\_primary\_metadata\_region to true. | `bool` | `true` | no | +| [enable\_secrets\_manager\_integration](#input\_enable\_secrets\_manager\_integration) | Integrate with IBM Cloud Secrets Manager so you can centrally manage Ingress subdomain certificates and other secrets. | `bool` | `true` | no | | [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | To enable VPC Flow logs, set this to true. | `bool` | `false` | no | | [event\_notifications\_email\_list](#input\_event\_notifications\_email\_list) | The list of email address to target out when Secrets Manager triggers an event | `list(string)` | `[]` | no | | [event\_notifications\_endpoint\_url](#input\_event\_notifications\_endpoint\_url) | The URL of the Event Notifications service endpoint to use for notifying configuration changes. For more information on the endpoint URL for Event Notifications, go to [Service endpoints](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-regions-endpoints#en-service-endpoints). It is required if `enable_event_notifications` is set to true. | `string` | `null` | no | @@ -187,6 +221,8 @@ module "monolith_ocp_add_ons" { | [flow\_logs\_cos\_bucket\_maximum\_retention\_days](#input\_flow\_logs\_cos\_bucket\_maximum\_retention\_days) | The maximum number of days that an object can be kept unmodified in the flow logs cloud object storage. | `number` | `350` | no | | [flow\_logs\_cos\_bucket\_minimum\_retention\_days](#input\_flow\_logs\_cos\_bucket\_minimum\_retention\_days) | The minimum number of days that an object must be kept unmodified in the flow logs cloud object storage. | `number` | `90` | no | | [flow\_logs\_cos\_bucket\_name](#input\_flow\_logs\_cos\_bucket\_name) | Name of the Cloud Object Storage bucket to be created to collect VPC flow logs. | `string` | `"flow-logs-bucket"` | no | +| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The IBM Cloud api token | `string` | n/a | yes | +| [ignore\_worker\_pool\_size\_changes](#input\_ignore\_worker\_pool\_size\_changes) | Enable if using worker autoscaling. Stops Terraform managing worker count. | `bool` | `false` | no | | [key\_create\_import\_access\_enabled](#input\_key\_create\_import\_access\_enabled) | If set to `true`, a key create and import access policy is enabled on the instance of Key Protect. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `true` | no | | [key\_protect\_allowed\_network](#input\_key\_protect\_allowed\_network) | Allowed network types for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"private-only"` | no | | [kms\_access\_tags](#input\_kms\_access\_tags) | A list of access tags to apply to the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `list(string)` | `[]` | no | @@ -201,12 +237,19 @@ module "monolith_ocp_add_ons" { | [kms\_resource\_tags](#input\_kms\_resource\_tags) | Optional list of tags to add to the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `list(string)` | `[]` | no | | [logs\_policies](#input\_logs\_policies) | Configuration of Cloud Logs policies. |
list(object({
logs_policy_name = string
logs_policy_description = optional(string, null)
logs_policy_priority = string
application_rule = optional(list(object({
name = string
rule_type_id = string
})))
subsystem_rule = optional(list(object({
name = string
rule_type_id = string
})))
log_rules = optional(list(object({
severities = list(string)
})))
archive_retention = optional(list(object({
id = string
})))
}))
| `[]` | no | | [logs\_routing\_tenant\_regions](#input\_logs\_routing\_tenant\_regions) | Pass a list of regions to create a tenant for that is targeted to the Cloud Logs instance created by this module. To manage platform logs that are generated by IBM Cloud® services in a region of IBM Cloud, you must create a tenant in each region that you operate. Leave the list empty if you don't want to create any tenants. NOTE: You can only have 1 tenant per region in an account. | `list(any)` | `[]` | no | +| [manage\_all\_addons](#input\_manage\_all\_addons) | Instructs deployable architecture to manage all cluster addons, even if addons were installed outside of the module. If set to 'true' this deployable architecture destroys any addons that were installed by other sources. | `bool` | `false` | no | | [management\_endpoint\_type\_for\_buckets](#input\_management\_endpoint\_type\_for\_buckets) | The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Possible values: `public`, `private`, `direct`. If you specify `private`, enable virtual routing and forwarding in your account, and the Terraform runtime must have access to the the IBM Cloud private network. | `string` | `"direct"` | no | | [metrics\_router\_routes](#input\_metrics\_router\_routes) | Routes for IBM Cloud Metrics Routing. |
list(object({
name = string
rules = list(object({
action = string
targets = list(object({
id = string
}))
inclusion_filters = list(object({
operand = string
operator = string
values = list(string)
}))
}))
}))
| `[]` | no | | [metrics\_routing\_route\_name](#input\_metrics\_routing\_route\_name) | The name of the IBM Cloud Metrics Routing route for the default route that indicate what metrics are routed in a region and where to store them. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"metrics-routing-route"` | no | | [metrics\_routing\_target\_name](#input\_metrics\_routing\_target\_name) | The name of the IBM Cloud Metrics Routing target where metrics are collected. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"cloud-monitoring-target"` | no | | [network\_acls](#input\_network\_acls) | The list of ACLs to create. Provide at least one rule for each ACL. |
list(
object({
name = string
add_ibm_cloud_internal_rules = optional(bool)
add_vpc_connectivity_rules = optional(bool)
prepend_ibm_rules = optional(bool)
rules = list(
object({
name = string
action = string
destination = string
direction = string
source = string
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
})
)
|
[
{
"add_ibm_cloud_internal_rules": true,
"add_vpc_connectivity_rules": true,
"name": "vpc-acl",
"prepend_ibm_rules": true,
"rules": [
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-443-inbound-source",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-443-inbound-dest",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-80-inbound",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 80,
"source_port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-ingress-inbound",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 32767,
"source_port_min": 30000
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-443-outbound-source",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-443-outbound-dest",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-80-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 80,
"port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-ingress-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 32767,
"port_min": 30000
}
}
]
}
]
| no | +| [number\_of\_lbs](#input\_number\_of\_lbs) | The total number of Load Balancers in the cluster that should be associated with the security groups defined in `additional_lb_security_group_ids` variable. | `number` | `1` | no | +| [ocp\_cbr\_rules](#input\_ocp\_cbr\_rules) | The list of context-based restriction rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [ocp\_entitlement](#input\_ocp\_entitlement) | Value that is applied to the entitlements for OCP cluster provisioning. | `string` | `null` | no | +| [openshift\_version](#input\_openshift\_version) | Version of the OpenShift cluster to provision. | `string` | `"4.19"` | no | +| [pod\_subnet\_cidr](#input\_pod\_subnet\_cidr) | Specify a custom subnet CIDR to provide private IP addresses for pods. The subnet must have a CIDR of at least `/23` or larger. Default value is `172.30.0.0/16` when the variable is set to `null`. | `string` | `null` | no | | [prefix](#input\_prefix) | The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string. | `string` | n/a | yes | +| [provider\_visibility](#input\_provider\_visibility) | Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. | `string` | `"private"` | no | | [region](#input\_region) | The region to provision all resources in. | `string` | `"us-south"` | no | | [resource\_group\_id](#input\_resource\_group\_id) | The ID of an existing IBM Cloud resource group where the cluster is grouped. | `string` | n/a | yes | | [rotation\_enabled](#input\_rotation\_enabled) | If set to `true`, a rotation policy is enabled on the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `true` | no | @@ -225,9 +268,11 @@ module "monolith_ocp_add_ons" { | [secrets\_manager\_endpoint\_type](#input\_secrets\_manager\_endpoint\_type) | The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications. | `string` | `"private"` | no | | [secrets\_manager\_instance\_name](#input\_secrets\_manager\_instance\_name) | The name to give the Secrets Manager instance provisioned by this solution. If a prefix input variable is specified, it is added to the value in the `-value` format. Applies only if `existing_secrets_manager_crn` is not provided. | `string` | `"secrets-manager"` | no | | [secrets\_manager\_resource\_tags](#input\_secrets\_manager\_resource\_tags) | The list of resource tags you want to associate with your Secrets Manager instance. Applies only if `existing_secrets_manager_crn` is not provided. | `list(string)` | `[]` | no | +| [secrets\_manager\_secret\_group\_id](#input\_secrets\_manager\_secret\_group\_id) | Secret group ID where Ingress secrets are stored in the Secrets Manager instance. If 'enable\_secrets\_manager\_integration' is set to true and 'secrets\_manager\_secret\_group\_id' is not provided, a new group will be created with the same name as cluster\_id. | `string` | `null` | no | | [secrets\_manager\_service\_plan](#input\_secrets\_manager\_service\_plan) | The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. You can create only one Trial instance of Secrets Manager per account. Before you can create a new Trial instance, you must delete the existing Trial instance and its reclamation. | `string` | `"standard"` | no | | [security\_group\_rules](#input\_security\_group\_rules) | A list of security group rules to be added to the default vpc security group (default empty). |
list(
object({
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
| `[]` | no | | [service\_cred](#input\_service\_cred) | Service configuration for COS. |
list(object({
secret_group_name = string # pragma: allowlist secret
secret_group_description = optional(string) # pragma: allowlist secret
existing_secret_group = optional(bool) # pragma: allowlist secret
service_credentials = list(object({ # pragma: allowlist secret
secret_name = string # pragma: allowlist secret
service_credentials_source_service_role_crn = string # pragma: allowlist secret
secret_labels = optional(list(string)) # pragma: allowlist secret
secret_auto_rotation = optional(bool) # pragma: allowlist secret
secret_auto_rotation_unit = optional(string) # pragma: allowlist secret
secret_auto_rotation_interval = optional(number) # pragma: allowlist secret
service_credentials_ttl = optional(string) # pragma: allowlist secret
service_credential_secret_description = optional(string) # pragma: allowlist secret

}))
}))
| `[]` | no | +| [service\_subnet\_cidr](#input\_service\_subnet\_cidr) | Specify a custom subnet CIDR to provide private IP addresses for services. The subnet must be at least `/24` or larger. Default value is `172.21.0.0/16` when the variable is set to `null`. | `string` | `null` | no | | [skip\_activity\_tracker\_cos\_auth\_policy](#input\_skip\_activity\_tracker\_cos\_auth\_policy) | To skip creating an IAM authorization policy that allows the Activity Tracker to write to the Cloud Object Storage instance, set this variable to `true`. | `bool` | `false` | no | | [skip\_app\_config\_event\_notifications\_auth\_policy](#input\_skip\_app\_config\_event\_notifications\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits App configuration instances to integrate with Event Notification in the same account. | `bool` | `false` | no | | [skip\_app\_config\_kms\_auth\_policy](#input\_skip\_app\_config\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits App configuration instances in the resource group to read the encryption key from the KMS instance in the same account. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the other account. | `bool` | `false` | no | @@ -236,12 +281,14 @@ module "monolith_ocp_add_ons" { | [skip\_event\_notifications\_kms\_auth\_policy](#input\_skip\_event\_notifications\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | | [skip\_event\_notifications\_secrets\_manager\_auth\_policy](#input\_skip\_event\_notifications\_secrets\_manager\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing\_secrets\_manager\_crn' is not passed. | `bool` | `false` | no | | [skip\_logs\_routing\_auth\_policy](#input\_skip\_logs\_routing\_auth\_policy) | Whether to create an IAM authorization policy that permits the Logs Routing server 'Sender' access to the IBM Cloud Logs instance created by this Deployable Architecture. | `bool` | `false` | no | +| [skip\_ocp\_secrets\_manager\_iam\_auth\_policy](#input\_skip\_ocp\_secrets\_manager\_iam\_auth\_policy) | To skip creating auth policy that allows OCP cluster 'Manager' role access in the existing Secrets Manager instance for managing ingress certificates. | `bool` | `false` | no | | [skip\_secrets\_manager\_cos\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_cos\_iam\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Cloud Object Storage. Set to `true` to use an existing policy. | `bool` | `false` | no | | [skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy) | If set to true, this skips the creation of a service to service authorization from Secrets Manager to Event Notifications. If false, the service to service authorization is created. | `bool` | `false` | no | | [skip\_secrets\_manager\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_iam\_auth\_policy) | Whether to skip the creation of the IAM authorization policies required to enable the IAM credentials engine (if you are using an existing Secrets Manager instance, attempting to re-create can cause conflicts if the policies already exist). If set to false, policies will be created that grants the Secrets Manager instance 'Operator' access to the IAM identity service, and 'Groups Service Member Manage' access to the IAM groups service. | `bool` | `false` | no | | [skip\_secrets\_manager\_kms\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_kms\_iam\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances in the resource group to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. | `bool` | `false` | no | | [skip\_vpc\_cos\_iam\_auth\_policy](#input\_skip\_vpc\_cos\_iam\_auth\_policy) | To skip creating an IAM authorization policy that allows the VPC to access the Cloud Object Storage, set this variable to `true`. Required only if `enable_vpc_flow_logs` is set to true. | `bool` | `false` | no | | [subnets](#input\_subnets) | List of subnets for the vpc. For each item in each array, a subnet will be created. Items can be either CIDR blocks or total ipv4 addresses. Public gateways will be enabled only in zones where a gateway has been createds. |
object({
zone-1 = list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
}))
zone-2 = optional(list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
})))
zone-3 = optional(list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
})))
})
|
{
"zone-1": [
{
"acl_name": "vpc-acl",
"cidr": "10.10.10.0/24",
"name": "subnet-a",
"no_addr_prefix": false,
"public_gateway": true
}
],
"zone-2": [
{
"acl_name": "vpc-acl",
"cidr": "10.20.10.0/24",
"name": "subnet-b",
"no_addr_prefix": false,
"public_gateway": true
}
],
"zone-3": [
{
"acl_name": "vpc-acl",
"cidr": "10.30.10.0/24",
"name": "subnet-c",
"no_addr_prefix": false,
"public_gateway": true
}
]
}
| no | +| [verify\_worker\_network\_readiness](#input\_verify\_worker\_network\_readiness) | By setting this to true, a script runs kubectl commands to verify that all worker nodes can communicate successfully with the master. If the runtime does not have access to the kube cluster to run kubectl commands, set this value to false. | `bool` | `true` | no | | [vpc\_access\_tags](#input\_vpc\_access\_tags) | The list of access tags to add to the VPC instance. | `list(string)` | `[]` | no | | [vpc\_flow\_logs\_access\_tags](#input\_vpc\_flow\_logs\_access\_tags) | The list of access tags to add to the VPC instance. | `list(string)` | `[]` | no | | [vpc\_name](#input\_vpc\_name) | Name of the VPC. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"vpc"` | no | @@ -252,6 +299,7 @@ module "monolith_ocp_add_ons" { | [vpe\_gateway\_security\_group\_ids](#input\_vpe\_gateway\_security\_group\_ids) | List of security group ids to attach to each endpoint gateway. | `list(string)` | `null` | no | | [vpe\_gateway\_service\_endpoints](#input\_vpe\_gateway\_service\_endpoints) | Service endpoints to use to create endpoint gateways. Can be `public`, or `private`. | `string` | `"private"` | no | | [vpn\_gateways](#input\_vpn\_gateways) | List of VPN Gateways to create. |
list(
object({
name = string
subnet_name = string # Do not include prefix, use same name as in `var.subnets`
mode = optional(string)
resource_group = optional(string)
access_tags = optional(list(string), [])
})
)
| `[]` | no | +| [worker\_pools\_taints](#input\_worker\_pools\_taints) | Optional, Map of lists containing node taints by node-pool name. | `map(list(object({ key = string, value = string, effect = string })))` | `null` | no | ### Outputs @@ -260,9 +308,6 @@ module "monolith_ocp_add_ons" { | [activity\_tracker\_cos\_target\_bucket\_name](#output\_activity\_tracker\_cos\_target\_bucket\_name) | he name of the object storage bucket which is set as activity tracker event routing target to collect audit events. | | [activity\_tracker\_routes](#output\_activity\_tracker\_routes) | The map of created Activity Tracker Event Routing routes | | [activity\_tracker\_targets](#output\_activity\_tracker\_targets) | The map of created Activity Tracker Event Routing targets | -| [boot\_volume\_existing\_kms\_guid](#output\_boot\_volume\_existing\_kms\_guid) | The GUID for the boot volume encryption | -| [boot\_volume\_kms\_account\_id](#output\_boot\_volume\_kms\_account\_id) | The Account ID for the boot volume encryption | -| [boot\_volume\_kms\_key\_id](#output\_boot\_volume\_kms\_key\_id) | The Key ID for the boot volume encryption | | [cloud\_logs\_crn](#output\_cloud\_logs\_crn) | The id of the provisioned IBM Cloud Logs instance. | | [cloud\_logs\_guid](#output\_cloud\_logs\_guid) | The guid of the provisioned IBM Cloud Logs instance. | | [cloud\_logs\_ingress\_endpoint](#output\_cloud\_logs\_ingress\_endpoint) | The public ingress endpoint of the provisioned IBM Cloud Logs instance. | @@ -274,6 +319,9 @@ module "monolith_ocp_add_ons" { | [cloud\_monitoring\_crn](#output\_cloud\_monitoring\_crn) | The id of the provisioned IBM Cloud Monitoring instance. | | [cloud\_monitoring\_guid](#output\_cloud\_monitoring\_guid) | The guid of the provisioned IBM Cloud Monitoring instance. | | [cloud\_monitoring\_name](#output\_cloud\_monitoring\_name) | The name of the provisioned IBM Cloud Monitoring instance. | +| [cluster\_crn](#output\_cluster\_crn) | The Cloud Resource Name (CRN) of the provisioned OpenShift cluster. | +| [cluster\_id](#output\_cluster\_id) | The unique identifier assigned to the provisioned OpenShift cluster. | +| [cluster\_name](#output\_cluster\_name) | The name of the provisioned OpenShift cluster. | | [cos\_instance\_crn](#output\_cos\_instance\_crn) | COS instance crn | | [cos\_instance\_guid](#output\_cos\_instance\_guid) | COS instance guid | | [cos\_instance\_id](#output\_cos\_instance\_id) | COS instance ID | @@ -287,6 +335,7 @@ module "monolith_ocp_add_ons" { | [logs\_bucket\_crn](#output\_logs\_bucket\_crn) | Logs Cloud Object Storage bucket CRN | | [metrics\_bucket\_crn](#output\_metrics\_bucket\_crn) | Metrics Cloud Object Storage bucket CRN | | [network\_acls](#output\_network\_acls) | List of shortnames and IDs of network ACLs. | +| [ocp\_version](#output\_ocp\_version) | The version of OpenShift running on the provisioned cluster. | | [private\_path\_subnet\_id](#output\_private\_path\_subnet\_id) | The IDs of the subnets. | | [public\_gateways](#output\_public\_gateways) | Map of the public gateways by zone. | | [scc\_workload\_protection\_api\_endpoint](#output\_scc\_workload\_protection\_api\_endpoint) | SCC Workload Protection API endpoint | @@ -309,4 +358,5 @@ module "monolith_ocp_add_ons" { | [vpe\_ips](#output\_vpe\_ips) | The reserved IPs for endpoint gateways. | | [vpn\_gateways\_data](#output\_vpn\_gateways\_data) | Details of VPN gateways data. | | [vpn\_gateways\_name](#output\_vpn\_gateways\_name) | List of names of VPN gateways. | +| [workerpools](#output\_workerpools) | A list of worker pools associated with the provisioned cluster | diff --git a/modules/monolith/main.tf b/modules/monolith/main.tf index 7a33e6fad..fc2dc5c0d 100644 --- a/modules/monolith/main.tf +++ b/modules/monolith/main.tf @@ -31,6 +31,7 @@ locals { cluster_kms_key_crn = var.kms_encryption_enabled_cluster ? module.kms[0].keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn : var.existing_cluster_kms_key_crn != null ? var.existing_boot_volume_kms_key_crn : var.kms_encryption_enabled_cluster ? module.kms[0].key_protect_crn : null cluster_key_ring_name = "${local.prefix}${var.cluster_kms_key_ring_name}" cluster_key_name = "${local.prefix}${var.cluster_kms_key_name}" + cluster_name = "${local.prefix}${var.cluster_name}" boot_volume_key_ring_name = "${local.prefix}${var.boot_volume_kms_key_ring_name}" boot_volume_key_name = "${local.prefix}${var.boot_volume_kms_key_name}" @@ -923,3 +924,149 @@ module "vpe_gateway" { service_endpoints = var.vpe_gateway_service_endpoints reserved_ips = var.vpe_gateway_reserved_ips } + +######################################################################################################################## +# OCP VPC cluster +######################################################################################################################## + +locals { + vpc_subnets = { + # The default behavior is to deploy the worker pool across all subnets within the VPC. + "default" = [ + for subnet in module.vpc.subnet_zone_list : + { + id = subnet.id + zone = subnet.zone + cidr_block = subnet.cidr + } + ] + } + + worker_pools = concat([ + { + subnet_prefix = "default" + pool_name = "default" + machine_type = var.default_worker_pool_machine_type + workers_per_zone = var.default_worker_pool_workers_per_zone + resource_group_id = var.resource_group_id + operating_system = var.default_worker_pool_operating_system + labels = var.default_worker_pool_labels + minSize = var.default_pool_minimum_number_of_nodes + maxSize = var.default_pool_maximum_number_of_nodes + enableAutoscaling = var.enable_autoscaling_for_default_pool + boot_volume_encryption_kms_config = { + crk = local.boot_volume_kms_key_id + kms_instance_id = local.boot_volume_existing_kms_guid + kms_account_id = local.boot_volume_kms_account_id + } + additional_security_group_ids = var.additional_security_group_ids + } + ], [for pool in var.additional_worker_pools : merge(pool, { resource_group_id = var.resource_group_id + boot_volume_encryption_kms_config = { + crk = local.boot_volume_kms_key_id + kms_instance_id = local.boot_volume_existing_kms_guid + kms_account_id = local.boot_volume_kms_account_id + } }) if length(pool.vpc_subnets) > 0], + [for pool in var.additional_worker_pools : { + pool_name = pool.pool_name + machine_type = pool.machine_type + workers_per_zone = pool.workers_per_zone + resource_group_id = var.resource_group_id + operating_system = pool.operating_system + labels = pool.labels + minSize = pool.minSize + secondary_storage = pool.secondary_storage + maxSize = pool.maxSize + enableAutoscaling = pool.enableAutoscaling + boot_volume_encryption_kms_config = { + crk = local.boot_volume_kms_key_id + kms_instance_id = local.boot_volume_existing_kms_guid + kms_account_id = local.boot_volume_kms_account_id + } + additional_security_group_ids = pool.additional_security_group_ids + subnet_prefix = "default" + } if length(pool.vpc_subnets) == 0]) + + # Managing the ODF version accordingly, as it changes with each OCP version. + addons = lookup(var.addons, "openshift-data-foundation", null) != null ? lookup(var.addons["openshift-data-foundation"], "version", null) == null ? { for key, value in var.addons : + key => value != null ? { + version = lookup(value, "version", null) == null && key == "openshift-data-foundation" ? "${var.openshift_version}.0" : lookup(value, "version", null) + parameters_json = lookup(value, "parameters_json", null) + } : null } : var.addons : var.addons +} + +module "ocp_base" { + source = "../.." + resource_group_id = var.resource_group_id + region = var.region + tags = var.cluster_resource_tags + cluster_name = local.cluster_name + force_delete_storage = true + use_existing_cos = true + existing_cos_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_crn + vpc_id = module.vpc.vpc_id + vpc_subnets = local.vpc_subnets + ocp_version = var.openshift_version + worker_pools = local.worker_pools + access_tags = var.access_tags + ocp_entitlement = var.ocp_entitlement + additional_lb_security_group_ids = var.additional_lb_security_group_ids + additional_vpe_security_group_ids = var.additional_vpe_security_group_ids + addons = local.addons + allow_default_worker_pool_replacement = var.allow_default_worker_pool_replacement + attach_ibm_managed_security_group = var.attach_ibm_managed_security_group + cluster_config_endpoint_type = var.cluster_config_endpoint_type + cbr_rules = var.ocp_cbr_rules + cluster_ready_when = var.cluster_ready_when + custom_security_group_ids = var.custom_security_group_ids + disable_outbound_traffic_protection = var.allow_outbound_traffic + disable_public_endpoint = !var.allow_public_access_to_cluster_management + enable_ocp_console = var.enable_ocp_console + ignore_worker_pool_size_changes = var.ignore_worker_pool_size_changes + kms_config = local.kms_config + manage_all_addons = var.manage_all_addons + number_of_lbs = var.number_of_lbs + pod_subnet_cidr = var.pod_subnet_cidr + service_subnet_cidr = var.service_subnet_cidr + verify_worker_network_readiness = var.verify_worker_network_readiness + worker_pools_taints = var.worker_pools_taints + enable_secrets_manager_integration = var.enable_secrets_manager_integration + existing_secrets_manager_instance_crn = local.secrets_manager_crn + secrets_manager_secret_group_id = var.secrets_manager_secret_group_id != null ? var.secrets_manager_secret_group_id : (var.enable_secrets_manager_integration ? module.secret_group[0].secret_group_id : null) + skip_ocp_secrets_manager_iam_auth_policy = var.skip_ocp_secrets_manager_iam_auth_policy +} + +resource "terraform_data" "delete_secrets" { + count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 + input = { + secret_id = module.secret_group[0].secret_group_id + provider_visibility = var.provider_visibility + secrets_manager_instance_id = local.secrets_manager_guid + secrets_manager_region = local.secrets_manager_region + secrets_manager_endpoint = var.secrets_manager_endpoint_type + } + # api key in triggers_replace to avoid it to be printed out in clear text in terraform_data output + triggers_replace = { + api_key = var.ibmcloud_api_key + } + provisioner "local-exec" { + when = destroy + command = "${path.module}/../../solutions/fully-configurable/scripts/delete_secrets.sh ${self.input.secret_id} ${self.input.provider_visibility} ${self.input.secrets_manager_instance_id} ${self.input.secrets_manager_region} ${self.input.secrets_manager_endpoint}" + interpreter = ["/bin/bash", "-c"] + + environment = { + API_KEY = self.triggers_replace.api_key + } + } +} + +module "secret_group" { + count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 + source = "terraform-ibm-modules/secrets-manager-secret-group/ibm" + version = "1.3.15" + region = local.secrets_manager_region + secrets_manager_guid = local.secrets_manager_guid + secret_group_name = module.ocp_base.cluster_id + secret_group_description = "Secret group for storing ingress certificates for cluster ${local.cluster_name} with id: ${module.ocp_base.cluster_id}" + endpoint_type = var.secrets_manager_endpoint_type +} diff --git a/modules/monolith/outputs.tf b/modules/monolith/outputs.tf index b66be2b21..26efb70d2 100644 --- a/modules/monolith/outputs.tf +++ b/modules/monolith/outputs.tf @@ -130,21 +130,6 @@ output "kms_config" { value = local.kms_config } -output "boot_volume_kms_key_id" { - description = "The Key ID for the boot volume encryption" - value = local.boot_volume_kms_key_id -} - -output "boot_volume_existing_kms_guid" { - description = "The GUID for the boot volume encryption" - value = local.boot_volume_existing_kms_guid -} - -output "boot_volume_kms_account_id" { - description = "The Account ID for the boot volume encryption" - value = local.boot_volume_kms_account_id -} - ############################################################################## # EN Outputs ############################################################################## @@ -320,3 +305,32 @@ output "scc_workload_protection_api_endpoint" { value = module.scc_wp.api_endpoint sensitive = true } + +############################################################################## +# Cluster Outputs +############################################################################## + +output "cluster_name" { + value = module.ocp_base.cluster_name + description = "The name of the provisioned OpenShift cluster." +} + +output "cluster_id" { + value = module.ocp_base.cluster_id + description = "The unique identifier assigned to the provisioned OpenShift cluster." +} + +output "cluster_crn" { + description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." + value = module.ocp_base.cluster_crn +} + +output "workerpools" { + description = "A list of worker pools associated with the provisioned cluster" + value = module.ocp_base.workerpools +} + +output "ocp_version" { + description = "The version of OpenShift running on the provisioned cluster." + value = module.ocp_base.ocp_version +} diff --git a/modules/monolith/variables.tf b/modules/monolith/variables.tf index fb231cf43..55478ed52 100644 --- a/modules/monolith/variables.tf +++ b/modules/monolith/variables.tf @@ -1,3 +1,19 @@ +variable "ibmcloud_api_key" { + type = string + description = "The IBM Cloud api token" + sensitive = true +} + +variable "provider_visibility" { + description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`." + type = string + default = "private" + validation { + condition = contains(["public", "private", "public-and-private"], var.provider_visibility) + error_message = "Invalid visibility option. Allowed values are `public`, `private`, or `public-and-private`." + } +} + variable "prefix" { type = string nullable = true @@ -2027,3 +2043,310 @@ variable "vpe_gateway_reserved_ips" { }) default = {} } + +######################################################################################################################## +# OCP VPC cluster +######################################################################################################################## + +variable "cluster_name" { + type = string + description = "The name of the new IBM Cloud OpenShift Cluster. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "openshift" +} + +variable "default_worker_pool_machine_type" { + type = string + description = "The machine type for worker nodes." + default = "bx2.4x16" + validation { + condition = length(regexall("^[a-z0-9]+(?:\\.[a-z0-9]+)*\\.\\d+x\\d+(?:\\.[a-z0-9]+)?$", var.default_worker_pool_machine_type)) > 0 + error_message = "Invalid value provided for the machine type." + } +} + +variable "default_worker_pool_workers_per_zone" { + type = number + description = "Number of worker nodes in each zone of the cluster." + default = 1 +} + +variable "default_worker_pool_operating_system" { + type = string + description = "The operating system installed on the worker nodes." + default = "RHCOS" +} + +variable "default_worker_pool_labels" { + type = map(string) + description = "A set of key-value labels assigned to the worker pool for identification." + default = {} +} + +variable "default_pool_minimum_number_of_nodes" { + type = number + description = "The minimum number of worker nodes allowed in the pool, ensuring at least one worker is always running." + default = 1 +} + +variable "default_pool_maximum_number_of_nodes" { + type = number + description = "The maximum number of worker nodes allowed in the pool, preventing the pool from exceeding three workers." + default = 3 +} + +variable "additional_security_group_ids" { + type = list(string) + description = "A list of security group IDs that are attached to the worker nodes for additional network security controls." + default = [] +} + +variable "additional_worker_pools" { + type = list(object({ + vpc_subnets = optional(list(object({ + id = string + zone = string + cidr_block = string + })), []) + pool_name = string + machine_type = string + workers_per_zone = number + operating_system = string + labels = optional(map(string)) + minSize = optional(number) + secondary_storage = optional(string) + maxSize = optional(number) + enableAutoscaling = optional(bool) + additional_security_group_ids = optional(list(string)) + })) + description = "List of additional worker pools." + default = [] +} + +variable "enable_autoscaling_for_default_pool" { + type = bool + description = "Set `true` to enable automatic scaling of worker based on workload demand." + default = false +} + +variable "addons" { + type = object({ + debug-tool = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + image-key-synchronizer = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + openshift-data-foundation = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + vpc-file-csi-driver = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + static-route = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + cluster-autoscaler = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + vpc-block-csi-driver = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + ibm-storage-operator = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + openshift-ai = optional(object({ + version = optional(string) + parameters_json = optional(string) + })) + }) + description = "Map of OCP cluster add-on versions to install (NOTE: The 'vpc-block-csi-driver' add-on is installed by default for VPC clusters and 'ibm-storage-operator' is installed by default in OCP 4.15 and later, however you can explicitly specify it here if you wish to choose a later version than the default one). [Check supported addons and versions here](https://cloud.ibm.com/docs/containers?topic=containers-supported-cluster-addon-versions)." + nullable = false + default = {} +} + +variable "openshift_version" { + type = string + description = "Version of the OpenShift cluster to provision." + default = "4.19" +} + +variable "cluster_resource_tags" { + type = list(string) + description = "Metadata labels describing this cluster deployment, i.e. test." + default = [] +} + +variable "access_tags" { + type = list(string) + description = "A list of access tags to apply to the resources created by the module." + default = [] +} + +variable "ocp_entitlement" { + type = string + description = "Value that is applied to the entitlements for OCP cluster provisioning." + default = null +} + +variable "additional_lb_security_group_ids" { + description = "List of additional security group IDs to add to the load balancers associated with the cluster. Ensure that the `number_of_lbs` variable is set to the number of Load Balancers associated with the cluster. This comes in addition to the IBM maintained security group." + type = list(string) + default = [] + nullable = false +} + +variable "number_of_lbs" { + description = "The total number of Load Balancers in the cluster that should be associated with the security groups defined in `additional_lb_security_group_ids` variable." + type = number + default = 1 + nullable = false +} + +variable "additional_vpe_security_group_ids" { + description = "Additional security groups to add to all existing load balancers. This comes in addition to the IBM maintained security group." + type = object({ + master = optional(list(string), []) + registry = optional(list(string), []) + api = optional(list(string), []) + }) + default = {} +} + +variable "allow_default_worker_pool_replacement" { + type = bool + description = "Set to true to allow the module to recreate a default worker pool. Only use in the case where you are getting an error indicating that the default worker pool cannot be replaced on apply. Once the default worker pool is handled separately, if you wish to make any change to the default worker pool which requires the re-creation of the default pool set this variable to true." + default = false + nullable = false +} + +variable "attach_ibm_managed_security_group" { + description = "Specify whether to attach the IBM-defined default security group (whose name is kube-) to all worker nodes. Only applicable if `custom_security_group_ids` is set." + type = bool + default = true +} + +variable "cluster_config_endpoint_type" { + description = "Specify which type of endpoint to use for cluster config access: 'default', 'private', 'vpe', 'link'. A 'default' value uses the default endpoint of the cluster." + type = string + default = "default" + nullable = false +} + +variable "verify_worker_network_readiness" { + type = bool + description = "By setting this to true, a script runs kubectl commands to verify that all worker nodes can communicate successfully with the master. If the runtime does not have access to the kube cluster to run kubectl commands, set this value to false." + default = true +} + +variable "cluster_ready_when" { + type = string + description = "The cluster is ready based on one of the following:: MasterNodeReady (not recommended), OneWorkerNodeReady, Normal, IngressReady." + default = "IngressReady" +} + +variable "custom_security_group_ids" { + description = "Security groups to add to all worker nodes. This comes in addition to the IBM maintained security group if `attach_ibm_managed_security_group` is set to true. If this variable is set, the default VPC security group is NOT assigned to the worker nodes." + type = list(string) + default = null +} + +variable "allow_outbound_traffic" { + type = bool + description = "Set to true to allow public outbound access from the cluster workers." + default = true +} + +variable "allow_public_access_to_cluster_management" { + type = bool + description = "Set to true to access the cluster through a public cloud service endpoint." + default = true +} + +variable "enable_ocp_console" { + description = "Flag to specify whether to enable or disable the OpenShift console. If set to `null` the module does not modify the current setting on the cluster. Keep in mind that when this input is set to `true` or `false` on a cluster with private only endpoint enabled, the runtime must be able to access the private endpoint." + type = bool + default = null + nullable = true +} + +variable "ignore_worker_pool_size_changes" { + type = bool + description = "Enable if using worker autoscaling. Stops Terraform managing worker count." + default = false +} + +variable "manage_all_addons" { + type = bool + default = false + nullable = false + description = "Instructs deployable architecture to manage all cluster addons, even if addons were installed outside of the module. If set to 'true' this deployable architecture destroys any addons that were installed by other sources." +} + +variable "pod_subnet_cidr" { + type = string + description = "Specify a custom subnet CIDR to provide private IP addresses for pods. The subnet must have a CIDR of at least `/23` or larger. Default value is `172.30.0.0/16` when the variable is set to `null`." + default = null +} + +variable "service_subnet_cidr" { + type = string + description = "Specify a custom subnet CIDR to provide private IP addresses for services. The subnet must be at least `/24` or larger. Default value is `172.21.0.0/16` when the variable is set to `null`." + default = null +} + +variable "worker_pools_taints" { + type = map(list(object({ key = string, value = string, effect = string }))) + description = "Optional, Map of lists containing node taints by node-pool name." + default = null +} + +variable "enable_secrets_manager_integration" { + type = bool + description = "Integrate with IBM Cloud Secrets Manager so you can centrally manage Ingress subdomain certificates and other secrets." + default = true + nullable = false +} + +variable "secrets_manager_secret_group_id" { + type = string + description = "Secret group ID where Ingress secrets are stored in the Secrets Manager instance. If 'enable_secrets_manager_integration' is set to true and 'secrets_manager_secret_group_id' is not provided, a new group will be created with the same name as cluster_id." + default = null +} + +variable "skip_ocp_secrets_manager_iam_auth_policy" { + type = bool + description = "To skip creating auth policy that allows OCP cluster 'Manager' role access in the existing Secrets Manager instance for managing ingress certificates." + default = false +} + +variable "ocp_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + tags = optional(list(object({ + name = string + value = string + })), []) + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restriction rules to create." + default = [] +} diff --git a/tests/other_test.go b/tests/other_test.go index c0ef925f0..30173d5a9 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -220,7 +220,7 @@ func TestMonolithExample(t *testing.T) { WaitJobCompleteMinutes: 240, IgnoreAdds: testhelper.Exemptions{ List: []string{ - "module.monolith_add_ons.module.scc_wp.restapi_object.cspm", + "module.ocp_cluster_with_add_ons.module.scc_wp.restapi_object.cspm", }, }, IgnoreUpdates: testhelper.Exemptions{ @@ -230,14 +230,13 @@ func TestMonolithExample(t *testing.T) { "module.monitoring_agent.helm_release.cloud_monitoring_agent", // Have to ignore account settings as other tests may be updating them concurrently // which can cause consistency test to fail if not ignored. - "module.monolith_add_ons.module.metrics_routing[0].ibm_metrics_router_settings.metrics_router_settings[0]", + "module.ocp_cluster_with_add_ons.module.metrics_routing[0].ibm_metrics_router_settings.metrics_router_settings[0]", }, }, }) options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "prefix", Value: options.Prefix, DataType: "string"}, - {Name: "kms_encryption_enabled_cluster", Value: true, DataType: "bool"}, } err := options.RunSchematicTest() From b3a60e6a9395f4893f72482ab66dfe6ab9bd14d2 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Thu, 11 Dec 2025 13:26:16 +0530 Subject: [PATCH 07/15] pre-commit changes --- examples/monolith/version.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/monolith/version.tf b/examples/monolith/version.tf index 8c94c3ba8..a1a72fb06 100644 --- a/examples/monolith/version.tf +++ b/examples/monolith/version.tf @@ -3,19 +3,19 @@ terraform { required_providers { ibm = { source = "IBM-Cloud/ibm" - version = "1.84.3" + version = ">= 1.78.2, < 2.0.0" } restapi = { source = "Mastercard/restapi" - version = "2.0.1" + version = ">= 2.0.1" } helm = { source = "hashicorp/helm" - version = "3.0.2" + version = ">= 3.0.0, <4.0.0" } kubernetes = { source = "hashicorp/kubernetes" - version = "2.38.0" + version = ">= 2.16.1" } } } From a5309f706188ec2558f7f0b043244a68964d9e59 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Thu, 11 Dec 2025 13:33:35 +0530 Subject: [PATCH 08/15] pre-commit changes --- common-dev-assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common-dev-assets b/common-dev-assets index 99dc77722..56a3cfddb 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit 99dc77722bfa0a104d19511fd097af2fe0356db2 +Subproject commit 56a3cfddb4a1ef2599b100ae698ab2f6400e1bf8 From 603ecaad92f5a3b402f71165586060cba72db5d7 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Thu, 11 Dec 2025 17:53:14 +0530 Subject: [PATCH 09/15] Update folder name --- README.md | 4 ++-- .../{monolith => containerized_app_landing_zone}/README.md | 2 +- examples/{monolith => containerized_app_landing_zone}/main.tf | 2 +- .../{monolith => containerized_app_landing_zone}/outputs.tf | 0 .../{monolith => containerized_app_landing_zone}/provider.tf | 0 .../{monolith => containerized_app_landing_zone}/variables.tf | 0 .../{monolith => containerized_app_landing_zone}/version.tf | 0 .../{monolith => containerized_app_landing_zone}/README.md | 4 ++-- modules/{monolith => containerized_app_landing_zone}/main.tf | 0 .../{monolith => containerized_app_landing_zone}/outputs.tf | 0 .../{monolith => containerized_app_landing_zone}/variables.tf | 0 .../{monolith => containerized_app_landing_zone}/version.tf | 0 tests/other_test.go | 4 ++-- 13 files changed, 8 insertions(+), 8 deletions(-) rename examples/{monolith => containerized_app_landing_zone}/README.md (73%) rename examples/{monolith => containerized_app_landing_zone}/main.tf (98%) rename examples/{monolith => containerized_app_landing_zone}/outputs.tf (100%) rename examples/{monolith => containerized_app_landing_zone}/provider.tf (100%) rename examples/{monolith => containerized_app_landing_zone}/variables.tf (100%) rename examples/{monolith => containerized_app_landing_zone}/version.tf (100%) rename modules/{monolith => containerized_app_landing_zone}/README.md (99%) rename modules/{monolith => containerized_app_landing_zone}/main.tf (100%) rename modules/{monolith => containerized_app_landing_zone}/outputs.tf (100%) rename modules/{monolith => containerized_app_landing_zone}/variables.tf (100%) rename modules/{monolith => containerized_app_landing_zone}/version.tf (100%) diff --git a/README.md b/README.md index b31e4b578..ab4c9309e 100644 --- a/README.md +++ b/README.md @@ -27,18 +27,18 @@ By default, the module automatically downloads the required dependencies if they ## Overview * [terraform-ibm-base-ocp-vpc](#terraform-ibm-base-ocp-vpc) * [Submodules](./modules) + * [containerized_app_landing_zone](./modules/containerized_app_landing_zone) * [fscloud](./modules/fscloud) * [kube-audit](./modules/kube-audit) - * [monolith](./modules/monolith) * [worker-pool](./modules/worker-pool) * [Examples](./examples) *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
+ *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
- *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
* [Contributing](#contributing) diff --git a/examples/monolith/README.md b/examples/containerized_app_landing_zone/README.md similarity index 73% rename from examples/monolith/README.md rename to examples/containerized_app_landing_zone/README.md index 5326bad34..1ba6f4073 100644 --- a/examples/monolith/README.md +++ b/examples/containerized_app_landing_zone/README.md @@ -2,7 +2,7 @@ A simple example that shows how to provision a multi zone OCP VPC cluster as well as all foundational infrastructure and supporting services required for a secure and compliant OpenShift (OCP) cluster deployment on IBM Cloud VPC. -- Refer [here](../../modules/monolith/README.md) to check all the resources are provisioned by this example by calling the monolith module. +- Refer [here](../../modules/containerized_app_landing_zone/README.md) to check all the resources are provisioned by this example by calling the monolith module. - A new resource group if an existing resource group is not passed. - Monitoring agent. - A Trusted Profile with Sender role to logs service. diff --git a/examples/monolith/main.tf b/examples/containerized_app_landing_zone/main.tf similarity index 98% rename from examples/monolith/main.tf rename to examples/containerized_app_landing_zone/main.tf index 3dd13f678..61c341c92 100644 --- a/examples/monolith/main.tf +++ b/examples/containerized_app_landing_zone/main.tf @@ -13,7 +13,7 @@ module "resource_group" { ######################################################################################################################## module "ocp_cluster_with_add_ons" { - source = "../../modules/monolith" + source = "../../modules/containerized_app_landing_zone" prefix = var.prefix region = var.region ibmcloud_api_key = var.ibmcloud_api_key diff --git a/examples/monolith/outputs.tf b/examples/containerized_app_landing_zone/outputs.tf similarity index 100% rename from examples/monolith/outputs.tf rename to examples/containerized_app_landing_zone/outputs.tf diff --git a/examples/monolith/provider.tf b/examples/containerized_app_landing_zone/provider.tf similarity index 100% rename from examples/monolith/provider.tf rename to examples/containerized_app_landing_zone/provider.tf diff --git a/examples/monolith/variables.tf b/examples/containerized_app_landing_zone/variables.tf similarity index 100% rename from examples/monolith/variables.tf rename to examples/containerized_app_landing_zone/variables.tf diff --git a/examples/monolith/version.tf b/examples/containerized_app_landing_zone/version.tf similarity index 100% rename from examples/monolith/version.tf rename to examples/containerized_app_landing_zone/version.tf diff --git a/modules/monolith/README.md b/modules/containerized_app_landing_zone/README.md similarity index 99% rename from modules/monolith/README.md rename to modules/containerized_app_landing_zone/README.md index de61c9df7..c5177d1d9 100644 --- a/modules/monolith/README.md +++ b/modules/containerized_app_landing_zone/README.md @@ -27,14 +27,14 @@ The primary goal of this module is to provision an OpenShift cluster on VPC and ```hcl module "monolith_ocp_add_ons" { - source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/monolith" + source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/containerized_app_landing_zone" version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release prefix = "" region = "us-south" resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" } ``` -To run this module refer to the example [here](../../examples/monolith) +To run this module refer to the example [here](../../examples/containerized_app_landing_zone) ### Requirements diff --git a/modules/monolith/main.tf b/modules/containerized_app_landing_zone/main.tf similarity index 100% rename from modules/monolith/main.tf rename to modules/containerized_app_landing_zone/main.tf diff --git a/modules/monolith/outputs.tf b/modules/containerized_app_landing_zone/outputs.tf similarity index 100% rename from modules/monolith/outputs.tf rename to modules/containerized_app_landing_zone/outputs.tf diff --git a/modules/monolith/variables.tf b/modules/containerized_app_landing_zone/variables.tf similarity index 100% rename from modules/monolith/variables.tf rename to modules/containerized_app_landing_zone/variables.tf diff --git a/modules/monolith/version.tf b/modules/containerized_app_landing_zone/version.tf similarity index 100% rename from modules/monolith/version.tf rename to modules/containerized_app_landing_zone/version.tf diff --git a/tests/other_test.go b/tests/other_test.go index 30173d5a9..a3500215f 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -17,7 +17,7 @@ const advancedExampleDir = "examples/advanced" const basicExampleDir = "examples/basic" const fscloudExampleDir = "examples/fscloud" const crossKmsSupportExampleDir = "examples/cross_kms_support" -const monolithExampleDir = "examples/monolith" +const monolithExampleDir = "examples/containerized_app_landing_zone" func setupOptions(t *testing.T, prefix string, terraformDir string, ocpVersion string) *testhelper.TestOptions { options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ @@ -212,7 +212,7 @@ func TestMonolithExample(t *testing.T) { "modules/kube-audit/scripts/*.*", "modules/kube-audit/helm-charts/kube-audit/*.*", "modules/kube-audit/helm-charts/kube-audit/templates/*.*", - "modules/monolith/*.tf", + "modules/containerized_app_landing_zone/*.tf", }, TemplateFolder: monolithExampleDir, Tags: []string{"monolith-base-ocp-test"}, From 8a920bf2ad6b6107426c70b8127c643781ef49a2 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Thu, 11 Dec 2025 17:53:33 +0530 Subject: [PATCH 10/15] Update folder name --- common-dev-assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common-dev-assets b/common-dev-assets index 56a3cfddb..0424afd3c 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit 56a3cfddb4a1ef2599b100ae698ab2f6400e1bf8 +Subproject commit 0424afd3c435499ed3f0130f8cf6afb7ab36140d From 4de060a62ed93eca632e5d5485f7e45c69f24a8c Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Fri, 12 Dec 2025 00:49:44 +0530 Subject: [PATCH 11/15] PR changes --- README.md | 2 +- .../containerized_app_landing_zone/README.md | 12 +-- .../containerized_app_landing_zone/main.tf | 29 +++--- .../containerized_app_landing_zone/outputs.tf | 94 +++++++++---------- .../containerized_app_landing_zone/README.md | 2 +- tests/other_test.go | 14 +-- 6 files changed, 74 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index ab4c9309e..f27504a00 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ By default, the module automatically downloads the required dependencies if they *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
- *
Deploy to IBM Cloud button
+ *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
diff --git a/examples/containerized_app_landing_zone/README.md b/examples/containerized_app_landing_zone/README.md index 1ba6f4073..c214fe91b 100644 --- a/examples/containerized_app_landing_zone/README.md +++ b/examples/containerized_app_landing_zone/README.md @@ -1,9 +1,9 @@ -# IBM Cloud OpenShift DA - Monolith Add-ons Module Example +# IBM Cloud OpenShift Landing Zone with Integrated Services Example A simple example that shows how to provision a multi zone OCP VPC cluster as well as all foundational infrastructure and supporting services required for a secure and compliant OpenShift (OCP) cluster deployment on IBM Cloud VPC. -- Refer [here](../../modules/containerized_app_landing_zone/README.md) to check all the resources are provisioned by this example by calling the monolith module. -- A new resource group if an existing resource group is not passed. -- Monitoring agent. -- A Trusted Profile with Sender role to logs service. -- Logs agent. +* Refer [here](../../modules/containerized_app_landing_zone/README.md) to check all the resources that are provisioned by this example by calling the `containerized_app_landing_zone` module. +* A new resource group if an existing resource group is not passed. +* Monitoring agent. +* A Trusted Profile with Sender role to logs service. +* Logs agent. diff --git a/examples/containerized_app_landing_zone/main.tf b/examples/containerized_app_landing_zone/main.tf index 61c341c92..d020b2adc 100644 --- a/examples/containerized_app_landing_zone/main.tf +++ b/examples/containerized_app_landing_zone/main.tf @@ -9,10 +9,10 @@ module "resource_group" { } ######################################################################################################################## -# Add-ons +# OpenShift cluster integrated with other services ######################################################################################################################## -module "ocp_cluster_with_add_ons" { +module "openshift_landing_zone" { source = "../../modules/containerized_app_landing_zone" prefix = var.prefix region = var.region @@ -46,7 +46,7 @@ module "ocp_cluster_with_add_ons" { } data "ibm_container_cluster_config" "cluster_config" { - cluster_name_id = module.ocp_cluster_with_add_ons.cluster_id + cluster_name_id = module.openshift_landing_zone.cluster_id resource_group_id = module.resource_group.resource_group_id config_dir = "${path.module}/../../kubeconfig" } @@ -58,10 +58,10 @@ data "ibm_container_cluster_config" "cluster_config" { module "monitoring_agent" { source = "terraform-ibm-modules/monitoring-agent/ibm" version = "1.19.0" - cluster_id = module.ocp_cluster_with_add_ons.cluster_id + cluster_id = module.openshift_landing_zone.cluster_id cluster_resource_group_id = module.resource_group.resource_group_id is_vpc_cluster = true - access_key = module.ocp_cluster_with_add_ons.cloud_monitoring_access_key + access_key = module.openshift_landing_zone.cloud_monitoring_access_key instance_region = var.region metrics_filter = [{ exclude = "metricA.*" }, { include = "metricB.*" }] container_filter = [{ type = "exclude", parameter = "kubernetes.namespace.name", name = "kube-system" }] @@ -84,7 +84,6 @@ module "trusted_profile" { version = "3.2.0" trusted_profile_name = "${var.prefix}-profile" trusted_profile_description = "Logs agent Trusted Profile" - # As a `Sender`, you can send logs to your IBM Cloud Logs service instance - but not query or tail logs. This role is meant to be used by agent and routers sending logs. trusted_profile_policies = [{ roles = ["Sender"] unique_identifier = "logs-agent" @@ -92,12 +91,11 @@ module "trusted_profile" { service = "logs" }] }] - # Set up fine-grained authorization for `logs-agent` running in ROKS cluster in `ibm-observe` namespace. trusted_profile_links = [{ cr_type = "ROKS_SA" unique_identifier = "logs-agent-link" links = [{ - crn = module.ocp_cluster_with_add_ons.cluster_crn + crn = module.openshift_landing_zone.cluster_crn namespace = local.logs_agent_namespace name = local.logs_agent_name }] @@ -106,20 +104,18 @@ module "trusted_profile" { } module "logs_agent" { - source = "terraform-ibm-modules/logs-agent/ibm" - version = "1.10.0" - cluster_id = module.ocp_cluster_with_add_ons.cluster_id - cluster_resource_group_id = module.resource_group.resource_group_id - # Logs agent + source = "terraform-ibm-modules/logs-agent/ibm" + version = "1.10.0" + cluster_id = module.openshift_landing_zone.cluster_id + cluster_resource_group_id = module.resource_group.resource_group_id logs_agent_trusted_profile_id = module.trusted_profile.trusted_profile.id logs_agent_namespace = local.logs_agent_namespace logs_agent_name = local.logs_agent_name - cloud_logs_ingress_endpoint = module.ocp_cluster_with_add_ons.cloud_logs_ingress_private_endpoint + cloud_logs_ingress_endpoint = module.openshift_landing_zone.cloud_logs_ingress_private_endpoint cloud_logs_ingress_port = 3443 - # example of how to add additional metadata to the logs agent logs_agent_additional_metadata = [{ key = "cluster_id" - value = module.ocp_cluster_with_add_ons.cluster_id + value = module.openshift_landing_zone.cluster_id }] logs_agent_resources = { limits = { @@ -131,6 +127,5 @@ module "logs_agent" { memory = "1Gi" } } - # example of how to add additional log source path logs_agent_system_logs = ["/logs/*.log"] } diff --git a/examples/containerized_app_landing_zone/outputs.tf b/examples/containerized_app_landing_zone/outputs.tf index ebdf3b8c5..73b78fee3 100644 --- a/examples/containerized_app_landing_zone/outputs.tf +++ b/examples/containerized_app_landing_zone/outputs.tf @@ -9,17 +9,17 @@ output "vpc_name" { description = "Name of the VPC created." - value = module.ocp_cluster_with_add_ons.vpc_name + value = module.openshift_landing_zone.vpc_name } output "vpc_id" { description = "ID of the VPC created." - value = module.ocp_cluster_with_add_ons.vpc_id + value = module.openshift_landing_zone.vpc_id } output "vpc_crn" { description = "CRN of the VPC created." - value = module.ocp_cluster_with_add_ons.vpc_crn + value = module.openshift_landing_zone.vpc_crn } ############################################################################## @@ -28,7 +28,7 @@ output "vpc_crn" { output "public_gateways" { description = "Map of the public gateways by zone." - value = module.ocp_cluster_with_add_ons.public_gateways + value = module.openshift_landing_zone.public_gateways } ############################################################################## @@ -37,7 +37,7 @@ output "public_gateways" { output "vpc_flow_logs" { description = "Details of the VPC flow logs collector." - value = module.ocp_cluster_with_add_ons.vpc_flow_logs + value = module.openshift_landing_zone.vpc_flow_logs } ############################################################################## @@ -46,7 +46,7 @@ output "vpc_flow_logs" { output "network_acls" { description = "List of shortnames and IDs of network ACLs." - value = module.ocp_cluster_with_add_ons.network_acls + value = module.openshift_landing_zone.network_acls } ############################################################################## @@ -55,27 +55,27 @@ output "network_acls" { output "subnet_ids" { description = "The IDs of the subnets." - value = module.ocp_cluster_with_add_ons.subnet_ids + value = module.openshift_landing_zone.subnet_ids } output "private_path_subnet_id" { description = "The IDs of the subnets." - value = length(module.ocp_cluster_with_add_ons.subnet_ids) > 0 ? module.ocp_cluster_with_add_ons.subnet_ids[0] : null + value = length(module.openshift_landing_zone.subnet_ids) > 0 ? module.openshift_landing_zone.subnet_ids[0] : null } output "subnet_detail_list" { description = "A list of subnets containing names, CIDR blocks, and zones." - value = module.ocp_cluster_with_add_ons.subnet_detail_list + value = module.openshift_landing_zone.subnet_detail_list } output "subnet_zone_list" { description = "A list of subnet IDs and subnet zones." - value = module.ocp_cluster_with_add_ons.subnet_zone_list + value = module.openshift_landing_zone.subnet_zone_list } output "subnet_detail_map" { description = "A map of subnets containing IDs, CIDR blocks, and zones." - value = module.ocp_cluster_with_add_ons.subnet_detail_map + value = module.openshift_landing_zone.subnet_detail_map } ############################################################################## @@ -84,12 +84,12 @@ output "subnet_detail_map" { output "vpn_gateways_name" { description = "List of names of VPN gateways." - value = module.ocp_cluster_with_add_ons.vpn_gateways_name + value = module.openshift_landing_zone.vpn_gateways_name } output "vpn_gateways_data" { description = "Details of VPN gateways data." - value = module.ocp_cluster_with_add_ons.vpn_gateways_data + value = module.openshift_landing_zone.vpn_gateways_data } ############################################################################## @@ -98,12 +98,12 @@ output "vpn_gateways_data" { output "vpe_ips" { description = "The reserved IPs for endpoint gateways." - value = module.ocp_cluster_with_add_ons.vpe_ips + value = module.openshift_landing_zone.vpe_ips } output "vpe_crn" { description = "The CRN of the endpoint gateway." - value = module.ocp_cluster_with_add_ons.vpe_crn + value = module.openshift_landing_zone.vpe_crn } ############################################################################## @@ -112,21 +112,21 @@ output "vpe_crn" { output "kms_guid" { description = "Key Protect instance GUID or the KMS instance GUID if existing_kms_instance_crn was set" - value = module.ocp_cluster_with_add_ons.kms_guid + value = module.openshift_landing_zone.kms_guid } output "kms_account_id" { description = "The account ID of the KMS instance." - value = module.ocp_cluster_with_add_ons.kms_account_id + value = module.openshift_landing_zone.kms_account_id } output "key_protect_id" { description = "Key Protect instance ID when an instance is created, otherwise null" - value = module.ocp_cluster_with_add_ons.key_protect_id + value = module.openshift_landing_zone.key_protect_id } output "kms_instance_crn" { - value = module.ocp_cluster_with_add_ons.kms_instance_crn + value = module.openshift_landing_zone.kms_instance_crn description = "The CRN of the Hyper Protect Crypto Service instance or Key Protect instance" } @@ -136,12 +136,12 @@ output "kms_instance_crn" { output "en_crn" { description = "Event Notification crn" - value = module.ocp_cluster_with_add_ons.en_crn + value = module.openshift_landing_zone.en_crn } output "en_guid" { description = "Event Notification guid" - value = module.ocp_cluster_with_add_ons.en_guid + value = module.openshift_landing_zone.en_guid } ############################################################################## @@ -150,16 +150,16 @@ output "en_guid" { output "secrets_manager_guid" { description = "GUID of Secrets Manager instance" - value = module.ocp_cluster_with_add_ons.secrets_manager_guid + value = module.openshift_landing_zone.secrets_manager_guid } output "secrets_manager_crn" { - value = module.ocp_cluster_with_add_ons.secrets_manager_crn + value = module.openshift_landing_zone.secrets_manager_crn description = "CRN of the Secrets Manager instance" } output "secrets_manager_region" { - value = module.ocp_cluster_with_add_ons.secrets_manager_region + value = module.openshift_landing_zone.secrets_manager_region description = "Region of the Secrets Manager instance" } @@ -169,12 +169,12 @@ output "secrets_manager_region" { output "cos_instance_crn" { description = "COS instance crn" - value = module.ocp_cluster_with_add_ons.cos_instance_crn + value = module.openshift_landing_zone.cos_instance_crn } output "cos_instance_guid" { description = "COS instance guid" - value = module.ocp_cluster_with_add_ons.cos_instance_guid + value = module.openshift_landing_zone.cos_instance_guid } ############################################################################## @@ -182,26 +182,26 @@ output "cos_instance_guid" { ############################################################################## output "cloud_monitoring_crn" { - value = module.ocp_cluster_with_add_ons.cloud_monitoring_crn + value = module.openshift_landing_zone.cloud_monitoring_crn description = "The id of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_name" { - value = module.ocp_cluster_with_add_ons.cloud_monitoring_name + value = module.openshift_landing_zone.cloud_monitoring_name description = "The name of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_guid" { - value = module.ocp_cluster_with_add_ons.cloud_monitoring_guid + value = module.openshift_landing_zone.cloud_monitoring_guid description = "The guid of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_access_key_name" { - value = module.ocp_cluster_with_add_ons.cloud_monitoring_access_key_name + value = module.openshift_landing_zone.cloud_monitoring_access_key_name description = "The name of the IBM Cloud Monitoring access key for agents to use" } output "cloud_monitoring_access_key" { - value = module.ocp_cluster_with_add_ons.cloud_monitoring_access_key + value = module.openshift_landing_zone.cloud_monitoring_access_key description = "The IBM Cloud Monitoring access key for agents to use" sensitive = true } @@ -211,28 +211,28 @@ output "cloud_monitoring_access_key" { ############################################################################## output "cloud_logs_crn" { - value = module.ocp_cluster_with_add_ons.cloud_logs_crn + value = module.openshift_landing_zone.cloud_logs_crn description = "The id of the provisioned IBM Cloud Logs instance." } output "cloud_logs_guid" { - value = module.ocp_cluster_with_add_ons.cloud_logs_guid + value = module.openshift_landing_zone.cloud_logs_guid description = "The guid of the provisioned IBM Cloud Logs instance." } output "cloud_logs_name" { - value = module.ocp_cluster_with_add_ons.cloud_logs_name + value = module.openshift_landing_zone.cloud_logs_name description = "The name of the provisioned IBM Cloud Logs instance." } output "logs_bucket_crn" { description = "Logs Cloud Object Storage bucket CRN" - value = module.ocp_cluster_with_add_ons.logs_bucket_crn + value = module.openshift_landing_zone.logs_bucket_crn } output "metrics_bucket_crn" { description = "Metrics Cloud Object Storage bucket CRN" - value = module.ocp_cluster_with_add_ons.metrics_bucket_crn + value = module.openshift_landing_zone.metrics_bucket_crn } ############################################################################## @@ -240,17 +240,17 @@ output "metrics_bucket_crn" { ############################################################################## output "activity_tracker_cos_target_bucket_name" { - value = module.ocp_cluster_with_add_ons.activity_tracker_cos_target_bucket_name + value = module.openshift_landing_zone.activity_tracker_cos_target_bucket_name description = "he name of the object storage bucket which is set as activity tracker event routing target to collect audit events." } output "activity_tracker_targets" { - value = module.ocp_cluster_with_add_ons.activity_tracker_targets + value = module.openshift_landing_zone.activity_tracker_targets description = "The map of created Activity Tracker Event Routing targets" } output "activity_tracker_routes" { - value = module.ocp_cluster_with_add_ons.activity_tracker_routes + value = module.openshift_landing_zone.activity_tracker_routes description = "The map of created Activity Tracker Event Routing routes" } @@ -260,17 +260,17 @@ output "activity_tracker_routes" { output "scc_workload_protection_id" { description = "SCC Workload Protection instance ID" - value = module.ocp_cluster_with_add_ons.scc_workload_protection_id + value = module.openshift_landing_zone.scc_workload_protection_id } output "scc_workload_protection_crn" { description = "SCC Workload Protection instance CRN" - value = module.ocp_cluster_with_add_ons.scc_workload_protection_crn + value = module.openshift_landing_zone.scc_workload_protection_crn } output "scc_workload_protection_name" { description = "SCC Workload Protection instance name" - value = module.ocp_cluster_with_add_ons.scc_workload_protection_name + value = module.openshift_landing_zone.scc_workload_protection_name } ############################################################################## @@ -278,26 +278,26 @@ output "scc_workload_protection_name" { ############################################################################## output "cluster_name" { - value = module.ocp_cluster_with_add_ons.cluster_name + value = module.openshift_landing_zone.cluster_name description = "The name of the provisioned OpenShift cluster." } output "cluster_id" { - value = module.ocp_cluster_with_add_ons.cluster_id + value = module.openshift_landing_zone.cluster_id description = "The unique identifier assigned to the provisioned OpenShift cluster." } output "cluster_crn" { description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." - value = module.ocp_cluster_with_add_ons.cluster_crn + value = module.openshift_landing_zone.cluster_crn } output "workerpools" { description = "A list of worker pools associated with the provisioned cluster" - value = module.ocp_cluster_with_add_ons.workerpools + value = module.openshift_landing_zone.workerpools } output "ocp_version" { description = "The version of OpenShift running on the provisioned cluster." - value = module.ocp_cluster_with_add_ons.ocp_version + value = module.openshift_landing_zone.ocp_version } diff --git a/modules/containerized_app_landing_zone/README.md b/modules/containerized_app_landing_zone/README.md index c5177d1d9..119b542cf 100644 --- a/modules/containerized_app_landing_zone/README.md +++ b/modules/containerized_app_landing_zone/README.md @@ -26,7 +26,7 @@ The primary goal of this module is to provision an OpenShift cluster on VPC and ## Usage ```hcl -module "monolith_ocp_add_ons" { +module "openshift_landing_zone" { source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/containerized_app_landing_zone" version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release prefix = "" diff --git a/tests/other_test.go b/tests/other_test.go index a3500215f..45b8cd6ab 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -17,7 +17,7 @@ const advancedExampleDir = "examples/advanced" const basicExampleDir = "examples/basic" const fscloudExampleDir = "examples/fscloud" const crossKmsSupportExampleDir = "examples/cross_kms_support" -const monolithExampleDir = "examples/containerized_app_landing_zone" +const openshiftLandingZoneExampleDir = "examples/containerized_app_landing_zone" func setupOptions(t *testing.T, prefix string, terraformDir string, ocpVersion string) *testhelper.TestOptions { options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ @@ -194,7 +194,7 @@ func TestFSCloudInSchematic(t *testing.T) { assert.Nil(t, err, "This should not have errored") } -func TestMonolithExample(t *testing.T) { +func TestOpenshiftLandingZoneExample(t *testing.T) { t.Parallel() options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ @@ -202,7 +202,7 @@ func TestMonolithExample(t *testing.T) { Prefix: "mon-ocp", TarIncludePatterns: []string{ "*.tf", - monolithExampleDir + "/*.tf", + openshiftLandingZoneExampleDir + "/*.tf", fullyConfigurableTerraformDir + "/scripts/*.*", "/scripts/*.*", "kubeconfig/*.*", @@ -214,13 +214,13 @@ func TestMonolithExample(t *testing.T) { "modules/kube-audit/helm-charts/kube-audit/templates/*.*", "modules/containerized_app_landing_zone/*.tf", }, - TemplateFolder: monolithExampleDir, - Tags: []string{"monolith-base-ocp-test"}, + TemplateFolder: openshiftLandingZoneExampleDir, + Tags: []string{"openshift-landing-zone-test"}, DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 240, IgnoreAdds: testhelper.Exemptions{ List: []string{ - "module.ocp_cluster_with_add_ons.module.scc_wp.restapi_object.cspm", + "module.openshift_landing_zone.module.scc_wp.restapi_object.cspm", }, }, IgnoreUpdates: testhelper.Exemptions{ @@ -230,7 +230,7 @@ func TestMonolithExample(t *testing.T) { "module.monitoring_agent.helm_release.cloud_monitoring_agent", // Have to ignore account settings as other tests may be updating them concurrently // which can cause consistency test to fail if not ignored. - "module.ocp_cluster_with_add_ons.module.metrics_routing[0].ibm_metrics_router_settings.metrics_router_settings[0]", + "module.openshift_landing_zone.module.metrics_routing[0].ibm_metrics_router_settings.metrics_router_settings[0]", }, }, }) From 8c2241e005798e2ba3bf6c53fb21315f6432a218 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Fri, 12 Dec 2025 21:43:53 +0530 Subject: [PATCH 12/15] README changes --- .../containerized_app_landing_zone/README.md | 3 +- .../containerized_app_landing_zone/outputs.tf | 81 +++++++++---------- .../variables.tf | 4 +- .../containerized_app_landing_zone/README.md | 25 +++--- .../containerized_app_landing_zone/outputs.tf | 80 ++++++++---------- .../variables.tf | 2 +- tests/other_test.go | 2 +- 7 files changed, 90 insertions(+), 107 deletions(-) diff --git a/examples/containerized_app_landing_zone/README.md b/examples/containerized_app_landing_zone/README.md index c214fe91b..2d910b98a 100644 --- a/examples/containerized_app_landing_zone/README.md +++ b/examples/containerized_app_landing_zone/README.md @@ -2,8 +2,9 @@ A simple example that shows how to provision a multi zone OCP VPC cluster as well as all foundational infrastructure and supporting services required for a secure and compliant OpenShift (OCP) cluster deployment on IBM Cloud VPC. -* Refer [here](../../modules/containerized_app_landing_zone/README.md) to check all the resources that are provisioned by this example by calling the `containerized_app_landing_zone` module. +The following resources are provisioned by this example: * A new resource group if an existing resource group is not passed. * Monitoring agent. * A Trusted Profile with Sender role to logs service. * Logs agent. +* All the resources that are provisioned by calling the `containerized_app_landing_zone` module can be referred [here](../../modules/containerized_app_landing_zone/README.md). diff --git a/examples/containerized_app_landing_zone/outputs.tf b/examples/containerized_app_landing_zone/outputs.tf index 73b78fee3..48c60d019 100644 --- a/examples/containerized_app_landing_zone/outputs.tf +++ b/examples/containerized_app_landing_zone/outputs.tf @@ -1,6 +1,31 @@ -######################################################################################################################## -# Outputs -######################################################################################################################## +############################################################################## +# Cluster Outputs +############################################################################## + +output "cluster_name" { + value = module.openshift_landing_zone.cluster_name + description = "The name of the provisioned OpenShift cluster." +} + +output "cluster_id" { + value = module.openshift_landing_zone.cluster_id + description = "The unique identifier assigned to the provisioned OpenShift cluster." +} + +output "cluster_crn" { + description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." + value = module.openshift_landing_zone.cluster_crn +} + +output "workerpools" { + description = "A list of worker pools associated with the provisioned cluster" + value = module.openshift_landing_zone.workerpools +} + +output "ocp_version" { + description = "The version of OpenShift running on the provisioned cluster." + value = module.openshift_landing_zone.ocp_version +} ############################################################################## @@ -111,7 +136,7 @@ output "vpe_crn" { ############################################################################## output "kms_guid" { - description = "Key Protect instance GUID or the KMS instance GUID if existing_kms_instance_crn was set" + description = "KMS instance GUID" value = module.openshift_landing_zone.kms_guid } @@ -120,32 +145,27 @@ output "kms_account_id" { value = module.openshift_landing_zone.kms_account_id } -output "key_protect_id" { - description = "Key Protect instance ID when an instance is created, otherwise null" - value = module.openshift_landing_zone.key_protect_id -} - output "kms_instance_crn" { value = module.openshift_landing_zone.kms_instance_crn - description = "The CRN of the Hyper Protect Crypto Service instance or Key Protect instance" + description = "The CRN of the KMS instance" } ############################################################################## -# EN Outputs +# Events Notification Outputs ############################################################################## -output "en_crn" { +output "events_notification_crn" { description = "Event Notification crn" - value = module.openshift_landing_zone.en_crn + value = module.openshift_landing_zone.events_notification_crn } -output "en_guid" { +output "events_notification_guid" { description = "Event Notification guid" - value = module.openshift_landing_zone.en_guid + value = module.openshift_landing_zone.events_notification_guid } ############################################################################## -# SM Outputs +# Secrets Manager Outputs ############################################################################## output "secrets_manager_guid" { @@ -272,32 +292,3 @@ output "scc_workload_protection_name" { description = "SCC Workload Protection instance name" value = module.openshift_landing_zone.scc_workload_protection_name } - -############################################################################## -# Cluster Outputs -############################################################################## - -output "cluster_name" { - value = module.openshift_landing_zone.cluster_name - description = "The name of the provisioned OpenShift cluster." -} - -output "cluster_id" { - value = module.openshift_landing_zone.cluster_id - description = "The unique identifier assigned to the provisioned OpenShift cluster." -} - -output "cluster_crn" { - description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." - value = module.openshift_landing_zone.cluster_crn -} - -output "workerpools" { - description = "A list of worker pools associated with the provisioned cluster" - value = module.openshift_landing_zone.workerpools -} - -output "ocp_version" { - description = "The version of OpenShift running on the provisioned cluster." - value = module.openshift_landing_zone.ocp_version -} diff --git a/examples/containerized_app_landing_zone/variables.tf b/examples/containerized_app_landing_zone/variables.tf index dd24ca953..1e9483155 100644 --- a/examples/containerized_app_landing_zone/variables.tf +++ b/examples/containerized_app_landing_zone/variables.tf @@ -11,7 +11,7 @@ variable "ibmcloud_api_key" { variable "prefix" { type = string description = "Prefix for name of all resource created by this example" - default = "mon-eg" + default = "ocp-lz" validation { error_message = "Prefix must begin and end with a letter and contain only letters, numbers, and - characters." condition = can(regex("^([A-z]|[a-z][-a-z0-9]*[a-z0-9])$", var.prefix)) @@ -49,7 +49,7 @@ variable "existing_event_notifications_instance_crn" { variable "existing_kms_instance_crn" { type = string default = null - description = "The CRN of an existing KMS instance (Hyper Protect Crypto Services or Key Protect)." + description = "The CRN of an existing KMS instance." validation { condition = anytrue([ diff --git a/modules/containerized_app_landing_zone/README.md b/modules/containerized_app_landing_zone/README.md index 119b542cf..51649818b 100644 --- a/modules/containerized_app_landing_zone/README.md +++ b/modules/containerized_app_landing_zone/README.md @@ -1,8 +1,12 @@ # Landing zone for containerized applications with OpenShift -This module provides a plain vanilla terraform implementation of the secure landing zone architecture- a production-grade Red Hat OpenShift platform on IBM Cloud VPC by providing a fully integrated ecosystem out of the box. Rather than just provisioning compute resources, it orchestrates the critical "operational glue" required for enterprise workloads—automatically wiring together Key Management, Secrets Manager, Cloud Logs, and Cloud Monitoring. This comprehensive approach reduces operational overhead and eliminates manual configuration errors, ensuring your environment is secure, observable, and ready. +This module provides a **terraform implementation** of the secure landing zone architecture - a production-grade Red Hat OpenShift platform on IBM Cloud VPC by providing a fully integrated ecosystem. Rather than just provisioning compute resources, it orchestrates the critical **operational glue** required for enterprise workloads—automatically wiring together **Key Management**, **Secrets Manager**, **Cloud Logs**, **Cloud Monitoring**, **Cloud Object Storage** and **Events Notification**. This comprehensive approach reduces operational overhead and eliminates manual configuration errors, ensuring your environment is secure, observable, and ready. -Secure, Compliant, and Scalable Designed to support a wide range of business needs—from rapid sandbox experimentation to highly regulated financial services deployments—the architecture is secure by design and fully configurable. It incorporates robust compliance features, such as SCC Workload Protection and automated audit logging, while allowing you to tailor specific integrations and worker pools to your requirements. This flexibility enables organizations to standardize on a single, reliable architectural pattern that streamlines security approvals and scales effortlessly with business demand. +Secure, Compliant, and Scalable Designed to support a wide range of business needs, the architecture is secure by design and fully configurable. It incorporates robust compliance features, such as **SCC Workload Protection**, while allowing you to tailor specific integrations and worker pools to your requirements. This flexibility enables organizations to standardize on a single, reliable architectural pattern that streamlines security approvals and scales effortlessly with business demand. + +### Reference Architecture + +![Architecture Diagram](../../reference-architectures/deployable-architecture-ocp-cluster.svg) ### Components @@ -19,22 +23,19 @@ The primary goal of this module is to provision an OpenShift cluster on VPC and * `App Configuration`: Optional provision and configuration of IBM Cloud App Configuration for centralized feature flag and property management, securely integrated with KMS and Event Notifications. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/app-configuration/ibm/1.14.2) about the service module. * `Context-Based Restrictions (CBR)`: Optional support for defining and attaching network access rules (CBR zones and rules) to all supported services (KMS, COS, Secrets Manager) to enforce zero-trust networking. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/cbr/ibm/1.34.0) about the service module. -### Reference Architecture - -![Architecture Diagram](../../reference-architectures/deployable-architecture-ocp-cluster.svg) - ## Usage ```hcl module "openshift_landing_zone" { - source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/containerized_app_landing_zone" - version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release - prefix = "" - region = "us-south" - resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" + source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/containerized_app_landing_zone" + version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release + prefix = "" + ibmcloud_api_key = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" + region = "us-south" + resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" } ``` -To run this module refer to the example [here](../../examples/containerized_app_landing_zone) +To run this module refer to the code [here](../../examples/containerized_app_landing_zone) ### Requirements diff --git a/modules/containerized_app_landing_zone/outputs.tf b/modules/containerized_app_landing_zone/outputs.tf index 26efb70d2..a2009339b 100644 --- a/modules/containerized_app_landing_zone/outputs.tf +++ b/modules/containerized_app_landing_zone/outputs.tf @@ -1,3 +1,32 @@ +############################################################################## +# Cluster Outputs +############################################################################## + +output "cluster_name" { + value = module.ocp_base.cluster_name + description = "The name of the provisioned OpenShift cluster." +} + +output "cluster_id" { + value = module.ocp_base.cluster_id + description = "The unique identifier assigned to the provisioned OpenShift cluster." +} + +output "cluster_crn" { + description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." + value = module.ocp_base.cluster_crn +} + +output "workerpools" { + description = "A list of worker pools associated with the provisioned cluster" + value = module.ocp_base.workerpools +} + +output "ocp_version" { + description = "The version of OpenShift running on the provisioned cluster." + value = module.ocp_base.ocp_version +} + ############################################################################## # VPC ############################################################################## @@ -106,7 +135,7 @@ output "vpe_crn" { ############################################################################## output "kms_guid" { - description = "Key Protect instance GUID or the KMS instance GUID if existing_kms_instance_crn was set" + description = "KMS instance GUID" value = local.cluster_existing_kms_guid } @@ -115,38 +144,28 @@ output "kms_account_id" { value = local.cluster_kms_account_id } -output "key_protect_id" { - description = "Key Protect instance ID when an instance is created, otherwise null" - value = local.cluster_kms_key_id -} - output "kms_instance_crn" { value = var.existing_kms_instance_crn == null ? var.kms_encryption_enabled_cluster ? module.kms[0].key_protect_crn : null : var.existing_kms_instance_crn - description = "The CRN of the Hyper Protect Crypto Service instance or Key Protect instance" -} - -output "kms_config" { - description = "The KMS config needed for OCP cluster" - value = local.kms_config + description = "The CRN of the KMS instance" } ############################################################################## -# EN Outputs +# Events Notification Outputs ############################################################################## -output "en_crn" { +output "events_notification_crn" { description = "Event Notification crn" value = local.eventnotification_crn } -output "en_guid" { +output "events_notification_guid" { description = "Event Notification guid" value = local.eventnotification_guid } ############################################################################## -# SM Outputs +# Secrets Manager Outputs ############################################################################## output "secrets_manager_guid" { @@ -305,32 +324,3 @@ output "scc_workload_protection_api_endpoint" { value = module.scc_wp.api_endpoint sensitive = true } - -############################################################################## -# Cluster Outputs -############################################################################## - -output "cluster_name" { - value = module.ocp_base.cluster_name - description = "The name of the provisioned OpenShift cluster." -} - -output "cluster_id" { - value = module.ocp_base.cluster_id - description = "The unique identifier assigned to the provisioned OpenShift cluster." -} - -output "cluster_crn" { - description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." - value = module.ocp_base.cluster_crn -} - -output "workerpools" { - description = "A list of worker pools associated with the provisioned cluster" - value = module.ocp_base.workerpools -} - -output "ocp_version" { - description = "The version of OpenShift running on the provisioned cluster." - value = module.ocp_base.ocp_version -} diff --git a/modules/containerized_app_landing_zone/variables.tf b/modules/containerized_app_landing_zone/variables.tf index 55478ed52..3d3008d71 100644 --- a/modules/containerized_app_landing_zone/variables.tf +++ b/modules/containerized_app_landing_zone/variables.tf @@ -76,7 +76,7 @@ variable "kms_encryption_enabled_cluster" { variable "existing_kms_instance_crn" { type = string default = null - description = "The CRN of an existing KMS instance (Hyper Protect Crypto Services or Key Protect)." + description = "The CRN of an existing KMS instance." validation { condition = anytrue([ diff --git a/tests/other_test.go b/tests/other_test.go index 45b8cd6ab..1fa0b7dc6 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -199,7 +199,7 @@ func TestOpenshiftLandingZoneExample(t *testing.T) { options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ Testing: t, - Prefix: "mon-ocp", + Prefix: "ocp-lz", TarIncludePatterns: []string{ "*.tf", openshiftLandingZoneExampleDir + "/*.tf", From b104239e2be8a0785d5687e809778319406e0633 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Fri, 12 Dec 2025 22:31:44 +0530 Subject: [PATCH 13/15] pre-commit changes --- common-dev-assets | 2 +- modules/containerized_app_landing_zone/README.md | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/common-dev-assets b/common-dev-assets index 0424afd3c..99dc77722 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit 0424afd3c435499ed3f0130f8cf6afb7ab36140d +Subproject commit 99dc77722bfa0a104d19511fd097af2fe0356db2 diff --git a/modules/containerized_app_landing_zone/README.md b/modules/containerized_app_landing_zone/README.md index 51649818b..dd522ca7f 100644 --- a/modules/containerized_app_landing_zone/README.md +++ b/modules/containerized_app_landing_zone/README.md @@ -30,7 +30,7 @@ module "openshift_landing_zone" { source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/containerized_app_landing_zone" version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release prefix = "" - ibmcloud_api_key = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" + ibmcloud_api_key = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" # pragma: allowlist secret region = "us-south" resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" } @@ -210,7 +210,7 @@ To run this module refer to the code [here](../../examples/containerized_app_lan | [existing\_cos\_instance\_crn](#input\_existing\_cos\_instance\_crn) | The CRN of an existing Object Storage instance. | `string` | `null` | no | | [existing\_event\_notifications\_instance\_crn](#input\_existing\_event\_notifications\_instance\_crn) | The CRN of the Event Notifications service used to enable lifecycle notifications for your Secrets Manager instance. | `string` | `null` | no | | [existing\_event\_notifications\_instances](#input\_existing\_event\_notifications\_instances) | List of Event Notifications instance details for routing critical events that occur in your IBM Cloud Logs. |
list(object({
crn = string
integration_name = optional(string)
skip_iam_auth_policy = optional(bool, false)
}))
| `[]` | no | -| [existing\_kms\_instance\_crn](#input\_existing\_kms\_instance\_crn) | The CRN of an existing KMS instance (Hyper Protect Crypto Services or Key Protect). | `string` | `null` | no | +| [existing\_kms\_instance\_crn](#input\_existing\_kms\_instance\_crn) | The CRN of an existing KMS instance. | `string` | `null` | no | | [existing\_secrets\_manager\_crn](#input\_existing\_secrets\_manager\_crn) | The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created. | `string` | `null` | no | | [flow\_logs\_cos\_bucket\_archive\_days](#input\_flow\_logs\_cos\_bucket\_archive\_days) | The number of days before the `archive_type` rule action takes effect for the flow logs cloud object storage bucket. | `number` | `90` | no | | [flow\_logs\_cos\_bucket\_archive\_type](#input\_flow\_logs\_cos\_bucket\_archive\_type) | The storage class or archive type you want the object to transition to in the flow logs cloud object storage bucket. | `string` | `"Glacier"` | no | @@ -326,13 +326,11 @@ To run this module refer to the code [here](../../examples/containerized_app_lan | [cos\_instance\_crn](#output\_cos\_instance\_crn) | COS instance crn | | [cos\_instance\_guid](#output\_cos\_instance\_guid) | COS instance guid | | [cos\_instance\_id](#output\_cos\_instance\_id) | COS instance ID | -| [en\_crn](#output\_en\_crn) | Event Notification crn | -| [en\_guid](#output\_en\_guid) | Event Notification guid | -| [key\_protect\_id](#output\_key\_protect\_id) | Key Protect instance ID when an instance is created, otherwise null | +| [events\_notification\_crn](#output\_events\_notification\_crn) | Event Notification crn | +| [events\_notification\_guid](#output\_events\_notification\_guid) | Event Notification guid | | [kms\_account\_id](#output\_kms\_account\_id) | The account ID of the KMS instance. | -| [kms\_config](#output\_kms\_config) | The KMS config needed for OCP cluster | -| [kms\_guid](#output\_kms\_guid) | Key Protect instance GUID or the KMS instance GUID if existing\_kms\_instance\_crn was set | -| [kms\_instance\_crn](#output\_kms\_instance\_crn) | The CRN of the Hyper Protect Crypto Service instance or Key Protect instance | +| [kms\_guid](#output\_kms\_guid) | KMS instance GUID | +| [kms\_instance\_crn](#output\_kms\_instance\_crn) | The CRN of the KMS instance | | [logs\_bucket\_crn](#output\_logs\_bucket\_crn) | Logs Cloud Object Storage bucket CRN | | [metrics\_bucket\_crn](#output\_metrics\_bucket\_crn) | Metrics Cloud Object Storage bucket CRN | | [network\_acls](#output\_network\_acls) | List of shortnames and IDs of network ACLs. | From 7cf500eb8ef271869b94d5647e79b2c98ebf16e1 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Thu, 18 Dec 2025 13:54:20 +0530 Subject: [PATCH 14/15] remove monolith submodule --- README.md | 1 - .../containerized_app_landing_zone/README.md | 361 --- .../containerized_app_landing_zone/main.tf | 1072 -------- .../containerized_app_landing_zone/outputs.tf | 326 --- .../variables.tf | 2352 ----------------- .../containerized_app_landing_zone/version.tf | 13 - 6 files changed, 4125 deletions(-) delete mode 100644 modules/containerized_app_landing_zone/README.md delete mode 100644 modules/containerized_app_landing_zone/main.tf delete mode 100644 modules/containerized_app_landing_zone/outputs.tf delete mode 100644 modules/containerized_app_landing_zone/variables.tf delete mode 100644 modules/containerized_app_landing_zone/version.tf diff --git a/README.md b/README.md index c5ba2cb36..6c0d2ae45 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ By default, the module automatically downloads the required dependencies if they ## Overview * [terraform-ibm-base-ocp-vpc](#terraform-ibm-base-ocp-vpc) * [Submodules](./modules) - * [containerized_app_landing_zone](./modules/containerized_app_landing_zone) * [fscloud](./modules/fscloud) * [kube-audit](./modules/kube-audit) * [worker-pool](./modules/worker-pool) diff --git a/modules/containerized_app_landing_zone/README.md b/modules/containerized_app_landing_zone/README.md deleted file mode 100644 index dd522ca7f..000000000 --- a/modules/containerized_app_landing_zone/README.md +++ /dev/null @@ -1,361 +0,0 @@ -# Landing zone for containerized applications with OpenShift - -This module provides a **terraform implementation** of the secure landing zone architecture - a production-grade Red Hat OpenShift platform on IBM Cloud VPC by providing a fully integrated ecosystem. Rather than just provisioning compute resources, it orchestrates the critical **operational glue** required for enterprise workloads—automatically wiring together **Key Management**, **Secrets Manager**, **Cloud Logs**, **Cloud Monitoring**, **Cloud Object Storage** and **Events Notification**. This comprehensive approach reduces operational overhead and eliminates manual configuration errors, ensuring your environment is secure, observable, and ready. - -Secure, Compliant, and Scalable Designed to support a wide range of business needs, the architecture is secure by design and fully configurable. It incorporates robust compliance features, such as **SCC Workload Protection**, while allowing you to tailor specific integrations and worker pools to your requirements. This flexibility enables organizations to standardize on a single, reliable architectural pattern that streamlines security approvals and scales effortlessly with business demand. - -### Reference Architecture - -![Architecture Diagram](../../reference-architectures/deployable-architecture-ocp-cluster.svg) - -### Components - -The primary goal of this module is to provision an OpenShift cluster on VPC and automatically configure the necessary supporting services, including: -* `VPC Infrastructure`: The base VPC, subnets, and network access controls (ACLs) for the OpenShift cluster. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/landing-zone-vpc/ibm/8.9.1) about the service module. -* `Key Management (KMS)`: Optional provision and configuration of an IBM Key Protect or Hyper Protect Crypto Services (HPCS) instance for encrypting cluster and boot volumes. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/kms-all-inclusive/ibm/5.4.5) about the service module. -* `Secrets Management`: Optional provision and configuration of an IBM Secrets Manager instance to securely store service credentials and other secrets. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/secrets-manager/ibm/2.11.9) about the service module. -* `Cloud Object Storage (COS)`: Optional provision and configuration of COS instances and buckets for flow logs, activity tracker, and other data storage needs. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/cos/ibm/10.5.9) about the service module. -* `Monitoring & Logging`: Optional provision and configuration of IBM Cloud Monitoring and IBM Cloud Logs instances for centralized observability. Learn more about the [Cloud Monitoring](https://registry.terraform.io/modules/terraform-ibm-modules/cloud-monitoring/ibm/1.11.0) and [Cloud Logs](https://registry.terraform.io/modules/terraform-ibm-modules/cloud-logs/ibm/1.10.0) service module. -* `Activity Tracker and Event Routing`: Configure event routing for platform audit logs to a COS bucket or IBM Cloud Logs. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/activity-tracker/ibm/1.5.0) about the service module. -* `Security & Compliance`: Optional integration with IBM Cloud Security and Compliance Center (SCC) Workload Protection. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/scc-workload-protection/ibm/1.16.4) about the service module. -* `VPE Gateways`: Optional configuration of Virtual Private Endpoint (VPE) gateways for secure private connectivity to cloud services. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/vpe-gateway/ibm/4.6.6) about the service module. -* `Event Notifications`: Optional provision and configuration of IBM Cloud Event Notifications for centralized event routing and management, with support for KMS encryption and failed event collection in COS. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/event-notifications/ibm/2.7.0) about the service module. -* `App Configuration`: Optional provision and configuration of IBM Cloud App Configuration for centralized feature flag and property management, securely integrated with KMS and Event Notifications. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/app-configuration/ibm/1.14.2) about the service module. -* `Context-Based Restrictions (CBR)`: Optional support for defining and attaching network access rules (CBR zones and rules) to all supported services (KMS, COS, Secrets Manager) to enforce zero-trust networking. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/cbr/ibm/1.34.0) about the service module. - -## Usage - -```hcl -module "openshift_landing_zone" { - source = "terraform-ibm-modules/base-ocp-vpc/ibm//modules/containerized_app_landing_zone" - version = "X.Y.Z" # Replace "X.Y.Z" with a release version to lock into a specific release - prefix = "" - ibmcloud_api_key = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" # pragma: allowlist secret - region = "us-south" - resource_group_id = "xxXXxxXXxXxXXXXxxXxxxXXXXxXXXXX" -} -``` -To run this module refer to the code [here](../../examples/containerized_app_landing_zone) - - -### Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >=1.9.0 | -| [ibm](#requirement\_ibm) | >= 1.78.2, < 2.0.0 | -| [time](#requirement\_time) | >= 0.9.1, < 1.0.0 | - -### Modules - -| Name | Source | Version | -|------|--------|---------| -| [activity\_tracker](#module\_activity\_tracker) | terraform-ibm-modules/activity-tracker/ibm | 1.5.0 | -| [app\_config](#module\_app\_config) | terraform-ibm-modules/app-configuration/ibm | 1.14.2 | -| [at\_cos\_bucket](#module\_at\_cos\_bucket) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | -| [cloud\_logs](#module\_cloud\_logs) | terraform-ibm-modules/cloud-logs/ibm | 1.10.0 | -| [cloud\_logs\_buckets](#module\_cloud\_logs\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | -| [cloud\_monitoring](#module\_cloud\_monitoring) | terraform-ibm-modules/cloud-monitoring/ibm | 1.11.0 | -| [cos](#module\_cos) | terraform-ibm-modules/cos/ibm//modules/fscloud | 10.5.9 | -| [cos\_secrets\_manager\_service\_credentials](#module\_cos\_secrets\_manager\_service\_credentials) | terraform-ibm-modules/secrets-manager/ibm//modules/secrets | 2.11.9 | -| [en\_cos\_buckets](#module\_en\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | -| [en\_secrets\_manager\_service\_credentials](#module\_en\_secrets\_manager\_service\_credentials) | terraform-ibm-modules/secrets-manager/ibm//modules/secrets | 2.11.9 | -| [event\_notifications](#module\_event\_notifications) | terraform-ibm-modules/event-notifications/ibm | 2.7.0 | -| [existing\_boot\_volume\_kms\_key\_crn\_parser](#module\_existing\_boot\_volume\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_cloud\_monitoring\_crn\_parser](#module\_existing\_cloud\_monitoring\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_cluster\_kms\_key\_crn\_parser](#module\_existing\_cluster\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_cos\_instance\_crn\_parser](#module\_existing\_cos\_instance\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_en\_crn\_parser](#module\_existing\_en\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_kms\_crn\_parser](#module\_existing\_kms\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [existing\_sm\_crn\_parser](#module\_existing\_sm\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [kms](#module\_kms) | terraform-ibm-modules/kms-all-inclusive/ibm | 5.4.5 | -| [metrics\_routing](#module\_metrics\_routing) | terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing | 1.11.0 | -| [ocp\_base](#module\_ocp\_base) | ../.. | n/a | -| [scc\_wp](#module\_scc\_wp) | terraform-ibm-modules/scc-workload-protection/ibm | 1.16.4 | -| [secret\_group](#module\_secret\_group) | terraform-ibm-modules/secrets-manager-secret-group/ibm | 1.3.15 | -| [secrets\_manager](#module\_secrets\_manager) | terraform-ibm-modules/secrets-manager/ibm | 2.11.9 | -| [secrets\_manager\_crn\_parser](#module\_secrets\_manager\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.3.0 | -| [vpc](#module\_vpc) | terraform-ibm-modules/landing-zone-vpc/ibm | 8.9.1 | -| [vpc\_cos\_buckets](#module\_vpc\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | -| [vpe\_gateway](#module\_vpe\_gateway) | terraform-ibm-modules/vpe-gateway/ibm | 4.6.6 | - -### Resources - -| Name | Type | -|------|------| -| [ibm_en_subscription_email.apprapp_email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | -| [ibm_en_subscription_email.en_email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | -| [ibm_en_topic.en_apprapp_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | -| [ibm_en_topic.en_sm_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | -| [ibm_iam_authorization_policy.cos_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | -| [ibm_iam_authorization_policy.en_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | -| [terraform_data.delete_secrets](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | -| [time_sleep.wait_for_cos_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | -| [time_sleep.wait_for_en_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | -| [time_sleep.wait_for_secrets_manager](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | -| [ibm_en_destinations.en_apprapp_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | -| [ibm_en_destinations.en_sm_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | - -### Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [access\_tags](#input\_access\_tags) | A list of access tags to apply to the resources created by the module. | `list(string)` | `[]` | no | -| [activity\_tracker\_cloud\_logs\_route\_name](#input\_activity\_tracker\_cloud\_logs\_route\_name) | Name of the cloud logs route for activity tracker event routing. | `string` | `null` | no | -| [activity\_tracker\_cos\_bucket\_access\_tags](#input\_activity\_tracker\_cos\_bucket\_access\_tags) | A list of optional access tags to add to the IBM Cloud Activity Tracker Event Routing Cloud Object Storage bucket. | `list(string)` | `[]` | no | -| [activity\_tracker\_cos\_bucket\_retention\_policy](#input\_activity\_tracker\_cos\_bucket\_retention\_policy) | The retention policy of the IBM Cloud Activity Tracker Event Routing COS target bucket. |
object({
default = optional(number, 90)
maximum = optional(number, 350)
minimum = optional(number, 90)
permanent = optional(bool, false)
})
| `null` | no | -| [activity\_tracker\_cos\_route\_name](#input\_activity\_tracker\_cos\_route\_name) | Name of the cos route for activity tracker event routing. | `string` | `null` | no | -| [activity\_tracker\_cos\_target\_bucket\_class](#input\_activity\_tracker\_cos\_target\_bucket\_class) | The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`. | `string` | `"smart"` | no | -| [activity\_tracker\_cos\_target\_bucket\_name](#input\_activity\_tracker\_cos\_target\_bucket\_name) | The name of the Cloud Object Storage bucket to create for the Cloud Object Storage target to store AT events. Cloud Object Storage bucket names are globally unique. If the `add_bucket_name_suffix` variable is set to `true`, 4 random characters are added to this name to ensure that the name of the bucket is globally unique. If the prefix input variable is passed, the name of the instance is prefixed to the value in the `-value` format. | `string` | `"at-events-cos-bucket"` | no | -| [additional\_lb\_security\_group\_ids](#input\_additional\_lb\_security\_group\_ids) | List of additional security group IDs to add to the load balancers associated with the cluster. Ensure that the `number_of_lbs` variable is set to the number of Load Balancers associated with the cluster. This comes in addition to the IBM maintained security group. | `list(string)` | `[]` | no | -| [additional\_security\_group\_ids](#input\_additional\_security\_group\_ids) | A list of security group IDs that are attached to the worker nodes for additional network security controls. | `list(string)` | `[]` | no | -| [additional\_vpe\_security\_group\_ids](#input\_additional\_vpe\_security\_group\_ids) | Additional security groups to add to all existing load balancers. This comes in addition to the IBM maintained security group. |
object({
master = optional(list(string), [])
registry = optional(list(string), [])
api = optional(list(string), [])
})
| `{}` | no | -| [additional\_worker\_pools](#input\_additional\_worker\_pools) | List of additional worker pools. |
list(object({
vpc_subnets = optional(list(object({
id = string
zone = string
cidr_block = string
})), [])
pool_name = string
machine_type = string
workers_per_zone = number
operating_system = string
labels = optional(map(string))
minSize = optional(number)
secondary_storage = optional(string)
maxSize = optional(number)
enableAutoscaling = optional(bool)
additional_security_group_ids = optional(list(string))
}))
| `[]` | no | -| [addons](#input\_addons) | Map of OCP cluster add-on versions to install (NOTE: The 'vpc-block-csi-driver' add-on is installed by default for VPC clusters and 'ibm-storage-operator' is installed by default in OCP 4.15 and later, however you can explicitly specify it here if you wish to choose a later version than the default one). [Check supported addons and versions here](https://cloud.ibm.com/docs/containers?topic=containers-supported-cluster-addon-versions). |
object({
debug-tool = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
image-key-synchronizer = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
openshift-data-foundation = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
vpc-file-csi-driver = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
static-route = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
cluster-autoscaler = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
vpc-block-csi-driver = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
ibm-storage-operator = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
openshift-ai = optional(object({
version = optional(string)
parameters_json = optional(string)
}))
})
| `{}` | no | -| [address\_prefixes](#input\_address\_prefixes) | The IP range that will be defined for the VPC for a certain location. Use only with manual address prefixes. |
object({
zone-1 = optional(list(string))
zone-2 = optional(list(string))
zone-3 = optional(list(string))
})
|
{
"zone-1": null,
"zone-2": null,
"zone-3": null
}
| no | -| [allow\_default\_worker\_pool\_replacement](#input\_allow\_default\_worker\_pool\_replacement) | Set to true to allow the module to recreate a default worker pool. Only use in the case where you are getting an error indicating that the default worker pool cannot be replaced on apply. Once the default worker pool is handled separately, if you wish to make any change to the default worker pool which requires the re-creation of the default pool set this variable to true. | `bool` | `false` | no | -| [allow\_outbound\_traffic](#input\_allow\_outbound\_traffic) | Set to true to allow public outbound access from the cluster workers. | `bool` | `true` | no | -| [allow\_public\_access\_to\_cluster\_management](#input\_allow\_public\_access\_to\_cluster\_management) | Set to true to access the cluster through a public cloud service endpoint. | `bool` | `true` | no | -| [app\_config\_collections](#input\_app\_config\_collections) | (Optional, list) A list of collections to be added to the App Configuration instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-app-configuration/tree/main/solutions/fully-configurable/DA-collections.md). |
list(object({
name = string
collection_id = string
description = optional(string, null)
tags = optional(string, null)
}))
| `[]` | no | -| [app\_config\_event\_notifications\_source\_name](#input\_app\_config\_event\_notifications\_source\_name) | The name by which Event Notifications source will be created in the existing Event Notification instance. | `string` | `"app-config-en"` | no | -| [app\_config\_name](#input\_app\_config\_name) | Name for the App Configuration service instance. | `string` | `"app-config"` | no | -| [app\_config\_plan](#input\_app\_config\_plan) | Plan for the App Configuration service instance. | `string` | `"enterprise"` | no | -| [app\_config\_service\_endpoints](#input\_app\_config\_service\_endpoints) | Service Endpoints for the App Configuration service instance, valid endpoints are public or public-and-private. | `string` | `"public-and-private"` | no | -| [app\_config\_tags](#input\_app\_config\_tags) | Optional list of tags to be added to the App Config instance. | `list(string)` | `[]` | no | -| [append\_random\_bucket\_name\_suffix](#input\_append\_random\_bucket\_name\_suffix) | Append random generated suffix (4 characters long) to the newly provisioned IBM Cloud Logs Object Storage bucket names. | `bool` | `true` | no | -| [apprapp\_cbr\_rules](#input\_apprapp\_cbr\_rules) | The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md). |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [attach\_ibm\_managed\_security\_group](#input\_attach\_ibm\_managed\_security\_group) | Specify whether to attach the IBM-defined default security group (whose name is kube-) to all worker nodes. Only applicable if `custom_security_group_ids` is set. | `bool` | `true` | no | -| [boot\_volume\_kms\_key\_name](#input\_boot\_volume\_kms\_key\_name) | The name for the key created for the block storage volumes. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key"` | no | -| [boot\_volume\_kms\_key\_ring\_name](#input\_boot\_volume\_kms\_key\_ring\_name) | The name for the key ring created for the block storage volumes key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"boot-volume-key-ring"` | no | -| [clean\_default\_security\_group\_acl](#input\_clean\_default\_security\_group\_acl) | Remove all rules from the default VPC security group and VPC ACL (less permissive). | `bool` | `true` | no | -| [cloud\_logs\_access\_tags](#input\_cloud\_logs\_access\_tags) | A list of access tags to apply to the IBM Cloud Logs instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | -| [cloud\_logs\_cbr\_rules](#input\_cloud\_logs\_cbr\_rules) | (Optional, list) List of context-based restrictions rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [cloud\_logs\_data\_cos\_bucket\_name](#input\_cloud\_logs\_data\_cos\_bucket\_name) | The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs-logs-bucket"` | no | -| [cloud\_logs\_instance\_name](#input\_cloud\_logs\_instance\_name) | The name of the IBM Cloud Logs instance to create. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs"` | no | -| [cloud\_logs\_metrics\_cos\_bucket\_name](#input\_cloud\_logs\_metrics\_cos\_bucket\_name) | The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cloud-logs-metrics-bucket"` | no | -| [cloud\_logs\_resource\_tags](#input\_cloud\_logs\_resource\_tags) | Tags associated with the IBM Cloud Logs instance (Optional, array of strings). | `list(string)` | `[]` | no | -| [cloud\_logs\_retention\_period](#input\_cloud\_logs\_retention\_period) | The number of days IBM Cloud Logs will retain the logs data in Priority insights. Allowed values: 7, 14, 30, 60, 90. | `number` | `7` | no | -| [cloud\_logs\_target\_name](#input\_cloud\_logs\_target\_name) | Name of the cloud logs target for activity tracker event routing. | `string` | `null` | no | -| [cloud\_monitoring\_access\_tags](#input\_cloud\_monitoring\_access\_tags) | A list of access tags to apply to the IBM Cloud Monitoring instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | -| [cloud\_monitoring\_cbr\_rules](#input\_cloud\_monitoring\_cbr\_rules) | The list of context-based restriction rules to create for the instance. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [cloud\_monitoring\_instance\_name](#input\_cloud\_monitoring\_instance\_name) | The name of the IBM Cloud Monitoring instance to create. If the prefix variable is passed, the name of the instance is prefixed to the value in the `-value` format. | `string` | `"cloud-monitoring"` | no | -| [cloud\_monitoring\_plan](#input\_cloud\_monitoring\_plan) | The IBM Cloud Monitoring plan to provision. Available values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only). | `string` | `"graduated-tier"` | no | -| [cloud\_monitoring\_resource\_keys](#input\_cloud\_monitoring\_resource\_keys) | A list of maps representing resource keys to create for the IBM Cloud Monitoring instance. Each entry defines a single resource key. Use this list to manage custom keys and handle key rotation. |
list(object({
name = string
generate_hmac_credentials = optional(bool, false) # pragma: allowlist secret
role = optional(string, "Manager")
service_id_crn = optional(string, null)
}))
| `[]` | no | -| [cloud\_monitoring\_resource\_tags](#input\_cloud\_monitoring\_resource\_tags) | Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings). | `list(string)` | `[]` | no | -| [cluster\_config\_endpoint\_type](#input\_cluster\_config\_endpoint\_type) | Specify which type of endpoint to use for cluster config access: 'default', 'private', 'vpe', 'link'. A 'default' value uses the default endpoint of the cluster. | `string` | `"default"` | no | -| [cluster\_kms\_key\_name](#input\_cluster\_kms\_key\_name) | The name of the key to be created for the cluster's Object Storage bucket encryption. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key"` | no | -| [cluster\_kms\_key\_ring\_name](#input\_cluster\_kms\_key\_ring\_name) | The name of the key ring to be created for the cluster's Object Storage bucket encryption key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"cluster-key-ring"` | no | -| [cluster\_name](#input\_cluster\_name) | The name of the new IBM Cloud OpenShift Cluster. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"openshift"` | no | -| [cluster\_ready\_when](#input\_cluster\_ready\_when) | The cluster is ready based on one of the following:: MasterNodeReady (not recommended), OneWorkerNodeReady, Normal, IngressReady. | `string` | `"IngressReady"` | no | -| [cluster\_resource\_tags](#input\_cluster\_resource\_tags) | Metadata labels describing this cluster deployment, i.e. test. | `list(string)` | `[]` | no | -| [config\_aggregator\_enterprise\_account\_group\_ids\_to\_assign](#input\_config\_aggregator\_enterprise\_account\_group\_ids\_to\_assign) | A list of enterprise account group IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all account groups. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`. | `list(string)` |
[
"all"
]
| no | -| [config\_aggregator\_enterprise\_account\_ids\_to\_assign](#input\_config\_aggregator\_enterprise\_account\_ids\_to\_assign) | A list of enterprise account IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all accounts. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`. | `list(string)` | `[]` | no | -| [config\_aggregator\_enterprise\_id](#input\_config\_aggregator\_enterprise\_id) | If the account is an enterprise account, this value should be set to the enterprise ID (NOTE: This is different to the account ID). | `string` | `null` | no | -| [config\_aggregator\_enterprise\_trusted\_profile\_name](#input\_config\_aggregator\_enterprise\_trusted\_profile\_name) | The name to give the enterprise viewer trusted profile with that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"config-aggregator-enterprise-trusted-profile"` | no | -| [config\_aggregator\_enterprise\_trusted\_profile\_template\_name](#input\_config\_aggregator\_enterprise\_trusted\_profile\_template\_name) | The name to give the trusted profile template that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"config-aggregator-trusted-profile-template"` | no | -| [config\_aggregator\_resource\_collection\_regions](#input\_config\_aggregator\_resource\_collection\_regions) | From which region do you want to collect configuration data? Only applies if `enable_config_aggregator` is set to true. | `list(string)` |
[
"all"
]
| no | -| [config\_aggregator\_trusted\_profile\_name](#input\_config\_aggregator\_trusted\_profile\_name) | The name to give the trusted profile that will be created if `enable_config_aggregator` is set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"config-aggregator-trusted-profile"` | no | -| [cos\_buckets\_class](#input\_cos\_buckets\_class) | The storage class of the newly provisioned IBM Cloud Logs Object Storage buckets. Possible values: `standard` or `smart`. Applies only if `existing_cloud_logs_crn` is not provided. | `string` | `"smart"` | no | -| [cos\_instance\_access\_tags](#input\_cos\_instance\_access\_tags) | A list of access tags to apply to the Object Storage instance created by the module. | `list(string)` | `[]` | no | -| [cos\_instance\_cbr\_rules](#input\_cos\_instance\_cbr\_rules) | The list of context-based restriction rules to create for the instance. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [cos\_instance\_name](#input\_cos\_instance\_name) | The name for the IBM Cloud Object Storage instance provisioned by this solution. If a value is passed for `prefix`, the instance will be named with the prefix value in the format of `-value`. | `string` | `"cos-instance"` | no | -| [cos\_instance\_plan](#input\_cos\_instance\_plan) | The plan to use when Object Storage instances are created. | `string` | `"standard"` | no | -| [cos\_instance\_resource\_tags](#input\_cos\_instance\_resource\_tags) | A list of resource tags to apply to the Object Storage instance. | `list(string)` | `[]` | no | -| [cos\_target\_name](#input\_cos\_target\_name) | Name of the cos target for activity tracker event routing. | `string` | `null` | no | -| [cspm\_enabled](#input\_cspm\_enabled) | Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service. | `bool` | `true` | no | -| [custom\_security\_group\_ids](#input\_custom\_security\_group\_ids) | Security groups to add to all worker nodes. This comes in addition to the IBM maintained security group if `attach_ibm_managed_security_group` is set to true. If this variable is set, the default VPC security group is NOT assigned to the worker nodes. | `list(string)` | `null` | no | -| [default\_network\_acl\_name](#input\_default\_network\_acl\_name) | Name of the Default ACL. If null, a name will be automatically generated. | `string` | `null` | no | -| [default\_pool\_maximum\_number\_of\_nodes](#input\_default\_pool\_maximum\_number\_of\_nodes) | The maximum number of worker nodes allowed in the pool, preventing the pool from exceeding three workers. | `number` | `3` | no | -| [default\_pool\_minimum\_number\_of\_nodes](#input\_default\_pool\_minimum\_number\_of\_nodes) | The minimum number of worker nodes allowed in the pool, ensuring at least one worker is always running. | `number` | `1` | no | -| [default\_routing\_table\_name](#input\_default\_routing\_table\_name) | Name of the Default Routing Table. If null, a name will be automatically generated. | `string` | `null` | no | -| [default\_security\_group\_name](#input\_default\_security\_group\_name) | Name of the Default Security Group. If null, a name will be automatically generated. | `string` | `null` | no | -| [default\_worker\_pool\_labels](#input\_default\_worker\_pool\_labels) | A set of key-value labels assigned to the worker pool for identification. | `map(string)` | `{}` | no | -| [default\_worker\_pool\_machine\_type](#input\_default\_worker\_pool\_machine\_type) | The machine type for worker nodes. | `string` | `"bx2.4x16"` | no | -| [default\_worker\_pool\_operating\_system](#input\_default\_worker\_pool\_operating\_system) | The operating system installed on the worker nodes. | `string` | `"RHCOS"` | no | -| [default\_worker\_pool\_workers\_per\_zone](#input\_default\_worker\_pool\_workers\_per\_zone) | Number of worker nodes in each zone of the cluster. | `number` | `1` | no | -| [disable\_access\_key\_creation](#input\_disable\_access\_key\_creation) | When set to true, disables the creation of a default manager access key which is required by agents to ingest metrics. | `bool` | `false` | no | -| [dual\_auth\_delete\_enabled](#input\_dual\_auth\_delete\_enabled) | If set to `true`, a dual authorization policy is enabled on the Key Protect instance. After the dual authorization policy is set on the instance, it cannot be reverted. An instance with dual authorization policy enabled cannot be destroyed by using Terraform. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `false` | no | -| [en\_access\_tags](#input\_en\_access\_tags) | A list of access tags to apply to the Event Notifications instance created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial). | `list(string)` | `[]` | no | -| [en\_cbr\_rules](#input\_en\_cbr\_rules) | The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md). |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [en\_cos\_bucket\_access\_tags](#input\_en\_cos\_bucket\_access\_tags) | A list of access tags to apply to the Cloud Object Storage bucket created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial). | `list(string)` | `[]` | no | -| [en\_cos\_bucket\_name](#input\_en\_cos\_bucket\_name) | The name to use when creating the Object Storage bucket for the storage of failed delivery events. Bucket names are globally unique. If `add_bucket_name_suffix` is set to `true`, a random 4 character string is added to this name to help ensure that the bucket name is unique. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"base-event-notifications-bucket"` | no | -| [en\_resource\_tags](#input\_en\_resource\_tags) | The list of tags to add to the Event Notifications instance. | `list(string)` | `[]` | no | -| [en\_service\_credential\_names](#input\_en\_service\_credential\_names) | A mapping of names and associated roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/blob/main/solutions/fully-configurable/DA-types.md#service-credentials-). | `map(string)` | `{}` | no | -| [en\_service\_credential\_secrets](#input\_en\_service\_credential\_secrets) | Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets). |
list(object({
secret_group_name = string # pragma: allowlist secret
secret_group_description = optional(string) # pragma: allowlist secret
existing_secret_group = optional(bool) # pragma: allowlist secret
service_credentials = list(object({ # pragma: allowlist secret
secret_name = string # pragma: allowlist secret
service_credentials_source_service_role_crn = string # pragma: allowlist secret
secret_labels = optional(list(string)) # pragma: allowlist secret
secret_auto_rotation = optional(bool) # pragma: allowlist secret
secret_auto_rotation_unit = optional(string) # pragma: allowlist secret
secret_auto_rotation_interval = optional(number) # pragma: allowlist secret
service_credentials_ttl = optional(string) # pragma: allowlist secret
service_credential_secret_description = optional(string) # pragma: allowlist secret

}))
}))
| `[]` | no | -| [en\_service\_endpoints](#input\_en\_service\_endpoints) | Specify whether you want to enable public, private, or both public and private service endpoints. Possible values: `public`, `private`, `public-and-private`. | `string` | `"private"` | no | -| [en\_service\_plan](#input\_en\_service\_plan) | The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard`. | `string` | `"standard"` | no | -| [enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs](#input\_enable\_activity\_tracker\_event\_routing\_to\_cloud\_logs) | When set to `true`, you must provide a value for `existing_cloud_logs_crn` to enable event routing from Activity Tracker to a Cloud Logs instance. | `bool` | `true` | no | -| [enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket](#input\_enable\_activity\_tracker\_event\_routing\_to\_cos\_bucket) | When set to `true`, you must provide a value for `existing_cos_instance_crn` to enable event routing from Activity Tracker to a Object Storage bucket. | `bool` | `true` | no | -| [enable\_autoscaling\_for\_default\_pool](#input\_enable\_autoscaling\_for\_default\_pool) | Set `true` to enable automatic scaling of worker based on workload demand. | `bool` | `false` | no | -| [enable\_collecting\_failed\_events](#input\_enable\_collecting\_failed\_events) | Set to true to enable Cloud Object Storage integration. If enabled, you must also provide a Cloud Object Storage instance (for storing failed events) using the `existing_cos_instance_crn` variable. For more information, [see here](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-cfe-integrations). | `bool` | `true` | no | -| [enable\_config\_aggregator](#input\_enable\_config\_aggregator) | Set to true to enable configuration aggregator. By setting to true a trusted profile will be created with the required access to record configuration data from all resources across regions in your account. [Learn more](https://cloud.ibm.com/docs/app-configuration?topic=app-configuration-ac-configuration-aggregator). | `bool` | `true` | no | -| [enable\_metrics](#input\_enable\_metrics) | Set to `true` to enable metrics on the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. In order to view metrics, you need an IBM Cloud Monitoring (Sysdig) instance that is located in the same region as the Key Protect instance. After you provision a Monitoring instance, enable platform metrics to monitor your Key Protect instance. | `bool` | `true` | no | -| [enable\_metrics\_routing\_to\_cloud\_monitoring](#input\_enable\_metrics\_routing\_to\_cloud\_monitoring) | Whether to enable metrics routing from IBM Cloud Metric Routing to Cloud Monitoring. | `bool` | `true` | no | -| [enable\_ocp\_console](#input\_enable\_ocp\_console) | Flag to specify whether to enable or disable the OpenShift console. If set to `null` the module does not modify the current setting on the cluster. Keep in mind that when this input is set to `true` or `false` on a cluster with private only endpoint enabled, the runtime must be able to access the private endpoint. | `bool` | `null` | no | -| [enable\_platform\_metrics](#input\_enable\_platform\_metrics) | When set to `true`, the IBM Cloud Monitoring instance collects the platform metrics. | `bool` | `false` | no | -| [enable\_primary\_metadata\_region](#input\_enable\_primary\_metadata\_region) | When set to `true`, sets `primary_metadata_region` to `region`, storing Metrics Router metadata in that region. When `false`, no region is set and the default global region is used. For new accounts, creating targets and routes will fail until primary\_metadata\_region is set, so it is recommended to default enable\_primary\_metadata\_region to true. | `bool` | `true` | no | -| [enable\_secrets\_manager\_integration](#input\_enable\_secrets\_manager\_integration) | Integrate with IBM Cloud Secrets Manager so you can centrally manage Ingress subdomain certificates and other secrets. | `bool` | `true` | no | -| [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | To enable VPC Flow logs, set this to true. | `bool` | `false` | no | -| [event\_notifications\_email\_list](#input\_event\_notifications\_email\_list) | The list of email address to target out when Secrets Manager triggers an event | `list(string)` | `[]` | no | -| [event\_notifications\_endpoint\_url](#input\_event\_notifications\_endpoint\_url) | The URL of the Event Notifications service endpoint to use for notifying configuration changes. For more information on the endpoint URL for Event Notifications, go to [Service endpoints](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-regions-endpoints#en-service-endpoints). It is required if `enable_event_notifications` is set to true. | `string` | `null` | no | -| [event\_notifications\_from\_email](#input\_event\_notifications\_from\_email) | The email address used to send any Secrets Manager event coming via Event Notifications | `string` | `"compliancealert@ibm.com"` | no | -| [event\_notifications\_instance\_name](#input\_event\_notifications\_instance\_name) | The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications"` | no | -| [event\_notifications\_reply\_to\_email](#input\_event\_notifications\_reply\_to\_email) | The email address specified in the 'reply\_to' section for any Secret Manager event coming via Event Notifications | `string` | `"no-reply@ibm.com"` | no | -| [existing\_activity\_tracker\_cos\_target\_bucket\_endpoint](#input\_existing\_activity\_tracker\_cos\_target\_bucket\_endpoint) | The name of an existing Cloud Object Storage bucket endpoint to use for setting up IBM Cloud Activity Tracker Event Routing. If an existing endpoint is not specified, the endpoint of the new Cloud Object Storage bucket is used. | `string` | `null` | no | -| [existing\_activity\_tracker\_cos\_target\_bucket\_name](#input\_existing\_activity\_tracker\_cos\_target\_bucket\_name) | The name of an existing bucket within the Cloud Object Storage instance in which to store IBM Cloud Activity Tracker Event Routing. If an existing Cloud Object Storage bucket is not specified, a bucket is created. | `string` | `null` | no | -| [existing\_boot\_volume\_kms\_key\_crn](#input\_existing\_boot\_volume\_kms\_key\_crn) | The CRN of an existing KMS key to use to encrypt the the block storage volumes for VPC. If no value is set for this variable, specify a value for either the `existing_kms_instance_crn` variable to create a key ring and key. | `string` | `null` | no | -| [existing\_cloud\_logs\_crn](#input\_existing\_cloud\_logs\_crn) | The CRN of an existing Cloud Logs instance. If not supplied, a new instance will be created. | `string` | `null` | no | -| [existing\_cloud\_monitoring\_crn](#input\_existing\_cloud\_monitoring\_crn) | The CRN of an existing Cloud Monitoring instance. If not supplied, a new instance will be created. | `string` | `null` | no | -| [existing\_cluster\_kms\_key\_crn](#input\_existing\_cluster\_kms\_key\_crn) | The CRN of an existing KMS key to use for encrypting the Object Storage of the Cluster. If no value is set for this variable, specify a value for `existing_kms_instance_crn` variable to create a key ring and key. | `string` | `null` | no | -| [existing\_cos\_instance\_crn](#input\_existing\_cos\_instance\_crn) | The CRN of an existing Object Storage instance. | `string` | `null` | no | -| [existing\_event\_notifications\_instance\_crn](#input\_existing\_event\_notifications\_instance\_crn) | The CRN of the Event Notifications service used to enable lifecycle notifications for your Secrets Manager instance. | `string` | `null` | no | -| [existing\_event\_notifications\_instances](#input\_existing\_event\_notifications\_instances) | List of Event Notifications instance details for routing critical events that occur in your IBM Cloud Logs. |
list(object({
crn = string
integration_name = optional(string)
skip_iam_auth_policy = optional(bool, false)
}))
| `[]` | no | -| [existing\_kms\_instance\_crn](#input\_existing\_kms\_instance\_crn) | The CRN of an existing KMS instance. | `string` | `null` | no | -| [existing\_secrets\_manager\_crn](#input\_existing\_secrets\_manager\_crn) | The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created. | `string` | `null` | no | -| [flow\_logs\_cos\_bucket\_archive\_days](#input\_flow\_logs\_cos\_bucket\_archive\_days) | The number of days before the `archive_type` rule action takes effect for the flow logs cloud object storage bucket. | `number` | `90` | no | -| [flow\_logs\_cos\_bucket\_archive\_type](#input\_flow\_logs\_cos\_bucket\_archive\_type) | The storage class or archive type you want the object to transition to in the flow logs cloud object storage bucket. | `string` | `"Glacier"` | no | -| [flow\_logs\_cos\_bucket\_default\_retention\_days](#input\_flow\_logs\_cos\_bucket\_default\_retention\_days) | The number of days that an object can remain unmodified in the flow logs cloud object storage bucket. | `number` | `90` | no | -| [flow\_logs\_cos\_bucket\_enable\_object\_versioning](#input\_flow\_logs\_cos\_bucket\_enable\_object\_versioning) | Set it to true if object versioning is enabled so that multiple versions of an object are retained in the flow logs cloud object storage bucket. Cannot be used if `flow_logs_cos_bucket_enable_retention` is true. | `bool` | `false` | no | -| [flow\_logs\_cos\_bucket\_enable\_permanent\_retention](#input\_flow\_logs\_cos\_bucket\_enable\_permanent\_retention) | Whether permanent retention status is enabled for the flow logs cloud object storage bucket. | `bool` | `false` | no | -| [flow\_logs\_cos\_bucket\_enable\_retention](#input\_flow\_logs\_cos\_bucket\_enable\_retention) | Set to true to enable retention for the flow logs cloud object storage bucket. | `bool` | `false` | no | -| [flow\_logs\_cos\_bucket\_expire\_days](#input\_flow\_logs\_cos\_bucket\_expire\_days) | The number of days before the expire rule action takes effect for the flow logs cloud object storage bucket. | `number` | `366` | no | -| [flow\_logs\_cos\_bucket\_maximum\_retention\_days](#input\_flow\_logs\_cos\_bucket\_maximum\_retention\_days) | The maximum number of days that an object can be kept unmodified in the flow logs cloud object storage. | `number` | `350` | no | -| [flow\_logs\_cos\_bucket\_minimum\_retention\_days](#input\_flow\_logs\_cos\_bucket\_minimum\_retention\_days) | The minimum number of days that an object must be kept unmodified in the flow logs cloud object storage. | `number` | `90` | no | -| [flow\_logs\_cos\_bucket\_name](#input\_flow\_logs\_cos\_bucket\_name) | Name of the Cloud Object Storage bucket to be created to collect VPC flow logs. | `string` | `"flow-logs-bucket"` | no | -| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The IBM Cloud api token | `string` | n/a | yes | -| [ignore\_worker\_pool\_size\_changes](#input\_ignore\_worker\_pool\_size\_changes) | Enable if using worker autoscaling. Stops Terraform managing worker count. | `bool` | `false` | no | -| [key\_create\_import\_access\_enabled](#input\_key\_create\_import\_access\_enabled) | If set to `true`, a key create and import access policy is enabled on the instance of Key Protect. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `true` | no | -| [key\_protect\_allowed\_network](#input\_key\_protect\_allowed\_network) | Allowed network types for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"private-only"` | no | -| [kms\_access\_tags](#input\_kms\_access\_tags) | A list of access tags to apply to the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `list(string)` | `[]` | no | -| [kms\_cbr\_rules](#input\_kms\_cbr\_rules) | The context-based restrictions rule to create. Only one rule is allowed. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [kms\_encryption\_enabled\_boot\_volume](#input\_kms\_encryption\_enabled\_boot\_volume) | Set this to true to control the encryption keys used to encrypt the data that for the block storage volumes for VPC. If set to false, the data is encrypted by using randomly generated keys. For more info on encrypting block storage volumes, see https://cloud.ibm.com/docs/vpc?topic=vpc-creating-instances-byok | `bool` | `false` | no | -| [kms\_encryption\_enabled\_buckets](#input\_kms\_encryption\_enabled\_buckets) | Set to true to enable KMS encryption on the Object Storage buckets created for the IBM Cloud Logs instance. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn` (to create a new key). Can not be set to true if passing a value for `existing_cloud_logs_crn`. | `bool` | `false` | no | -| [kms\_encryption\_enabled\_cluster](#input\_kms\_encryption\_enabled\_cluster) | Set to true to enable KMS encryption for the cluster's Object Storage bucket. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn`. | `bool` | `false` | no | -| [kms\_endpoint\_type](#input\_kms\_endpoint\_type) | The endpoint for communicating with the KMS instance. Possible values: `public`, `private`. Applies only if `kms_encryption_enabled_cluster` is true | `string` | `"private"` | no | -| [kms\_endpoint\_url](#input\_kms\_endpoint\_url) | The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input. | `string` | `null` | no | -| [kms\_instance\_name](#input\_kms\_instance\_name) | The name to give the Key Protect instance that that is created by this module. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"key-protect"` | no | -| [kms\_plan](#input\_kms\_plan) | Plan for the Key Protect instance. Supported values are 'tiered-pricing' and 'cross-region-resiliency'. Only used if 'create\_key\_protect\_instance' is set to `true`. | `string` | `"tiered-pricing"` | no | -| [kms\_resource\_tags](#input\_kms\_resource\_tags) | Optional list of tags to add to the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `list(string)` | `[]` | no | -| [logs\_policies](#input\_logs\_policies) | Configuration of Cloud Logs policies. |
list(object({
logs_policy_name = string
logs_policy_description = optional(string, null)
logs_policy_priority = string
application_rule = optional(list(object({
name = string
rule_type_id = string
})))
subsystem_rule = optional(list(object({
name = string
rule_type_id = string
})))
log_rules = optional(list(object({
severities = list(string)
})))
archive_retention = optional(list(object({
id = string
})))
}))
| `[]` | no | -| [logs\_routing\_tenant\_regions](#input\_logs\_routing\_tenant\_regions) | Pass a list of regions to create a tenant for that is targeted to the Cloud Logs instance created by this module. To manage platform logs that are generated by IBM Cloud® services in a region of IBM Cloud, you must create a tenant in each region that you operate. Leave the list empty if you don't want to create any tenants. NOTE: You can only have 1 tenant per region in an account. | `list(any)` | `[]` | no | -| [manage\_all\_addons](#input\_manage\_all\_addons) | Instructs deployable architecture to manage all cluster addons, even if addons were installed outside of the module. If set to 'true' this deployable architecture destroys any addons that were installed by other sources. | `bool` | `false` | no | -| [management\_endpoint\_type\_for\_buckets](#input\_management\_endpoint\_type\_for\_buckets) | The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Possible values: `public`, `private`, `direct`. If you specify `private`, enable virtual routing and forwarding in your account, and the Terraform runtime must have access to the the IBM Cloud private network. | `string` | `"direct"` | no | -| [metrics\_router\_routes](#input\_metrics\_router\_routes) | Routes for IBM Cloud Metrics Routing. |
list(object({
name = string
rules = list(object({
action = string
targets = list(object({
id = string
}))
inclusion_filters = list(object({
operand = string
operator = string
values = list(string)
}))
}))
}))
| `[]` | no | -| [metrics\_routing\_route\_name](#input\_metrics\_routing\_route\_name) | The name of the IBM Cloud Metrics Routing route for the default route that indicate what metrics are routed in a region and where to store them. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"metrics-routing-route"` | no | -| [metrics\_routing\_target\_name](#input\_metrics\_routing\_target\_name) | The name of the IBM Cloud Metrics Routing target where metrics are collected. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format. | `string` | `"cloud-monitoring-target"` | no | -| [network\_acls](#input\_network\_acls) | The list of ACLs to create. Provide at least one rule for each ACL. |
list(
object({
name = string
add_ibm_cloud_internal_rules = optional(bool)
add_vpc_connectivity_rules = optional(bool)
prepend_ibm_rules = optional(bool)
rules = list(
object({
name = string
action = string
destination = string
direction = string
source = string
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
source_port_max = optional(number)
source_port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
})
)
|
[
{
"add_ibm_cloud_internal_rules": true,
"add_vpc_connectivity_rules": true,
"name": "vpc-acl",
"prepend_ibm_rules": true,
"rules": [
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-443-inbound-source",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-443-inbound-dest",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-80-inbound",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 80,
"source_port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "inbound",
"name": "allow-all-ingress-inbound",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 32767,
"source_port_min": 30000
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-443-outbound-source",
"source": "0.0.0.0/0",
"tcp": {
"source_port_max": 443,
"source_port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-443-outbound-dest",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 443,
"port_min": 443
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-80-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 80,
"port_min": 80
}
},
{
"action": "allow",
"destination": "0.0.0.0/0",
"direction": "outbound",
"name": "allow-all-ingress-outbound",
"source": "0.0.0.0/0",
"tcp": {
"port_max": 32767,
"port_min": 30000
}
}
]
}
]
| no | -| [number\_of\_lbs](#input\_number\_of\_lbs) | The total number of Load Balancers in the cluster that should be associated with the security groups defined in `additional_lb_security_group_ids` variable. | `number` | `1` | no | -| [ocp\_cbr\_rules](#input\_ocp\_cbr\_rules) | The list of context-based restriction rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [ocp\_entitlement](#input\_ocp\_entitlement) | Value that is applied to the entitlements for OCP cluster provisioning. | `string` | `null` | no | -| [openshift\_version](#input\_openshift\_version) | Version of the OpenShift cluster to provision. | `string` | `"4.19"` | no | -| [pod\_subnet\_cidr](#input\_pod\_subnet\_cidr) | Specify a custom subnet CIDR to provide private IP addresses for pods. The subnet must have a CIDR of at least `/23` or larger. Default value is `172.30.0.0/16` when the variable is set to `null`. | `string` | `null` | no | -| [prefix](#input\_prefix) | The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string. | `string` | n/a | yes | -| [provider\_visibility](#input\_provider\_visibility) | Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. | `string` | `"private"` | no | -| [region](#input\_region) | The region to provision all resources in. | `string` | `"us-south"` | no | -| [resource\_group\_id](#input\_resource\_group\_id) | The ID of an existing IBM Cloud resource group where the cluster is grouped. | `string` | n/a | yes | -| [rotation\_enabled](#input\_rotation\_enabled) | If set to `true`, a rotation policy is enabled on the Key Protect instance. Only used if 'create\_key\_protect\_instance' is set to `true`. | `bool` | `true` | no | -| [rotation\_interval\_month](#input\_rotation\_interval\_month) | Specifies how often keys are rotated in months. Value must be between `1` and `12` inclusive. Only used if 'create\_key\_protect\_instance' is set to `true`. | `number` | `1` | no | -| [routes](#input\_routes) | Allows you to specify the next hop for packets based on their destination address. |
list(
object({
name = string
route_direct_link_ingress = optional(bool)
route_transit_gateway_ingress = optional(bool)
route_vpc_zone_ingress = optional(bool)
routes = optional(
list(
object({
action = optional(string)
zone = number
destination = string
next_hop = string
})
))
})
)
| `[]` | no | -| [scc\_workload\_protection\_access\_tags](#input\_scc\_workload\_protection\_access\_tags) | A list of access tags to apply to the Workload Protection instance. Maximum length: 128 characters. Possible characters are A-Z, 0-9, spaces, underscores, hyphens, periods, and colons. | `list(string)` | `[]` | no | -| [scc\_workload\_protection\_instance\_name](#input\_scc\_workload\_protection\_instance\_name) | The name for the Workload Protection instance that is created by this solution. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"scc-workload-protection"` | no | -| [scc\_workload\_protection\_instance\_tags](#input\_scc\_workload\_protection\_instance\_tags) | The list of tags to add to the Workload Protection instance. | `list(string)` | `[]` | no | -| [scc\_workload\_protection\_resource\_key\_tags](#input\_scc\_workload\_protection\_resource\_key\_tags) | The tags associated with the Workload Protection resource key. | `list(string)` | `[]` | no | -| [scc\_workload\_protection\_service\_plan](#input\_scc\_workload\_protection\_service\_plan) | The pricing plan for the Workload Protection instance service. Possible values: `free-trial`, `graduated-tier`. | `string` | `"graduated-tier"` | no | -| [scc\_workload\_protection\_trusted\_profile\_name](#input\_scc\_workload\_protection\_trusted\_profile\_name) | The name to give the trusted profile that is created by this module if `cspm_enabled` is `true. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format.` | `string` | `"workload-protection-trusted-profile"` | no | -| [scc\_wp\_cbr\_rules](#input\_scc\_wp\_cbr\_rules) | The list of context-based restriction rules to create for the instance. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [secret\_groups](#input\_secret\_groups) | Secret Manager secret group and access group configurations. If a prefix input variable is specified, it is added to the `access_group_name` value in the `-value` format. If you do not wish to create any groups, set the value to `[]`. |
list(object({
secret_group_name = string
secret_group_description = optional(string)
create_access_group = optional(bool, true)
access_group_name = optional(string)
access_group_roles = optional(list(string), ["SecretsReader"])
access_group_tags = optional(list(string))
}))
|
[
{
"access_group_name": "general-secrets-group-access-group",
"access_group_roles": [
"SecretsReader"
],
"create_access_group": true,
"secret_group_description": "A general purpose secrets group with an associated access group which has a secrets reader role",
"secret_group_name": "General"
}
]
| no | -| [secrets\_manager\_allowed\_network](#input\_secrets\_manager\_allowed\_network) | The types of service endpoints to set on the Secrets Manager instance. Possible values are `private-only` or `public-and-private`. | `string` | `"private-only"` | no | -| [secrets\_manager\_cbr\_rules](#input\_secrets\_manager\_cbr\_rules) | (Optional, list) List of CBR rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | -| [secrets\_manager\_endpoint\_type](#input\_secrets\_manager\_endpoint\_type) | The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications. | `string` | `"private"` | no | -| [secrets\_manager\_instance\_name](#input\_secrets\_manager\_instance\_name) | The name to give the Secrets Manager instance provisioned by this solution. If a prefix input variable is specified, it is added to the value in the `-value` format. Applies only if `existing_secrets_manager_crn` is not provided. | `string` | `"secrets-manager"` | no | -| [secrets\_manager\_resource\_tags](#input\_secrets\_manager\_resource\_tags) | The list of resource tags you want to associate with your Secrets Manager instance. Applies only if `existing_secrets_manager_crn` is not provided. | `list(string)` | `[]` | no | -| [secrets\_manager\_secret\_group\_id](#input\_secrets\_manager\_secret\_group\_id) | Secret group ID where Ingress secrets are stored in the Secrets Manager instance. If 'enable\_secrets\_manager\_integration' is set to true and 'secrets\_manager\_secret\_group\_id' is not provided, a new group will be created with the same name as cluster\_id. | `string` | `null` | no | -| [secrets\_manager\_service\_plan](#input\_secrets\_manager\_service\_plan) | The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. You can create only one Trial instance of Secrets Manager per account. Before you can create a new Trial instance, you must delete the existing Trial instance and its reclamation. | `string` | `"standard"` | no | -| [security\_group\_rules](#input\_security\_group\_rules) | A list of security group rules to be added to the default vpc security group (default empty). |
list(
object({
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
udp = optional(
object({
port_max = optional(number)
port_min = optional(number)
})
)
icmp = optional(
object({
type = optional(number)
code = optional(number)
})
)
})
)
| `[]` | no | -| [service\_cred](#input\_service\_cred) | Service configuration for COS. |
list(object({
secret_group_name = string # pragma: allowlist secret
secret_group_description = optional(string) # pragma: allowlist secret
existing_secret_group = optional(bool) # pragma: allowlist secret
service_credentials = list(object({ # pragma: allowlist secret
secret_name = string # pragma: allowlist secret
service_credentials_source_service_role_crn = string # pragma: allowlist secret
secret_labels = optional(list(string)) # pragma: allowlist secret
secret_auto_rotation = optional(bool) # pragma: allowlist secret
secret_auto_rotation_unit = optional(string) # pragma: allowlist secret
secret_auto_rotation_interval = optional(number) # pragma: allowlist secret
service_credentials_ttl = optional(string) # pragma: allowlist secret
service_credential_secret_description = optional(string) # pragma: allowlist secret

}))
}))
| `[]` | no | -| [service\_subnet\_cidr](#input\_service\_subnet\_cidr) | Specify a custom subnet CIDR to provide private IP addresses for services. The subnet must be at least `/24` or larger. Default value is `172.21.0.0/16` when the variable is set to `null`. | `string` | `null` | no | -| [skip\_activity\_tracker\_cos\_auth\_policy](#input\_skip\_activity\_tracker\_cos\_auth\_policy) | To skip creating an IAM authorization policy that allows the Activity Tracker to write to the Cloud Object Storage instance, set this variable to `true`. | `bool` | `false` | no | -| [skip\_app\_config\_event\_notifications\_auth\_policy](#input\_skip\_app\_config\_event\_notifications\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits App configuration instances to integrate with Event Notification in the same account. | `bool` | `false` | no | -| [skip\_app\_config\_kms\_auth\_policy](#input\_skip\_app\_config\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits App configuration instances in the resource group to read the encryption key from the KMS instance in the same account. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the other account. | `bool` | `false` | no | -| [skip\_cloud\_logs\_cos\_auth\_policy](#input\_skip\_cloud\_logs\_cos\_auth\_policy) | To skip creating an IAM authorization policy that allows the IBM Cloud logs to write to the Cloud Object Storage bucket, set this variable to `true`. | `bool` | `false` | no | -| [skip\_event\_notifications\_cos\_auth\_policy](#input\_skip\_event\_notifications\_cos\_auth\_policy) | Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy. | `bool` | `false` | no | -| [skip\_event\_notifications\_kms\_auth\_policy](#input\_skip\_event\_notifications\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | -| [skip\_event\_notifications\_secrets\_manager\_auth\_policy](#input\_skip\_event\_notifications\_secrets\_manager\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing\_secrets\_manager\_crn' is not passed. | `bool` | `false` | no | -| [skip\_logs\_routing\_auth\_policy](#input\_skip\_logs\_routing\_auth\_policy) | Whether to create an IAM authorization policy that permits the Logs Routing server 'Sender' access to the IBM Cloud Logs instance created by this Deployable Architecture. | `bool` | `false` | no | -| [skip\_ocp\_secrets\_manager\_iam\_auth\_policy](#input\_skip\_ocp\_secrets\_manager\_iam\_auth\_policy) | To skip creating auth policy that allows OCP cluster 'Manager' role access in the existing Secrets Manager instance for managing ingress certificates. | `bool` | `false` | no | -| [skip\_secrets\_manager\_cos\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_cos\_iam\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Cloud Object Storage. Set to `true` to use an existing policy. | `bool` | `false` | no | -| [skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_event\_notifications\_iam\_auth\_policy) | If set to true, this skips the creation of a service to service authorization from Secrets Manager to Event Notifications. If false, the service to service authorization is created. | `bool` | `false` | no | -| [skip\_secrets\_manager\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_iam\_auth\_policy) | Whether to skip the creation of the IAM authorization policies required to enable the IAM credentials engine (if you are using an existing Secrets Manager instance, attempting to re-create can cause conflicts if the policies already exist). If set to false, policies will be created that grants the Secrets Manager instance 'Operator' access to the IAM identity service, and 'Groups Service Member Manage' access to the IAM groups service. | `bool` | `false` | no | -| [skip\_secrets\_manager\_kms\_iam\_auth\_policy](#input\_skip\_secrets\_manager\_kms\_iam\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances in the resource group to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. | `bool` | `false` | no | -| [skip\_vpc\_cos\_iam\_auth\_policy](#input\_skip\_vpc\_cos\_iam\_auth\_policy) | To skip creating an IAM authorization policy that allows the VPC to access the Cloud Object Storage, set this variable to `true`. Required only if `enable_vpc_flow_logs` is set to true. | `bool` | `false` | no | -| [subnets](#input\_subnets) | List of subnets for the vpc. For each item in each array, a subnet will be created. Items can be either CIDR blocks or total ipv4 addresses. Public gateways will be enabled only in zones where a gateway has been createds. |
object({
zone-1 = list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
}))
zone-2 = optional(list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
})))
zone-3 = optional(list(object({
name = string
cidr = string
public_gateway = optional(bool)
acl_name = string
no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true
subnet_tags = optional(list(string), [])
})))
})
|
{
"zone-1": [
{
"acl_name": "vpc-acl",
"cidr": "10.10.10.0/24",
"name": "subnet-a",
"no_addr_prefix": false,
"public_gateway": true
}
],
"zone-2": [
{
"acl_name": "vpc-acl",
"cidr": "10.20.10.0/24",
"name": "subnet-b",
"no_addr_prefix": false,
"public_gateway": true
}
],
"zone-3": [
{
"acl_name": "vpc-acl",
"cidr": "10.30.10.0/24",
"name": "subnet-c",
"no_addr_prefix": false,
"public_gateway": true
}
]
}
| no | -| [verify\_worker\_network\_readiness](#input\_verify\_worker\_network\_readiness) | By setting this to true, a script runs kubectl commands to verify that all worker nodes can communicate successfully with the master. If the runtime does not have access to the kube cluster to run kubectl commands, set this value to false. | `bool` | `true` | no | -| [vpc\_access\_tags](#input\_vpc\_access\_tags) | The list of access tags to add to the VPC instance. | `list(string)` | `[]` | no | -| [vpc\_flow\_logs\_access\_tags](#input\_vpc\_flow\_logs\_access\_tags) | The list of access tags to add to the VPC instance. | `list(string)` | `[]` | no | -| [vpc\_name](#input\_vpc\_name) | Name of the VPC. If a prefix input variable is specified, the prefix is added to the name in the `-` format. | `string` | `"vpc"` | no | -| [vpc\_resource\_tags](#input\_vpc\_resource\_tags) | The list of tags to add to the VPC instance. | `list(string)` | `[]` | no | -| [vpe\_gateway\_cloud\_service\_by\_crn](#input\_vpe\_gateway\_cloud\_service\_by\_crn) | The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. |
set(
object({
crn = string
vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn.
allow_dns_resolution_binding = optional(bool, true)
})
)
| `[]` | no | -| [vpe\_gateway\_cloud\_services](#input\_vpe\_gateway\_cloud\_services) | The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | -| [vpe\_gateway\_reserved\_ips](#input\_vpe\_gateway\_reserved\_ips) | Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used when a user passes their existing reserved ips created here and not attempt to recreate those. |
object({
name = optional(string) # reserved ip name
})
| `{}` | no | -| [vpe\_gateway\_security\_group\_ids](#input\_vpe\_gateway\_security\_group\_ids) | List of security group ids to attach to each endpoint gateway. | `list(string)` | `null` | no | -| [vpe\_gateway\_service\_endpoints](#input\_vpe\_gateway\_service\_endpoints) | Service endpoints to use to create endpoint gateways. Can be `public`, or `private`. | `string` | `"private"` | no | -| [vpn\_gateways](#input\_vpn\_gateways) | List of VPN Gateways to create. |
list(
object({
name = string
subnet_name = string # Do not include prefix, use same name as in `var.subnets`
mode = optional(string)
resource_group = optional(string)
access_tags = optional(list(string), [])
})
)
| `[]` | no | -| [worker\_pools\_taints](#input\_worker\_pools\_taints) | Optional, Map of lists containing node taints by node-pool name. | `map(list(object({ key = string, value = string, effect = string })))` | `null` | no | - -### Outputs - -| Name | Description | -|------|-------------| -| [activity\_tracker\_cos\_target\_bucket\_name](#output\_activity\_tracker\_cos\_target\_bucket\_name) | he name of the object storage bucket which is set as activity tracker event routing target to collect audit events. | -| [activity\_tracker\_routes](#output\_activity\_tracker\_routes) | The map of created Activity Tracker Event Routing routes | -| [activity\_tracker\_targets](#output\_activity\_tracker\_targets) | The map of created Activity Tracker Event Routing targets | -| [cloud\_logs\_crn](#output\_cloud\_logs\_crn) | The id of the provisioned IBM Cloud Logs instance. | -| [cloud\_logs\_guid](#output\_cloud\_logs\_guid) | The guid of the provisioned IBM Cloud Logs instance. | -| [cloud\_logs\_ingress\_endpoint](#output\_cloud\_logs\_ingress\_endpoint) | The public ingress endpoint of the provisioned IBM Cloud Logs instance. | -| [cloud\_logs\_ingress\_private\_endpoint](#output\_cloud\_logs\_ingress\_private\_endpoint) | The private ingress endpoint of the provisioned IBM Cloud Logs instance. | -| [cloud\_logs\_logs\_policies\_details](#output\_cloud\_logs\_logs\_policies\_details) | The details of the IBM Cloud logs policies created. | -| [cloud\_logs\_name](#output\_cloud\_logs\_name) | The name of the provisioned IBM Cloud Logs instance. | -| [cloud\_monitoring\_access\_key](#output\_cloud\_monitoring\_access\_key) | The IBM Cloud Monitoring access key for agents to use | -| [cloud\_monitoring\_access\_key\_name](#output\_cloud\_monitoring\_access\_key\_name) | The name of the IBM Cloud Monitoring access key for agents to use | -| [cloud\_monitoring\_crn](#output\_cloud\_monitoring\_crn) | The id of the provisioned IBM Cloud Monitoring instance. | -| [cloud\_monitoring\_guid](#output\_cloud\_monitoring\_guid) | The guid of the provisioned IBM Cloud Monitoring instance. | -| [cloud\_monitoring\_name](#output\_cloud\_monitoring\_name) | The name of the provisioned IBM Cloud Monitoring instance. | -| [cluster\_crn](#output\_cluster\_crn) | The Cloud Resource Name (CRN) of the provisioned OpenShift cluster. | -| [cluster\_id](#output\_cluster\_id) | The unique identifier assigned to the provisioned OpenShift cluster. | -| [cluster\_name](#output\_cluster\_name) | The name of the provisioned OpenShift cluster. | -| [cos\_instance\_crn](#output\_cos\_instance\_crn) | COS instance crn | -| [cos\_instance\_guid](#output\_cos\_instance\_guid) | COS instance guid | -| [cos\_instance\_id](#output\_cos\_instance\_id) | COS instance ID | -| [events\_notification\_crn](#output\_events\_notification\_crn) | Event Notification crn | -| [events\_notification\_guid](#output\_events\_notification\_guid) | Event Notification guid | -| [kms\_account\_id](#output\_kms\_account\_id) | The account ID of the KMS instance. | -| [kms\_guid](#output\_kms\_guid) | KMS instance GUID | -| [kms\_instance\_crn](#output\_kms\_instance\_crn) | The CRN of the KMS instance | -| [logs\_bucket\_crn](#output\_logs\_bucket\_crn) | Logs Cloud Object Storage bucket CRN | -| [metrics\_bucket\_crn](#output\_metrics\_bucket\_crn) | Metrics Cloud Object Storage bucket CRN | -| [network\_acls](#output\_network\_acls) | List of shortnames and IDs of network ACLs. | -| [ocp\_version](#output\_ocp\_version) | The version of OpenShift running on the provisioned cluster. | -| [private\_path\_subnet\_id](#output\_private\_path\_subnet\_id) | The IDs of the subnets. | -| [public\_gateways](#output\_public\_gateways) | Map of the public gateways by zone. | -| [scc\_workload\_protection\_api\_endpoint](#output\_scc\_workload\_protection\_api\_endpoint) | SCC Workload Protection API endpoint | -| [scc\_workload\_protection\_crn](#output\_scc\_workload\_protection\_crn) | SCC Workload Protection instance CRN | -| [scc\_workload\_protection\_id](#output\_scc\_workload\_protection\_id) | SCC Workload Protection instance ID | -| [scc\_workload\_protection\_ingestion\_endpoint](#output\_scc\_workload\_protection\_ingestion\_endpoint) | SCC Workload Protection instance ingestion endpoint | -| [scc\_workload\_protection\_name](#output\_scc\_workload\_protection\_name) | SCC Workload Protection instance name | -| [secrets\_manager\_crn](#output\_secrets\_manager\_crn) | CRN of the Secrets Manager instance | -| [secrets\_manager\_guid](#output\_secrets\_manager\_guid) | GUID of Secrets Manager instance | -| [secrets\_manager\_region](#output\_secrets\_manager\_region) | Region of the Secrets Manager instance | -| [subnet\_detail\_list](#output\_subnet\_detail\_list) | A list of subnets containing names, CIDR blocks, and zones. | -| [subnet\_detail\_map](#output\_subnet\_detail\_map) | A map of subnets containing IDs, CIDR blocks, and zones. | -| [subnet\_ids](#output\_subnet\_ids) | The IDs of the subnets. | -| [subnet\_zone\_list](#output\_subnet\_zone\_list) | A list of subnet IDs and subnet zones. | -| [vpc\_crn](#output\_vpc\_crn) | CRN of the VPC created. | -| [vpc\_flow\_logs](#output\_vpc\_flow\_logs) | Details of the VPC flow logs collector. | -| [vpc\_id](#output\_vpc\_id) | ID of the VPC created. | -| [vpc\_name](#output\_vpc\_name) | Name of the VPC created. | -| [vpe\_crn](#output\_vpe\_crn) | The CRN of the endpoint gateway. | -| [vpe\_ips](#output\_vpe\_ips) | The reserved IPs for endpoint gateways. | -| [vpn\_gateways\_data](#output\_vpn\_gateways\_data) | Details of VPN gateways data. | -| [vpn\_gateways\_name](#output\_vpn\_gateways\_name) | List of names of VPN gateways. | -| [workerpools](#output\_workerpools) | A list of worker pools associated with the provisioned cluster | - diff --git a/modules/containerized_app_landing_zone/main.tf b/modules/containerized_app_landing_zone/main.tf deleted file mode 100644 index fc2dc5c0d..000000000 --- a/modules/containerized_app_landing_zone/main.tf +++ /dev/null @@ -1,1072 +0,0 @@ -################################################################################# -# KMS -################################################################################# - -module "existing_kms_crn_parser" { - count = var.existing_kms_instance_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_kms_instance_crn -} - -module "existing_cluster_kms_key_crn_parser" { - count = var.existing_cluster_kms_key_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_cluster_kms_key_crn -} - -module "existing_boot_volume_kms_key_crn_parser" { - count = var.existing_boot_volume_kms_key_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_boot_volume_kms_key_crn -} - -locals { - prefix = var.prefix != null ? trimspace(var.prefix) != "" ? "${var.prefix}-" : "" : "" - cluster_existing_kms_guid = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_cluster ? module.existing_kms_crn_parser[0].service_instance : var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].service_instance : var.kms_encryption_enabled_cluster ? module.kms[0].kms_guid : null - cluster_kms_account_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_cluster ? module.existing_kms_crn_parser[0].account_id : var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].account_id : var.kms_encryption_enabled_cluster ? module.kms[0].kms_account_id : null - cluster_kms_key_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_cluster ? module.kms[0].keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].key_id : var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].resource : var.kms_encryption_enabled_cluster ? module.kms[0].keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].key_id : null - cluster_kms_key_crn = var.kms_encryption_enabled_cluster ? module.kms[0].keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn : var.existing_cluster_kms_key_crn != null ? var.existing_boot_volume_kms_key_crn : var.kms_encryption_enabled_cluster ? module.kms[0].key_protect_crn : null - cluster_key_ring_name = "${local.prefix}${var.cluster_kms_key_ring_name}" - cluster_key_name = "${local.prefix}${var.cluster_kms_key_name}" - cluster_name = "${local.prefix}${var.cluster_name}" - - boot_volume_key_ring_name = "${local.prefix}${var.boot_volume_kms_key_ring_name}" - boot_volume_key_name = "${local.prefix}${var.boot_volume_kms_key_name}" - boot_volume_existing_kms_guid = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_boot_volume ? module.existing_kms_crn_parser[0].service_instance : var.existing_boot_volume_kms_key_crn != null ? module.existing_boot_volume_kms_key_crn_parser[0].service_instance : var.kms_encryption_enabled_cluster ? module.kms[0].kms_guid : null - boot_volume_kms_account_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_boot_volume ? module.existing_kms_crn_parser[0].account_id : var.existing_boot_volume_kms_key_crn != null ? module.existing_boot_volume_kms_key_crn_parser[0].account_id : var.kms_encryption_enabled_cluster ? module.kms[0].kms_account_id : null - boot_volume_kms_key_id = var.existing_kms_instance_crn != null && var.kms_encryption_enabled_boot_volume ? module.kms[0].keys[format("%s.%s", local.boot_volume_key_ring_name, local.boot_volume_key_name)].key_id : var.existing_boot_volume_kms_key_crn != null ? module.existing_boot_volume_kms_key_crn_parser[0].resource : var.kms_encryption_enabled_boot_volume ? module.kms[0].keys[format("%s.%s", local.boot_volume_key_ring_name, local.boot_volume_key_name)].key_id : null - parsed_service_name = var.existing_kms_instance_crn != null ? module.existing_kms_crn_parser[0].service_name : (var.existing_cluster_kms_key_crn != null ? module.existing_cluster_kms_key_crn_parser[0].service_name : null) - is_hpcs_key = local.parsed_service_name == "hs-crypto" ? true : false - - kms_config = var.kms_encryption_enabled_cluster ? { - crk_id = local.cluster_kms_key_id - instance_id = local.cluster_existing_kms_guid - private_endpoint = var.kms_endpoint_type == "private" ? true : false - account_id = local.cluster_kms_account_id - } : null - - keys = [ - var.kms_encryption_enabled_cluster ? { - key_ring_name = local.cluster_key_ring_name - existing_key_ring = false - keys = [ - { - key_name = local.cluster_key_name - standard_key = false - rotation_interval_month = 3 - dual_auth_delete_enabled = false - force_delete = true - } - ] - } : null, - var.kms_encryption_enabled_boot_volume ? { - key_ring_name = local.boot_volume_key_ring_name - existing_key_ring = false - keys = [ - { - key_name = local.boot_volume_key_name - standard_key = false - rotation_interval_month = 3 - dual_auth_delete_enabled = false - force_delete = true - } - ] - } : null - ] -} - -module "kms" { - count = (var.kms_encryption_enabled_boot_volume && var.existing_boot_volume_kms_key_crn == null) || (var.kms_encryption_enabled_cluster && var.existing_cluster_kms_key_crn == null) ? 1 : 0 - source = "terraform-ibm-modules/kms-all-inclusive/ibm" - version = "5.4.5" - resource_group_id = var.resource_group_id - region = var.region - create_key_protect_instance = var.existing_kms_instance_crn != null || var.existing_cluster_kms_key_crn != null || var.existing_boot_volume_kms_key_crn != null ? false : true - existing_kms_instance_crn = var.existing_kms_instance_crn - key_protect_instance_name = "${local.prefix}${var.kms_instance_name}" - key_protect_plan = var.kms_plan - rotation_enabled = var.rotation_enabled - rotation_interval_month = var.rotation_interval_month - dual_auth_delete_enabled = var.dual_auth_delete_enabled - enable_metrics = var.enable_metrics - key_create_import_access_enabled = var.key_create_import_access_enabled - key_protect_allowed_network = var.key_protect_allowed_network - key_ring_endpoint_type = var.kms_endpoint_type - key_endpoint_type = var.kms_endpoint_type - resource_tags = var.kms_resource_tags - access_tags = var.kms_access_tags - keys = [for key in local.keys : key if key != null] - cbr_rules = var.kms_cbr_rules -} - -################################################################################# -# Cloud Monitoring -################################################################################# - -module "existing_cloud_monitoring_crn_parser" { - count = var.existing_cloud_monitoring_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_cloud_monitoring_crn -} - -locals { - create_cloud_monitoring = var.existing_cloud_monitoring_crn == null - cloud_monitoring_crn = local.create_cloud_monitoring ? module.cloud_monitoring[0].crn : var.existing_cloud_monitoring_crn - cloud_monitoring_instance_name = "${local.prefix}${var.cloud_monitoring_instance_name}" - metrics_router_target_name = "${local.prefix}${var.metrics_routing_target_name}" - metrics_router_route_name = "${local.prefix}${var.metrics_routing_route_name}" - - default_metrics_router_route = var.enable_metrics_routing_to_cloud_monitoring ? [{ - name = local.metrics_router_route_name - rules = [{ - action = "send" - targets = [{ - id = module.metrics_routing[0].metrics_router_targets[local.metrics_router_target_name].id - }] - inclusion_filters = [] - }] - }] : [] -} - -module "cloud_monitoring" { - count = local.create_cloud_monitoring ? 1 : 0 - source = "terraform-ibm-modules/cloud-monitoring/ibm" - version = "1.11.0" - resource_group_id = var.resource_group_id - region = var.region - instance_name = local.cloud_monitoring_instance_name - plan = var.cloud_monitoring_plan - resource_tags = var.cloud_monitoring_resource_tags - access_tags = var.cloud_monitoring_access_tags - resource_keys = var.cloud_monitoring_resource_keys - disable_access_key_creation = var.disable_access_key_creation - service_endpoints = "public-and-private" - enable_platform_metrics = var.enable_platform_metrics - cbr_rules = var.cloud_monitoring_cbr_rules -} - -module "metrics_routing" { - count = var.enable_metrics_routing_to_cloud_monitoring ? 1 : 0 - source = "terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing" - version = "1.11.0" - metrics_router_targets = [ - { - destination_crn = local.cloud_monitoring_crn - target_name = local.metrics_router_target_name - target_region = var.region - skip_metrics_router_auth_policy = false - } - ] - - metrics_router_routes = length(var.metrics_router_routes) != 0 ? var.metrics_router_routes : local.default_metrics_router_route - metrics_router_settings = var.enable_primary_metadata_region ? { primary_metadata_region = var.region } : null -} - - - -######################################################################################################################## -# Event Notifications -######################################################################################################################## - -# If existing EN instance CRN passed, parse details from it -module "existing_en_crn_parser" { - count = var.existing_event_notifications_instance_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_event_notifications_instance_crn -} - -locals { - use_existing_en_instance = var.existing_event_notifications_instance_crn != null - existing_en_instance_guid = local.use_existing_en_instance ? module.existing_en_crn_parser[0].service_instance : null - eventnotification_guid = local.use_existing_en_instance ? local.existing_en_instance_guid : module.event_notifications[0].guid - eventnotification_crn = local.use_existing_en_instance ? var.existing_event_notifications_instance_crn : module.event_notifications[0].crn - en_cos_bucket_name = "${local.prefix}${var.en_cos_bucket_name}" -} - -module "event_notifications" { - count = local.use_existing_en_instance ? 0 : 1 - source = "terraform-ibm-modules/event-notifications/ibm" - version = "2.7.0" - resource_group_id = var.resource_group_id - region = var.region - name = "${local.prefix}${var.event_notifications_instance_name}" - plan = var.en_service_plan - tags = var.en_resource_tags - access_tags = var.en_access_tags - service_endpoints = var.en_service_endpoints - service_credential_names = var.en_service_credential_names - # KMS Related - kms_encryption_enabled = var.kms_encryption_enabled_cluster - kms_endpoint_url = (var.kms_encryption_enabled_boot_volume && var.existing_boot_volume_kms_key_crn == null) || (var.kms_encryption_enabled_cluster && var.existing_cluster_kms_key_crn == null) ? var.kms_endpoint_type == "private" ? module.kms[0].kms_private_endpoint : module.kms[0].kms_public_endpoint : var.kms_endpoint_url - existing_kms_instance_crn = var.existing_kms_instance_crn != null ? var.existing_kms_instance_crn : module.kms[0].key_protect_crn - root_key_id = local.cluster_kms_key_id - skip_en_kms_auth_policy = var.skip_event_notifications_kms_auth_policy - # COS Related - cos_integration_enabled = var.enable_collecting_failed_events - cos_bucket_name = var.existing_event_notifications_instance_crn == null && var.enable_collecting_failed_events ? module.en_cos_buckets[0].buckets[local.en_cos_bucket_name].bucket_name : null - cos_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id - skip_en_cos_auth_policy = var.skip_event_notifications_cos_auth_policy - cos_endpoint = var.existing_event_notifications_instance_crn == null && var.enable_collecting_failed_events ? "https://${module.en_cos_buckets[0].buckets[local.en_cos_bucket_name].s3_endpoint_direct}" : null - cbr_rules = var.en_cbr_rules -} - -locals { - bucket_config = [{ - access_tags = var.en_cos_bucket_access_tags - bucket_name = local.en_cos_bucket_name - add_bucket_name_suffix = var.append_random_bucket_name_suffix - kms_encryption_enabled = var.kms_encryption_enabled_buckets - kms_guid = local.cluster_existing_kms_guid - kms_key_crn = local.cluster_kms_key_crn - skip_iam_authorization_policy = false - management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = var.cos_buckets_class - resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id - region_location = var.region - activity_tracking = { - read_data_events = true - write_data_events = true - management_events = true - } - metrics_monitoring = { - usage_metrics_enabled = true - request_metrics_enabled = true - metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn - } - force_delete = true - }] -} - -module "en_cos_buckets" { - count = var.enable_collecting_failed_events && var.existing_event_notifications_instance_crn == null ? 1 : 0 - source = "terraform-ibm-modules/cos/ibm//modules/buckets" - version = "10.5.8" - bucket_configs = local.bucket_config -} - -######################################################################################################################## -# Service Credentials -######################################################################################################################## - -# If existing EN instance CRN passed, parse details from it -module "existing_sm_crn_parser" { - count = var.existing_secrets_manager_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_secrets_manager_crn -} - -locals { - en_service_credential_secrets = [ - for service_credentials in var.en_service_credential_secrets : { - secret_group_name = service_credentials.secret_group_name - secret_group_description = service_credentials.secret_group_description - existing_secret_group = service_credentials.existing_secret_group - secrets = [ - for secret in service_credentials.service_credentials : { - secret_name = secret.secret_name - secret_labels = secret.secret_labels - secret_auto_rotation = secret.secret_auto_rotation - secret_auto_rotation_unit = secret.secret_auto_rotation_unit - secret_auto_rotation_interval = secret.secret_auto_rotation_interval - service_credentials_ttl = secret.service_credentials_ttl - service_credential_secret_description = secret.service_credential_secret_description - service_credentials_source_service_role_crn = secret.service_credentials_source_service_role_crn - service_credentials_source_service_crn = local.eventnotification_crn - secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6 - } - ] - } - ] -} - -# create a service authorization between Secrets Manager and the target service (Event Notification) -resource "ibm_iam_authorization_policy" "en_secrets_manager_key_manager" { - count = var.skip_event_notifications_secrets_manager_auth_policy || var.existing_secrets_manager_crn == null ? 0 : 1 - source_service_name = "secrets-manager" - source_resource_instance_id = local.existing_secrets_manager_instance_guid - target_service_name = "event-notifications" - target_resource_instance_id = local.eventnotification_guid - roles = ["Key Manager"] - description = "Allow Secrets Manager instance to manage key for the event-notification instance" -} - -# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 -resource "time_sleep" "wait_for_en_authorization_policy" { - depends_on = [ibm_iam_authorization_policy.en_secrets_manager_key_manager] - create_duration = "30s" -} - -module "en_secrets_manager_service_credentials" { - count = length(local.en_service_credential_secrets) > 0 ? 1 : 0 - depends_on = [time_sleep.wait_for_en_authorization_policy] - source = "terraform-ibm-modules/secrets-manager/ibm//modules/secrets" - version = "2.11.9" - existing_sm_instance_guid = local.existing_secrets_manager_instance_guid - existing_sm_instance_region = local.existing_secrets_manager_instance_region - endpoint_type = var.secrets_manager_endpoint_type - secrets = local.en_service_credential_secrets -} - -################################################################################# -# Secrets Manager -################################################################################# - -locals { - enable_secrets_manager_cluster = var.existing_secrets_manager_crn == null ? true : false - parsed_existing_secrets_manager_crn = var.existing_secrets_manager_crn != null ? split(":", var.existing_secrets_manager_crn) : [] - secrets_manager_guid = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[7] : null) : module.secrets_manager[0].secrets_manager_guid - secrets_manager_crn = var.existing_secrets_manager_crn != null ? var.existing_secrets_manager_crn : module.secrets_manager[0].secrets_manager_crn - secrets_manager_region = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[5] : null) : module.secrets_manager[0].secrets_manager_region - secret_groups_with_prefix = [ - for group in var.secret_groups : merge(group, { - access_group_name = group.access_group_name != null ? "${local.prefix}${group.access_group_name}" : null - }) - ] -} - -module "secrets_manager_crn_parser" { - count = var.existing_secrets_manager_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_secrets_manager_crn -} - -module "secrets_manager" { - count = local.enable_secrets_manager_cluster ? 1 : 0 - source = "terraform-ibm-modules/secrets-manager/ibm" - version = "2.11.9" - existing_sm_instance_crn = var.existing_secrets_manager_crn - resource_group_id = var.resource_group_id - region = var.region - secrets_manager_name = "${local.prefix}${var.secrets_manager_instance_name}" - sm_service_plan = var.secrets_manager_service_plan - sm_tags = var.secrets_manager_resource_tags - skip_iam_authorization_policy = var.skip_secrets_manager_iam_auth_policy - # kms dependency - is_hpcs_key = local.is_hpcs_key - kms_encryption_enabled = var.kms_encryption_enabled_cluster - kms_key_crn = local.cluster_kms_key_crn - skip_kms_iam_authorization_policy = var.skip_secrets_manager_kms_iam_auth_policy #|| local.create_cross_account_auth_policy - # event notifications dependency - enable_event_notification = true - existing_en_instance_crn = local.eventnotification_crn - skip_en_iam_authorization_policy = var.skip_secrets_manager_event_notifications_iam_auth_policy - cbr_rules = var.secrets_manager_cbr_rules - endpoint_type = var.secrets_manager_endpoint_type - allowed_network = var.secrets_manager_allowed_network - secrets = local.secret_groups_with_prefix -} - -################################################################################# -# Secrets Manager Event Notifications Configuration -################################################################################# - -locals { - parsed_existing_en_instance_crn = split(":", local.eventnotification_crn) - existing_en_guid = length(local.parsed_existing_en_instance_crn) > 0 ? local.parsed_existing_en_instance_crn[7] : null -} - -data "ibm_en_destinations" "en_sm_destinations" { - # if existing SM instance CRN is passed (!= null), then never do data lookup for EN destinations - count = var.existing_secrets_manager_crn == null && local.enable_secrets_manager_cluster ? 1 : 0 - instance_guid = local.existing_en_guid -} - -# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5533 -resource "time_sleep" "wait_for_secrets_manager" { - # if existing SM instance CRN is passed (!= null), then never work with EN - count = var.existing_secrets_manager_crn == null && local.enable_secrets_manager_cluster ? 1 : 0 - depends_on = [module.secrets_manager] - - create_duration = "30s" -} - -resource "ibm_en_topic" "en_sm_topic" { - # if existing SM instance CRN is passed (!= null), then never create EN topic - count = var.existing_secrets_manager_crn == null && local.enable_secrets_manager_cluster ? 1 : 0 - depends_on = [time_sleep.wait_for_secrets_manager] - instance_guid = local.existing_en_guid - name = "Topic for Secrets Manager instance ${module.secrets_manager[0].secrets_manager_guid}" - description = "Topic for Secrets Manager events routing" - sources { - id = local.secrets_manager_crn - rules { - enabled = true - event_type_filter = "$.*" - } - } -} - -resource "ibm_en_subscription_email" "en_email_subscription" { - # if existing SM instance CRN is passed (!= null), then never create EN email subscription - count = var.existing_secrets_manager_crn == null && length(var.event_notifications_email_list) > 0 && local.enable_secrets_manager_cluster ? 1 : 0 - instance_guid = local.existing_en_guid - name = "Email for Secrets Manager Subscription" - description = "Subscription for Secret Manager Events" - destination_id = [for s in toset(data.ibm_en_destinations.en_sm_destinations[count.index].destinations) : s.id if s.type == "smtp_ibm"][0] - topic_id = ibm_en_topic.en_sm_topic[count.index].topic_id - attributes { - add_notification_payload = true - reply_to_mail = var.event_notifications_reply_to_email - reply_to_name = "Secret Manager Event Notifications Bot" - from_name = var.event_notifications_from_email - invited = var.event_notifications_email_list - } -} - -################################################################################# -# COS -################################################################################# - -locals { - create_cos_instance = var.existing_cos_instance_crn == null ? true : false - existing_secrets_manager_instance_guid = var.existing_secrets_manager_crn != null ? module.secrets_manager_crn_parser[0].service_instance : local.enable_secrets_manager_cluster ? module.secrets_manager[0].secrets_manager_guid : "" - existing_secrets_manager_instance_region = var.existing_secrets_manager_crn != null ? module.secrets_manager_crn_parser[0].region : local.enable_secrets_manager_cluster ? module.secrets_manager[0].secrets_manager_region : "" - - cos_service_credential_secrets = [ - for service_credentials in var.service_cred : { - secret_group_name = service_credentials.secret_group_name - secret_group_description = service_credentials.secret_group_description - existing_secret_group = service_credentials.existing_secret_group - secrets = [ - for secret in service_credentials.service_credentials : { - secret_name = secret.secret_name - secret_labels = secret.secret_labels - secret_auto_rotation = secret.secret_auto_rotation - secret_auto_rotation_unit = secret.secret_auto_rotation_unit - secret_auto_rotation_interval = secret.secret_auto_rotation_interval - service_credentials_ttl = secret.service_credentials_ttl - service_credential_secret_description = secret.service_credential_secret_description - service_credentials_source_service_role_crn = secret.service_credentials_source_service_role_crn - service_credentials_source_service_crn = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_id - secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6 - } - ] - } - ] -} - -module "existing_cos_instance_crn_parser" { - count = var.existing_cos_instance_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.3.0" - crn = var.existing_cos_instance_crn -} - -module "cos" { - count = local.create_cos_instance != false ? 1 : 0 - source = "terraform-ibm-modules/cos/ibm//modules/fscloud" - version = "10.5.9" - resource_group_id = var.resource_group_id - create_cos_instance = local.create_cos_instance - cos_instance_name = "${local.prefix}${var.cos_instance_name}" - resource_keys = [] - cos_plan = var.cos_instance_plan - cos_tags = var.cos_instance_resource_tags - access_tags = var.cos_instance_access_tags - instance_cbr_rules = var.cos_instance_cbr_rules -} - -################################################################################# -# Secrets Manager service credentials for COS -################################################################################# - -# create s2s auth policy with Secrets Manager -resource "ibm_iam_authorization_policy" "cos_secrets_manager_key_manager" { - count = !var.skip_secrets_manager_cos_iam_auth_policy && (var.existing_secrets_manager_crn != null || local.enable_secrets_manager_cluster) ? 1 : 0 - source_service_name = "secrets-manager" - source_resource_instance_id = local.existing_secrets_manager_instance_guid - target_service_name = "cloud-object-storage" - target_resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_guid - roles = ["Key Manager"] - description = "Allow Secrets Manager with instance id ${local.existing_secrets_manager_instance_guid} to manage key for the COS instance" -} - -# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 -resource "time_sleep" "wait_for_cos_authorization_policy" { - count = length(local.cos_service_credential_secrets) > 0 ? 1 : 0 - depends_on = [ibm_iam_authorization_policy.cos_secrets_manager_key_manager] - create_duration = "30s" -} - -module "cos_secrets_manager_service_credentials" { - count = length(local.cos_service_credential_secrets) > 0 ? 1 : 0 - depends_on = [time_sleep.wait_for_cos_authorization_policy] - source = "terraform-ibm-modules/secrets-manager/ibm//modules/secrets" - version = "2.11.9" - existing_sm_instance_guid = local.existing_secrets_manager_instance_guid - existing_sm_instance_region = local.existing_secrets_manager_instance_region - endpoint_type = var.secrets_manager_endpoint_type - secrets = local.cos_service_credential_secrets -} - -################################################################################# -# Cloud Logs -################################################################################# - -locals { - cloud_logs_instance_name = "${local.prefix}${var.cloud_logs_instance_name}" - create_cloud_logs = var.existing_cloud_logs_crn == null - cloud_logs_crn = local.create_cloud_logs ? module.cloud_logs[0].crn : var.existing_cloud_logs_crn - - data_bucket_name = "${local.prefix}${var.cloud_logs_data_cos_bucket_name}" - metrics_bucket_name = "${local.prefix}${var.cloud_logs_metrics_cos_bucket_name}" - cos_instance_guid = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_guid -} - -module "cloud_logs" { - depends_on = [time_sleep.wait_for_cos_authorization_policy[0]] - count = local.create_cloud_logs ? 1 : 0 - source = "terraform-ibm-modules/cloud-logs/ibm" - version = "1.10.0" - resource_group_id = var.resource_group_id - region = var.region - instance_name = local.cloud_logs_instance_name - plan = "standard" # not a variable because there is only one option - resource_tags = var.cloud_logs_resource_tags - access_tags = var.cloud_logs_access_tags - retention_period = var.cloud_logs_retention_period - service_endpoints = "public-and-private" # not a variable because there is only one option - existing_event_notifications_instances = var.existing_event_notifications_instances - cbr_rules = var.cloud_logs_cbr_rules - data_storage = { - logs_data = { - enabled = true - bucket_crn = module.cloud_logs_buckets.buckets[local.data_bucket_name].bucket_crn - bucket_endpoint = module.cloud_logs_buckets.buckets[local.data_bucket_name].s3_endpoint_direct - skip_cos_auth_policy = var.skip_cloud_logs_cos_auth_policy - }, - metrics_data = { - enabled = true - bucket_crn = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].bucket_crn - bucket_endpoint = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].s3_endpoint_direct - skip_cos_auth_policy = var.skip_cloud_logs_cos_auth_policy - } - } - logs_routing_tenant_regions = var.logs_routing_tenant_regions - skip_logs_routing_auth_policy = var.skip_logs_routing_auth_policy - policies = var.logs_policies -} - -module "cloud_logs_buckets" { - source = "terraform-ibm-modules/cos/ibm//modules/buckets" - version = "10.5.8" - bucket_configs = [ - { - bucket_name = local.data_bucket_name - kms_key_crn = var.kms_encryption_enabled_buckets ? local.cluster_kms_key_crn : null - kms_guid = var.kms_encryption_enabled_buckets ? local.cluster_existing_kms_guid : null - kms_encryption_enabled = var.kms_encryption_enabled_buckets - region_location = var.region - resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id - add_bucket_name_suffix = var.append_random_bucket_name_suffix - management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = var.cos_buckets_class - force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." - activity_tracking = { - read_data_events = true - write_data_events = true - management_events = true - } - metrics_monitoring = { - usage_metrics_enabled = true - request_metrics_enabled = true - metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn - } - }, - { - bucket_name = local.metrics_bucket_name - kms_key_crn = var.kms_encryption_enabled_buckets ? local.cluster_kms_key_crn : null - kms_guid = var.kms_encryption_enabled_buckets ? local.cluster_existing_kms_guid : null - kms_encryption_enabled = var.kms_encryption_enabled_buckets - region_location = var.region - resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id - add_bucket_name_suffix = var.append_random_bucket_name_suffix - management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = var.cos_buckets_class - skip_iam_authorization_policy = true - force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." - activity_tracking = { - read_data_events = true - write_data_events = true - management_events = true - } - metrics_monitoring = { - usage_metrics_enabled = true - request_metrics_enabled = true - metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn - } - } - ] -} - -################################################################################# -# Activity Tracker -################################################################################# -locals { - activity_tracker_cos_target_bucket_name = try("${local.prefix}${var.activity_tracker_cos_target_bucket_name}", var.activity_tracker_cos_target_bucket_name) - cos_target_bucket_name = var.existing_activity_tracker_cos_target_bucket_name != null ? var.existing_activity_tracker_cos_target_bucket_name : var.enable_activity_tracker_event_routing_to_cos_bucket ? module.at_cos_bucket[0].buckets[local.activity_tracker_cos_target_bucket_name].bucket_name : null - cos_target_bucket_endpoint = var.existing_activity_tracker_cos_target_bucket_endpoint != null ? var.existing_activity_tracker_cos_target_bucket_endpoint : var.enable_activity_tracker_event_routing_to_cos_bucket ? module.at_cos_bucket[0].buckets[local.activity_tracker_cos_target_bucket_name].s3_endpoint_private : null - cos_target_name = var.cos_target_name != null ? var.cos_target_name : local.create_cos_instance ? module.cos[0].cos_instance_name : try("${local.prefix}-cos-target", "cos-target") - cloud_logs_target_name = var.cloud_logs_target_name != null ? var.cloud_logs_target_name : local.create_cos_instance ? module.cos[0].cos_instance_name : try("${local.prefix}-cloud-logs-target", "cloud-logs-target") - activity_tracker_cos_route_name = var.activity_tracker_cos_route_name != null ? var.activity_tracker_cos_route_name : try("${local.prefix}at-cos-route", "at-cos-route") - activity_tracker_cloud_logs_route_name = var.activity_tracker_cloud_logs_route_name != null ? var.activity_tracker_cloud_logs_route_name : try("${local.prefix}at-cloud-logs-route", "at-cloud-logs-route") - activity_tracker_bucket_config = var.existing_activity_tracker_cos_target_bucket_name == null && var.enable_activity_tracker_event_routing_to_cos_bucket ? { - class = var.activity_tracker_cos_target_bucket_class - name = local.activity_tracker_cos_target_bucket_name - tag = var.activity_tracker_cos_bucket_access_tags - } : null - - - bucket_retention_configs = local.activity_tracker_bucket_config != null ? { (local.activity_tracker_cos_target_bucket_name) = var.activity_tracker_cos_bucket_retention_policy } : null - - at_buckets_config = local.activity_tracker_bucket_config != null ? [local.activity_tracker_bucket_config] : [] - - archive_rule = length(local.at_buckets_config) != 0 ? { - enable = true - days = 90 - type = "Glacier" - } : null - - expire_rule = length(local.at_buckets_config) != 0 ? { - enable = true - days = 366 - } : null - - activity_tracker_cos_route = var.enable_activity_tracker_event_routing_to_cos_bucket ? [{ - route_name = local.activity_tracker_cos_route_name - locations = ["*"] - target_ids = [module.activity_tracker.activity_tracker_targets[local.cos_target_name].id] - }] : [] - - activity_tracker_cloud_logs_route = var.enable_activity_tracker_event_routing_to_cloud_logs ? [{ - route_name = local.activity_tracker_cloud_logs_route_name - locations = ["*"] - target_ids = [module.activity_tracker.activity_tracker_targets[local.cloud_logs_target_name].id] - }] : [] - activity_tracker_routes = concat(local.activity_tracker_cos_route, local.activity_tracker_cloud_logs_route) - -} - -module "activity_tracker" { - source = "terraform-ibm-modules/activity-tracker/ibm" - version = "1.5.0" - cos_targets = var.enable_activity_tracker_event_routing_to_cos_bucket ? [ - { - bucket_name = local.cos_target_bucket_name - endpoint = local.cos_target_bucket_endpoint - instance_id = var.existing_cos_instance_crn != null ? var.existing_cos_instance_crn : module.cos[0].cos_instance_crn - target_region = var.region - target_name = local.cos_target_name - skip_atracker_cos_iam_auth_policy = var.skip_activity_tracker_cos_auth_policy - service_to_service_enabled = true - } - ] : [] - - cloud_logs_targets = var.enable_activity_tracker_event_routing_to_cloud_logs ? [ - { - instance_id = var.existing_cloud_logs_crn != null ? var.existing_cloud_logs_crn : module.cloud_logs[0].crn - target_region = var.region - target_name = local.cloud_logs_target_name - } - ] : [] - - # Routes - activity_tracker_routes = local.activity_tracker_routes -} - -module "at_cos_bucket" { - count = length(coalesce(local.at_buckets_config, [])) != 0 ? 1 : 0 # no need to call COS module if consumer is using existing COS bucket - source = "terraform-ibm-modules/cos/ibm//modules/buckets" - version = "10.5.8" - bucket_configs = [ - for value in local.at_buckets_config : - { - access_tags = value.tag - bucket_name = value.name - add_bucket_name_suffix = var.append_random_bucket_name_suffix - kms_guid = local.cluster_existing_kms_guid - kms_encryption_enabled = var.kms_encryption_enabled_buckets - kms_key_crn = local.cluster_kms_key_crn - skip_iam_authorization_policy = false - management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = value.class - resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id - region_location = var.region - force_delete = true - archive_rule = local.archive_rule - expire_rule = local.expire_rule - retention_rule = lookup(local.bucket_retention_configs, value.name, null) - metrics_monitoring = { - usage_metrics_enabled = true - request_metrics_enabled = true - # If `existing_monitoring_crn` is not passed, metrics are sent to the instance associated to the container's location unless otherwise specified in the Metrics Router service configuration. - metrics_monitoring_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn - } - activity_tracking = { - read_data_events = true - write_data_events = true - management_events = true - } - } - ] -} - -######################################################################################################################## -# App Config -######################################################################################################################## -module "app_config" { - source = "terraform-ibm-modules/app-configuration/ibm" - version = "1.14.2" - resource_group_id = var.resource_group_id - region = var.region - app_config_name = "${local.prefix}${var.app_config_name}" - app_config_plan = var.app_config_plan - app_config_service_endpoints = var.app_config_service_endpoints - app_config_tags = var.app_config_tags - app_config_collections = var.app_config_collections - enable_config_aggregator = var.enable_config_aggregator - config_aggregator_trusted_profile_name = "${local.prefix}${var.config_aggregator_trusted_profile_name}" - config_aggregator_resource_collection_regions = var.config_aggregator_resource_collection_regions - config_aggregator_enterprise_id = var.config_aggregator_enterprise_id - config_aggregator_enterprise_trusted_profile_name = "${local.prefix}${var.config_aggregator_enterprise_trusted_profile_name}" - config_aggregator_enterprise_trusted_profile_template_name = "${local.prefix}${var.config_aggregator_enterprise_trusted_profile_template_name}" - config_aggregator_enterprise_account_group_ids_to_assign = var.config_aggregator_enterprise_account_group_ids_to_assign - config_aggregator_enterprise_account_ids_to_assign = var.config_aggregator_enterprise_account_ids_to_assign - cbr_rules = var.apprapp_cbr_rules - kms_encryption_enabled = var.kms_encryption_enabled_cluster - skip_app_config_kms_auth_policy = var.skip_app_config_kms_auth_policy - existing_kms_instance_crn = var.existing_kms_instance_crn != null ? var.existing_kms_instance_crn : module.kms[0].key_protect_crn - kms_endpoint_url = (var.kms_encryption_enabled_boot_volume && var.existing_boot_volume_kms_key_crn == null) || (var.kms_encryption_enabled_cluster && var.existing_cluster_kms_key_crn == null) ? var.kms_endpoint_type == "private" ? module.kms[0].kms_private_endpoint : module.kms[0].kms_public_endpoint : var.kms_endpoint_url - root_key_id = local.cluster_kms_key_id - enable_event_notifications = true - skip_app_config_event_notifications_auth_policy = var.skip_app_config_event_notifications_auth_policy - existing_event_notifications_instance_crn = local.eventnotification_crn - event_notifications_endpoint_url = var.existing_event_notifications_instance_crn != null ? var.event_notifications_endpoint_url : var.en_service_endpoints == "private" ? module.event_notifications[0].event_notifications_private_endpoint : module.event_notifications[0].event_notifications_public_endpoint - app_config_event_notifications_source_name = "${local.prefix}${var.app_config_event_notifications_source_name}" - event_notifications_integration_description = "The App Configuration integration to send notifications of events to users from the Event Notifications instance GUID ${local.existing_en_guid}" -} - -####################################################################################################################### -# App Configuration Event Notifications Configuration -####################################################################################################################### - -data "ibm_en_destinations" "en_apprapp_destinations" { - instance_guid = local.existing_en_guid -} - -resource "ibm_en_topic" "en_apprapp_topic" { - depends_on = [module.app_config] - instance_guid = local.existing_en_guid - name = "Topic for App Configuration instance ${module.app_config.app_config_guid}" - description = "Topic for App Configuration events routing" - sources { - id = module.app_config.app_config_crn - rules { - enabled = true - event_type_filter = "$.*" - } - } -} - -resource "ibm_en_subscription_email" "apprapp_email_subscription" { - count = length(var.event_notifications_email_list) > 0 ? 1 : 0 - instance_guid = local.existing_en_guid - name = "Email for App Configuration Subscription" - description = "Subscription for App Configuration Events" - destination_id = [for s in toset(data.ibm_en_destinations.en_apprapp_destinations[count.index].destinations) : s.id if s.type == "smtp_ibm"][0] - topic_id = ibm_en_topic.en_apprapp_topic[count.index].topic_id - attributes { - add_notification_payload = true - reply_to_mail = var.event_notifications_reply_to_email - reply_to_name = "App Configuration Event Notifications Bot" - from_name = var.event_notifications_from_email - invited = var.event_notifications_email_list - } -} - -################################################################################# -# SCC Workload Protection -################################################################################# - -locals { - scc_workload_protection_instance_name = "${local.prefix}${var.scc_workload_protection_instance_name}" - scc_workload_protection_resource_key_name = "${local.prefix}${var.scc_workload_protection_instance_name}-key" -} - -module "scc_wp" { - source = "terraform-ibm-modules/scc-workload-protection/ibm" - version = "1.16.4" - name = local.scc_workload_protection_instance_name - region = var.region - resource_group_id = var.resource_group_id - resource_tags = var.scc_workload_protection_instance_tags - resource_key_name = local.scc_workload_protection_resource_key_name - resource_key_tags = var.scc_workload_protection_resource_key_tags - cloud_monitoring_instance_crn = var.existing_cloud_monitoring_crn != null ? var.existing_cloud_monitoring_crn : module.cloud_monitoring[0].crn - access_tags = var.scc_workload_protection_access_tags - scc_wp_service_plan = var.scc_workload_protection_service_plan - app_config_crn = module.app_config.app_config_crn - scc_workload_protection_trusted_profile_name = "${local.prefix}${var.scc_workload_protection_trusted_profile_name}" - cbr_rules = var.scc_wp_cbr_rules - cspm_enabled = var.cspm_enabled -} - -############################################################################# -# COS Bucket for VPC flow logs -############################################################################# - - -locals { - vpc_flow_logs_bucket_name = "${local.prefix}${var.flow_logs_cos_bucket_name}" - # configuration for the flow logs bucket - flow_logs_bucket_config = [{ - access_tags = var.vpc_flow_logs_access_tags - bucket_name = local.vpc_flow_logs_bucket_name - add_bucket_name_suffix = var.append_random_bucket_name_suffix - kms_encryption_enabled = var.kms_encryption_enabled_buckets - kms_guid = local.cluster_existing_kms_guid - kms_key_crn = local.cluster_kms_key_crn - skip_iam_authorization_policy = true - management_endpoint_type = var.management_endpoint_type_for_buckets - storage_class = var.cos_buckets_class - resource_instance_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_id - region_location = var.region - force_delete = true - archive_rule = var.flow_logs_cos_bucket_archive_days != null ? { - enable = true - days = var.flow_logs_cos_bucket_archive_days - type = var.flow_logs_cos_bucket_archive_type - } : null - expire_rule = var.flow_logs_cos_bucket_expire_days != null ? { - enable = true - days = var.flow_logs_cos_bucket_expire_days - } : null - retention_rule = var.flow_logs_cos_bucket_enable_retention ? { - default = var.flow_logs_cos_bucket_default_retention_days - maximum = var.flow_logs_cos_bucket_maximum_retention_days - minimum = var.flow_logs_cos_bucket_minimum_retention_days - permanent = var.flow_logs_cos_bucket_enable_permanent_retention - } : null - object_versioning_enabled = var.flow_logs_cos_bucket_enable_object_versioning - }] -} - -# Create COS bucket using the defined bucket configuration -module "vpc_cos_buckets" { - count = var.enable_vpc_flow_logs ? 1 : 0 - source = "terraform-ibm-modules/cos/ibm//modules/buckets" - version = "10.5.8" - bucket_configs = local.flow_logs_bucket_config -} - -############################################################################# -# VPC -############################################################################# - -locals { - # create 'use_public_gateways' object - public_gateway_object = { - for key, value in var.subnets : key => value != null ? length([for sub in value : sub.public_gateway if sub.public_gateway]) > 0 ? [for sub in value : sub.public_gateway if sub.public_gateway][0] : false : false - } -} - -# Create VPC -module "vpc" { - source = "terraform-ibm-modules/landing-zone-vpc/ibm" - version = "8.9.1" - resource_group_id = var.resource_group_id - region = var.region - create_vpc = true - name = var.vpc_name - prefix = local.prefix != "" ? trimspace(var.prefix) : null - tags = var.vpc_resource_tags - access_tags = var.vpc_access_tags - subnets = var.subnets - default_network_acl_name = var.default_network_acl_name - default_security_group_name = var.default_security_group_name - default_routing_table_name = var.default_routing_table_name - network_acls = var.network_acls - security_group_rules = var.security_group_rules - clean_default_sg_acl = var.clean_default_security_group_acl - use_public_gateways = local.public_gateway_object - address_prefixes = var.address_prefixes - routes = var.routes - enable_vpc_flow_logs = var.enable_vpc_flow_logs - create_authorization_policy_vpc_to_cos = !var.skip_vpc_cos_iam_auth_policy - existing_cos_instance_guid = var.enable_vpc_flow_logs ? local.cos_instance_guid : null - existing_storage_bucket_name = var.enable_vpc_flow_logs ? module.vpc_cos_buckets[0].buckets[local.vpc_flow_logs_bucket_name].bucket_name : null - vpn_gateways = var.vpn_gateways -} - -############################################################################# -# VPE Gateway -############################################################################# - -module "vpe_gateway" { - source = "terraform-ibm-modules/vpe-gateway/ibm" - version = "4.6.6" - resource_group_id = var.resource_group_id - region = var.region - prefix = local.prefix - security_group_ids = var.vpe_gateway_security_group_ids - vpc_name = module.vpc.vpc_name - vpc_id = module.vpc.vpc_id - subnet_zone_list = module.vpc.subnet_zone_list - cloud_services = var.vpe_gateway_cloud_services - cloud_service_by_crn = var.vpe_gateway_cloud_service_by_crn - service_endpoints = var.vpe_gateway_service_endpoints - reserved_ips = var.vpe_gateway_reserved_ips -} - -######################################################################################################################## -# OCP VPC cluster -######################################################################################################################## - -locals { - vpc_subnets = { - # The default behavior is to deploy the worker pool across all subnets within the VPC. - "default" = [ - for subnet in module.vpc.subnet_zone_list : - { - id = subnet.id - zone = subnet.zone - cidr_block = subnet.cidr - } - ] - } - - worker_pools = concat([ - { - subnet_prefix = "default" - pool_name = "default" - machine_type = var.default_worker_pool_machine_type - workers_per_zone = var.default_worker_pool_workers_per_zone - resource_group_id = var.resource_group_id - operating_system = var.default_worker_pool_operating_system - labels = var.default_worker_pool_labels - minSize = var.default_pool_minimum_number_of_nodes - maxSize = var.default_pool_maximum_number_of_nodes - enableAutoscaling = var.enable_autoscaling_for_default_pool - boot_volume_encryption_kms_config = { - crk = local.boot_volume_kms_key_id - kms_instance_id = local.boot_volume_existing_kms_guid - kms_account_id = local.boot_volume_kms_account_id - } - additional_security_group_ids = var.additional_security_group_ids - } - ], [for pool in var.additional_worker_pools : merge(pool, { resource_group_id = var.resource_group_id - boot_volume_encryption_kms_config = { - crk = local.boot_volume_kms_key_id - kms_instance_id = local.boot_volume_existing_kms_guid - kms_account_id = local.boot_volume_kms_account_id - } }) if length(pool.vpc_subnets) > 0], - [for pool in var.additional_worker_pools : { - pool_name = pool.pool_name - machine_type = pool.machine_type - workers_per_zone = pool.workers_per_zone - resource_group_id = var.resource_group_id - operating_system = pool.operating_system - labels = pool.labels - minSize = pool.minSize - secondary_storage = pool.secondary_storage - maxSize = pool.maxSize - enableAutoscaling = pool.enableAutoscaling - boot_volume_encryption_kms_config = { - crk = local.boot_volume_kms_key_id - kms_instance_id = local.boot_volume_existing_kms_guid - kms_account_id = local.boot_volume_kms_account_id - } - additional_security_group_ids = pool.additional_security_group_ids - subnet_prefix = "default" - } if length(pool.vpc_subnets) == 0]) - - # Managing the ODF version accordingly, as it changes with each OCP version. - addons = lookup(var.addons, "openshift-data-foundation", null) != null ? lookup(var.addons["openshift-data-foundation"], "version", null) == null ? { for key, value in var.addons : - key => value != null ? { - version = lookup(value, "version", null) == null && key == "openshift-data-foundation" ? "${var.openshift_version}.0" : lookup(value, "version", null) - parameters_json = lookup(value, "parameters_json", null) - } : null } : var.addons : var.addons -} - -module "ocp_base" { - source = "../.." - resource_group_id = var.resource_group_id - region = var.region - tags = var.cluster_resource_tags - cluster_name = local.cluster_name - force_delete_storage = true - use_existing_cos = true - existing_cos_id = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_crn - vpc_id = module.vpc.vpc_id - vpc_subnets = local.vpc_subnets - ocp_version = var.openshift_version - worker_pools = local.worker_pools - access_tags = var.access_tags - ocp_entitlement = var.ocp_entitlement - additional_lb_security_group_ids = var.additional_lb_security_group_ids - additional_vpe_security_group_ids = var.additional_vpe_security_group_ids - addons = local.addons - allow_default_worker_pool_replacement = var.allow_default_worker_pool_replacement - attach_ibm_managed_security_group = var.attach_ibm_managed_security_group - cluster_config_endpoint_type = var.cluster_config_endpoint_type - cbr_rules = var.ocp_cbr_rules - cluster_ready_when = var.cluster_ready_when - custom_security_group_ids = var.custom_security_group_ids - disable_outbound_traffic_protection = var.allow_outbound_traffic - disable_public_endpoint = !var.allow_public_access_to_cluster_management - enable_ocp_console = var.enable_ocp_console - ignore_worker_pool_size_changes = var.ignore_worker_pool_size_changes - kms_config = local.kms_config - manage_all_addons = var.manage_all_addons - number_of_lbs = var.number_of_lbs - pod_subnet_cidr = var.pod_subnet_cidr - service_subnet_cidr = var.service_subnet_cidr - verify_worker_network_readiness = var.verify_worker_network_readiness - worker_pools_taints = var.worker_pools_taints - enable_secrets_manager_integration = var.enable_secrets_manager_integration - existing_secrets_manager_instance_crn = local.secrets_manager_crn - secrets_manager_secret_group_id = var.secrets_manager_secret_group_id != null ? var.secrets_manager_secret_group_id : (var.enable_secrets_manager_integration ? module.secret_group[0].secret_group_id : null) - skip_ocp_secrets_manager_iam_auth_policy = var.skip_ocp_secrets_manager_iam_auth_policy -} - -resource "terraform_data" "delete_secrets" { - count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 - input = { - secret_id = module.secret_group[0].secret_group_id - provider_visibility = var.provider_visibility - secrets_manager_instance_id = local.secrets_manager_guid - secrets_manager_region = local.secrets_manager_region - secrets_manager_endpoint = var.secrets_manager_endpoint_type - } - # api key in triggers_replace to avoid it to be printed out in clear text in terraform_data output - triggers_replace = { - api_key = var.ibmcloud_api_key - } - provisioner "local-exec" { - when = destroy - command = "${path.module}/../../solutions/fully-configurable/scripts/delete_secrets.sh ${self.input.secret_id} ${self.input.provider_visibility} ${self.input.secrets_manager_instance_id} ${self.input.secrets_manager_region} ${self.input.secrets_manager_endpoint}" - interpreter = ["/bin/bash", "-c"] - - environment = { - API_KEY = self.triggers_replace.api_key - } - } -} - -module "secret_group" { - count = var.enable_secrets_manager_integration && var.secrets_manager_secret_group_id == null ? 1 : 0 - source = "terraform-ibm-modules/secrets-manager-secret-group/ibm" - version = "1.3.15" - region = local.secrets_manager_region - secrets_manager_guid = local.secrets_manager_guid - secret_group_name = module.ocp_base.cluster_id - secret_group_description = "Secret group for storing ingress certificates for cluster ${local.cluster_name} with id: ${module.ocp_base.cluster_id}" - endpoint_type = var.secrets_manager_endpoint_type -} diff --git a/modules/containerized_app_landing_zone/outputs.tf b/modules/containerized_app_landing_zone/outputs.tf deleted file mode 100644 index a2009339b..000000000 --- a/modules/containerized_app_landing_zone/outputs.tf +++ /dev/null @@ -1,326 +0,0 @@ -############################################################################## -# Cluster Outputs -############################################################################## - -output "cluster_name" { - value = module.ocp_base.cluster_name - description = "The name of the provisioned OpenShift cluster." -} - -output "cluster_id" { - value = module.ocp_base.cluster_id - description = "The unique identifier assigned to the provisioned OpenShift cluster." -} - -output "cluster_crn" { - description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." - value = module.ocp_base.cluster_crn -} - -output "workerpools" { - description = "A list of worker pools associated with the provisioned cluster" - value = module.ocp_base.workerpools -} - -output "ocp_version" { - description = "The version of OpenShift running on the provisioned cluster." - value = module.ocp_base.ocp_version -} - -############################################################################## -# VPC -############################################################################## - -output "vpc_name" { - description = "Name of the VPC created." - value = module.vpc.vpc_name -} - -output "vpc_id" { - description = "ID of the VPC created." - value = module.vpc.vpc_id -} - -output "vpc_crn" { - description = "CRN of the VPC created." - value = module.vpc.vpc_crn -} - -############################################################################## -# Public Gateways -############################################################################## - -output "public_gateways" { - description = "Map of the public gateways by zone." - value = module.vpc.public_gateways -} - -############################################################################## -# VPC flow logs -############################################################################## - -output "vpc_flow_logs" { - description = "Details of the VPC flow logs collector." - value = module.vpc.vpc_flow_logs -} - -############################################################################## -# Network ACLs -############################################################################## - -output "network_acls" { - description = "List of shortnames and IDs of network ACLs." - value = module.vpc.network_acls -} - -############################################################################## -# Subnet Outputs -############################################################################## - -output "subnet_ids" { - description = "The IDs of the subnets." - value = module.vpc.subnet_ids -} - -output "private_path_subnet_id" { - description = "The IDs of the subnets." - value = length(module.vpc.subnet_ids) > 0 ? module.vpc.subnet_ids[0] : null -} - -output "subnet_detail_list" { - description = "A list of subnets containing names, CIDR blocks, and zones." - value = module.vpc.subnet_detail_list -} - -output "subnet_zone_list" { - description = "A list of subnet IDs and subnet zones." - value = module.vpc.subnet_zone_list -} - -output "subnet_detail_map" { - description = "A map of subnets containing IDs, CIDR blocks, and zones." - value = module.vpc.subnet_detail_map -} - -############################################################################## -# VPN Gateways Outputs -############################################################################## - -output "vpn_gateways_name" { - description = "List of names of VPN gateways." - value = module.vpc.vpn_gateways_name -} - -output "vpn_gateways_data" { - description = "Details of VPN gateways data." - value = module.vpc.vpn_gateways_data -} - -############################################################################## -# VPE Outputs -############################################################################## - -output "vpe_ips" { - description = "The reserved IPs for endpoint gateways." - value = module.vpe_gateway.vpe_ips -} - -output "vpe_crn" { - description = "The CRN of the endpoint gateway." - value = module.vpe_gateway.crn -} - -############################################################################## -# KMS Outputs -############################################################################## - -output "kms_guid" { - description = "KMS instance GUID" - value = local.cluster_existing_kms_guid -} - -output "kms_account_id" { - description = "The account ID of the KMS instance." - value = local.cluster_kms_account_id -} - -output "kms_instance_crn" { - value = var.existing_kms_instance_crn == null ? var.kms_encryption_enabled_cluster ? module.kms[0].key_protect_crn : null : var.existing_kms_instance_crn - description = "The CRN of the KMS instance" -} - -############################################################################## -# Events Notification Outputs -############################################################################## - -output "events_notification_crn" { - description = "Event Notification crn" - value = local.eventnotification_crn -} - -output "events_notification_guid" { - description = "Event Notification guid" - value = local.eventnotification_guid -} - - -############################################################################## -# Secrets Manager Outputs -############################################################################## - -output "secrets_manager_guid" { - description = "GUID of Secrets Manager instance" - value = local.secrets_manager_guid -} - -output "secrets_manager_crn" { - value = local.secrets_manager_crn - description = "CRN of the Secrets Manager instance" -} - -output "secrets_manager_region" { - value = local.secrets_manager_region - description = "Region of the Secrets Manager instance" -} - -############################################################################## -# COS Outputs -############################################################################## - -output "cos_instance_crn" { - description = "COS instance crn" - value = var.existing_cos_instance_crn != null ? var.existing_cos_instance_crn : module.cos[0].cos_instance_crn -} - -output "cos_instance_guid" { - description = "COS instance guid" - value = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].service_instance : module.cos[0].cos_instance_guid -} - -output "cos_instance_id" { - description = "COS instance ID" - value = var.existing_cos_instance_crn != null ? module.existing_cos_instance_crn_parser[0].resource : module.cos[0].cos_instance_crn -} - - -############################################################################## -# Cloud Monitoring Outputs -############################################################################## - -output "cloud_monitoring_crn" { - value = local.cloud_monitoring_crn - description = "The id of the provisioned IBM Cloud Monitoring instance." -} -output "cloud_monitoring_name" { - value = local.create_cloud_monitoring ? module.cloud_monitoring[0].name : null - description = "The name of the provisioned IBM Cloud Monitoring instance." -} - -output "cloud_monitoring_guid" { - value = local.create_cloud_monitoring ? module.cloud_monitoring[0].guid : module.existing_cloud_monitoring_crn_parser[0].service_instance - description = "The guid of the provisioned IBM Cloud Monitoring instance." -} - -output "cloud_monitoring_access_key_name" { - value = local.create_cloud_monitoring ? module.cloud_monitoring[0].access_key_name : null - description = "The name of the IBM Cloud Monitoring access key for agents to use" -} - -output "cloud_monitoring_access_key" { - value = local.create_cloud_monitoring ? module.cloud_monitoring[0].access_key : null - description = "The IBM Cloud Monitoring access key for agents to use" - sensitive = true -} - -############################################################################## -# Cloud Logs Outputs -############################################################################## - -output "cloud_logs_crn" { - value = local.cloud_logs_crn - description = "The id of the provisioned IBM Cloud Logs instance." -} - -output "cloud_logs_guid" { - value = local.create_cloud_logs ? module.cloud_logs[0].guid : null - description = "The guid of the provisioned IBM Cloud Logs instance." -} - -output "cloud_logs_name" { - value = local.create_cloud_logs ? module.cloud_logs[0].name : null - description = "The name of the provisioned IBM Cloud Logs instance." -} - -output "cloud_logs_ingress_endpoint" { - value = local.create_cloud_logs ? module.cloud_logs[0].ingress_endpoint : null - description = "The public ingress endpoint of the provisioned IBM Cloud Logs instance." -} - -output "cloud_logs_ingress_private_endpoint" { - value = local.create_cloud_logs ? module.cloud_logs[0].ingress_private_endpoint : null - description = "The private ingress endpoint of the provisioned IBM Cloud Logs instance." -} - -output "cloud_logs_logs_policies_details" { - value = local.create_cloud_logs ? module.cloud_logs[0].logs_policies_details : null - description = "The details of the IBM Cloud logs policies created." -} - -output "logs_bucket_crn" { - description = "Logs Cloud Object Storage bucket CRN" - value = module.cloud_logs_buckets.buckets[local.data_bucket_name].bucket_crn -} - -output "metrics_bucket_crn" { - description = "Metrics Cloud Object Storage bucket CRN" - value = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].bucket_crn -} - -############################################################################## -# Activity Tracker Event Routing Outputs -############################################################################## - -output "activity_tracker_cos_target_bucket_name" { - value = var.existing_activity_tracker_cos_target_bucket_name == null ? var.enable_activity_tracker_event_routing_to_cos_bucket ? module.at_cos_bucket[0].buckets[local.activity_tracker_cos_target_bucket_name].bucket_name : null : var.existing_activity_tracker_cos_target_bucket_name - description = "he name of the object storage bucket which is set as activity tracker event routing target to collect audit events." -} - -output "activity_tracker_targets" { - value = module.activity_tracker.activity_tracker_targets - description = "The map of created Activity Tracker Event Routing targets" -} - -output "activity_tracker_routes" { - value = module.activity_tracker.activity_tracker_routes - description = "The map of created Activity Tracker Event Routing routes" -} - -############################################################################## -# SCC-WP Outputs -############################################################################## - -output "scc_workload_protection_id" { - description = "SCC Workload Protection instance ID" - value = module.scc_wp.id -} - -output "scc_workload_protection_crn" { - description = "SCC Workload Protection instance CRN" - value = module.scc_wp.crn -} - -output "scc_workload_protection_name" { - description = "SCC Workload Protection instance name" - value = module.scc_wp.name -} - -output "scc_workload_protection_ingestion_endpoint" { - description = "SCC Workload Protection instance ingestion endpoint" - value = module.scc_wp.name -} - -output "scc_workload_protection_api_endpoint" { - description = "SCC Workload Protection API endpoint" - value = module.scc_wp.api_endpoint - sensitive = true -} diff --git a/modules/containerized_app_landing_zone/variables.tf b/modules/containerized_app_landing_zone/variables.tf deleted file mode 100644 index 3d3008d71..000000000 --- a/modules/containerized_app_landing_zone/variables.tf +++ /dev/null @@ -1,2352 +0,0 @@ -variable "ibmcloud_api_key" { - type = string - description = "The IBM Cloud api token" - sensitive = true -} - -variable "provider_visibility" { - description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`." - type = string - default = "private" - validation { - condition = contains(["public", "private", "public-and-private"], var.provider_visibility) - error_message = "Invalid visibility option. Allowed values are `public`, `private`, or `public-and-private`." - } -} - -variable "prefix" { - type = string - nullable = true - description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string." - - validation { - # - null and empty string is allowed - # - Must not contain consecutive hyphens (--): length(regexall("--", var.prefix)) == 0 - # - Starts with a lowercase letter: [a-z] - # - Contains only lowercase letters (a–z), digits (0–9), and hyphens (-) - # - Must not end with a hyphen (-): [a-z0-9] - condition = (var.prefix == null || var.prefix == "" ? true : - alltrue([ - can(regex("^[a-z][-a-z0-9]*[a-z0-9]$", var.prefix)), - length(regexall("--", var.prefix)) == 0 - ]) - ) - error_message = "Prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It must not end with a hyphen('-'), and cannot contain consecutive hyphens ('--')." - } - - validation { - # must not exceed 16 characters in length - condition = var.prefix == null || var.prefix == "" ? true : length(var.prefix) <= 16 - error_message = "Prefix must not exceed 16 characters." - } -} - -variable "region" { - type = string - description = "The region to provision all resources in." - default = "us-south" - nullable = false -} - -variable "resource_group_id" { - type = string - description = "The ID of an existing IBM Cloud resource group where the cluster is grouped." -} - -############################################################## -# KMS Related -############################################################## -variable "kms_encryption_enabled_cluster" { - description = "Set to true to enable KMS encryption for the cluster's Object Storage bucket. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn`." - type = bool - default = false - nullable = false - - validation { - condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_cluster : true - error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_cluster' to true." - } - - validation { - condition = var.existing_cluster_kms_key_crn != null ? var.kms_encryption_enabled_cluster : true - error_message = "If passing a value for 'existing_cluster_kms_key_crn', you should set 'kms_encryption_enabled_cluster' to true." - } -} - -variable "existing_kms_instance_crn" { - type = string - default = null - description = "The CRN of an existing KMS instance." - - validation { - condition = anytrue([ - can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)), - var.existing_kms_instance_crn == null, - ]) - error_message = "The provided KMS instance CRN in the input 'existing_kms_instance_crn' in not valid." - } -} - -variable "existing_cluster_kms_key_crn" { - type = string - default = null - description = "The CRN of an existing KMS key to use for encrypting the Object Storage of the Cluster. If no value is set for this variable, specify a value for `existing_kms_instance_crn` variable to create a key ring and key." - - validation { - condition = anytrue([ - can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_cluster_kms_key_crn)), - var.existing_cluster_kms_key_crn == null, - ]) - error_message = "The provided KMS key CRN in the input 'existing_cluster_kms_key_crn' in not valid." - } - - validation { - condition = var.existing_cluster_kms_key_crn != null ? var.existing_kms_instance_crn == null : true - error_message = "A value should not be passed for 'existing_kms_instance_crn' when passing an existing key value using the 'existing_cluster_kms_key_crn' input." - } - -} - -variable "kms_endpoint_type" { - type = string - description = "The endpoint for communicating with the KMS instance. Possible values: `public`, `private`. Applies only if `kms_encryption_enabled_cluster` is true" - default = "private" - nullable = false - validation { - condition = can(regex("^(public|private)$", var.kms_endpoint_type)) - error_message = "The kms_endpoint_type value must be 'public' or 'private'." - } -} - -variable "cluster_kms_key_ring_name" { - type = string - default = "cluster-key-ring" - description = "The name of the key ring to be created for the cluster's Object Storage bucket encryption key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." -} - -variable "cluster_kms_key_name" { - type = string - default = "cluster-key" - description = "The name of the key to be created for the cluster's Object Storage bucket encryption. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." -} - -variable "kms_encryption_enabled_boot_volume" { - type = bool - description = "Set this to true to control the encryption keys used to encrypt the data that for the block storage volumes for VPC. If set to false, the data is encrypted by using randomly generated keys. For more info on encrypting block storage volumes, see https://cloud.ibm.com/docs/vpc?topic=vpc-creating-instances-byok" - default = false - nullable = false - - validation { - condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_boot_volume || var.kms_encryption_enabled_cluster : true - error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_boot_volume' to true." - } - - validation { - condition = var.existing_boot_volume_kms_key_crn != null ? var.kms_encryption_enabled_boot_volume : true - error_message = "If passing a value for 'existing_boot_volume_kms_key_crn', you should set 'kms_encryption_enabled_boot_volume' to true." - } -} - -variable "existing_boot_volume_kms_key_crn" { - type = string - default = null - description = "The CRN of an existing KMS key to use to encrypt the the block storage volumes for VPC. If no value is set for this variable, specify a value for either the `existing_kms_instance_crn` variable to create a key ring and key." - - validation { - condition = anytrue([ - can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_boot_volume_kms_key_crn)), - var.existing_boot_volume_kms_key_crn == null, - ]) - error_message = "The provided KMS key CRN in the input 'existing_boot_volume_kms_key_crn' in not valid." - } -} - -variable "boot_volume_kms_key_ring_name" { - type = string - default = "boot-volume-key-ring" - description = "The name for the key ring created for the block storage volumes key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." -} - -variable "boot_volume_kms_key_name" { - type = string - default = "boot-volume-key" - description = "The name for the key created for the block storage volumes. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." -} - -variable "kms_instance_name" { - type = string - description = "The name to give the Key Protect instance that that is created by this module. Only used if 'create_key_protect_instance' is set to `true`." - default = "key-protect" -} - -variable "kms_plan" { - type = string - description = "Plan for the Key Protect instance. Supported values are 'tiered-pricing' and 'cross-region-resiliency'. Only used if 'create_key_protect_instance' is set to `true`." - default = "tiered-pricing" - # validation performed in terraform-ibm-key-protect module -} - -variable "rotation_enabled" { - type = bool - description = "If set to `true`, a rotation policy is enabled on the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`." - default = true -} - -variable "rotation_interval_month" { - type = number - description = "Specifies how often keys are rotated in months. Value must be between `1` and `12` inclusive. Only used if 'create_key_protect_instance' is set to `true`." - default = 1 -} - -variable "dual_auth_delete_enabled" { - type = bool - description = "If set to `true`, a dual authorization policy is enabled on the Key Protect instance. After the dual authorization policy is set on the instance, it cannot be reverted. An instance with dual authorization policy enabled cannot be destroyed by using Terraform. Only used if 'create_key_protect_instance' is set to `true`." - default = false -} - -variable "enable_metrics" { - type = bool - description = "Set to `true` to enable metrics on the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`. In order to view metrics, you need an IBM Cloud Monitoring (Sysdig) instance that is located in the same region as the Key Protect instance. After you provision a Monitoring instance, enable platform metrics to monitor your Key Protect instance." - default = true -} - -variable "key_create_import_access_enabled" { - type = bool - description = "If set to `true`, a key create and import access policy is enabled on the instance of Key Protect. Only used if 'create_key_protect_instance' is set to `true`." - default = true -} - -variable "key_protect_allowed_network" { - type = string - description = "Allowed network types for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create_key_protect_instance' is set to `true`." - default = "private-only" - validation { - condition = can(regex("private-only|public-and-private", var.key_protect_allowed_network)) - error_message = "The `key_protect_allowed_network` value must be 'private-only' or 'public-and-private'." - } -} - -variable "kms_resource_tags" { - type = list(string) - description = "Optional list of tags to add to the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`." - default = [] -} - -variable "kms_access_tags" { - type = list(string) - description = "A list of access tags to apply to the Key Protect instance. Only used if 'create_key_protect_instance' is set to `true`." - default = [] -} - -variable "kms_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The context-based restrictions rule to create. Only one rule is allowed." - default = [] - # Validation happens in the rule module - # NOTE: Context-based restriction rules applies to Key Protect instances only and is not supported by Hyper Protect Crypto Services (HPCS) instances - - validation { - condition = var.existing_kms_instance_crn == null ? true : length(regexall(".*hscrypto.*", var.existing_kms_instance_crn)) > 0 ? length(var.kms_cbr_rules) == 0 : true - error_message = "When passing a Hyper Protect Crypto Services (HPCS) instance as a value for `existing_kms_instance_crn` you cannot provide `kms_cbr_rules`. Context-based restrictions are not supported by HPCS instances. For more information, go to [services that integrate with context-based restrictions](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis#cbr-adopters)." - } - validation { - condition = length(var.kms_cbr_rules) <= 1 - error_message = "Only one CBR rule is allowed." - } -} - -######################################################################################################################## -# Event Notifications -######################################################################################################################## - -variable "event_notifications_instance_name" { - type = string - description = "The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format." - default = "event-notifications" -} - -variable "en_service_plan" { - type = string - description = "The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard`." - default = "standard" - validation { - condition = contains(["lite", "standard"], var.en_service_plan) - error_message = "The specified pricing plan is not available. The following plans are supported: `Lite`, `Standard`" - } -} - -variable "en_service_endpoints" { - type = string - description = "Specify whether you want to enable public, private, or both public and private service endpoints. Possible values: `public`, `private`, `public-and-private`." - default = "private" - validation { - condition = contains(["public", "private", "public-and-private"], var.en_service_endpoints) - error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`, `public-and-private`" - } -} - -variable "en_resource_tags" { - type = list(string) - description = "The list of tags to add to the Event Notifications instance." - default = [] -} - -variable "en_access_tags" { - type = list(string) - description = "A list of access tags to apply to the Event Notifications instance created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." - default = [] - - validation { - condition = alltrue([ - for tag in var.en_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 - ]) - error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\". For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limit)." - } -} - -variable "en_service_credential_names" { - type = map(string) - description = "A mapping of names and associated roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/blob/main/solutions/fully-configurable/DA-types.md#service-credentials-)." - default = {} - - validation { - condition = alltrue([for name, role in var.en_service_credential_names : contains(["Manager", "Writer", "Reader", "Event Source Manager", "Channel Editor", "Event Notification Publisher", "Status Reporter", "Device Manager", "Email Sender", "Custom Email Status Reporter"], role)]) - error_message = "The specified service credential role is not valid. The following values are valid for service credential roles: 'Manager', 'Writer', 'Reader', 'Event Source Manager', 'Channel Editor', 'Event Notification Publisher', 'Status Reporter', 'Device Manager', 'Email Sender', 'Custom Email Status Reporter'" - } -} - -variable "kms_endpoint_url" { - type = string - description = "The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input." - default = null -} - -variable "skip_event_notifications_kms_auth_policy" { - type = bool - description = "Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." - default = false -} - -variable "enable_collecting_failed_events" { - type = bool - description = "Set to true to enable Cloud Object Storage integration. If enabled, you must also provide a Cloud Object Storage instance (for storing failed events) using the `existing_cos_instance_crn` variable. For more information, [see here](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-cfe-integrations)." - default = true -} - -variable "en_cos_bucket_name" { - type = string - description = "The name to use when creating the Object Storage bucket for the storage of failed delivery events. Bucket names are globally unique. If `add_bucket_name_suffix` is set to `true`, a random 4 character string is added to this name to help ensure that the bucket name is unique. If a `prefix` input variable is specified, it is added to this name in the `-value` format." - default = "base-event-notifications-bucket" -} - -variable "en_cos_bucket_access_tags" { - type = list(string) - description = "A list of access tags to apply to the Cloud Object Storage bucket created by the solution. For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." - default = [] - - validation { - condition = alltrue([ - for tag in var.en_cos_bucket_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 - ]) - error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\". For more information, [see here](https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits)." - } -} - -variable "skip_event_notifications_secrets_manager_auth_policy" { - type = bool - default = false - description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing_secrets_manager_crn' is not passed." -} - -variable "en_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md)." - default = [] -} - -variable "en_service_credential_secrets" { # pragma: allowlist secret - type = list(object({ - secret_group_name = string # pragma: allowlist secret - secret_group_description = optional(string) # pragma: allowlist secret - existing_secret_group = optional(bool) # pragma: allowlist secret - service_credentials = list(object({ # pragma: allowlist secret - secret_name = string # pragma: allowlist secret - service_credentials_source_service_role_crn = string # pragma: allowlist secret - secret_labels = optional(list(string)) # pragma: allowlist secret - secret_auto_rotation = optional(bool) # pragma: allowlist secret - secret_auto_rotation_unit = optional(string) # pragma: allowlist secret - secret_auto_rotation_interval = optional(number) # pragma: allowlist secret - service_credentials_ttl = optional(string) # pragma: allowlist secret - service_credential_secret_description = optional(string) # pragma: allowlist secret - - })) - })) - default = [] - description = "Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets)." - - validation { - # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select Event Notifications and select the role - condition = alltrue([ - for group in var.en_service_credential_secrets : alltrue([ - # crn:v?:bluemix; two non-empty segments; three possibly empty segments; :serviceRole or role: non-empty segment - for credential in group.service_credentials : can(regex("^crn:v[0-9]:bluemix(:..*){2}(:.*){3}:(serviceRole|role):..*$", credential.service_credentials_source_service_role_crn)) - ]) - ]) - error_message = "Provided value of `service_credentials_source_service_role_crn` is not valid. Refer [this](https://cloud.ibm.com/iam/roles) for allowed role/values." - } - validation { - condition = length(var.en_service_credential_secrets) > 0 ? var.existing_secrets_manager_crn != null : true - error_message = "'existing_secrets_manager_crn' is required when adding service credentials with the 'service_credential_secrets' input." - } - -} - -variable "skip_event_notifications_cos_auth_policy" { - type = bool - description = "Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy." - default = false -} - -variable "event_notifications_endpoint_url" { - type = string - description = "The URL of the Event Notifications service endpoint to use for notifying configuration changes. For more information on the endpoint URL for Event Notifications, go to [Service endpoints](https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-regions-endpoints#en-service-endpoints). It is required if `enable_event_notifications` is set to true." - default = null -} - -############################################################## -# Secrets Manager -############################################################## - -variable "secrets_manager_instance_name" { - type = string - description = "The name to give the Secrets Manager instance provisioned by this solution. If a prefix input variable is specified, it is added to the value in the `-value` format. Applies only if `existing_secrets_manager_crn` is not provided." - default = "secrets-manager" -} - -variable "existing_secrets_manager_crn" { - type = string - description = "The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created." - default = null -} - -variable "secrets_manager_service_plan" { - type = string - description = "The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. You can create only one Trial instance of Secrets Manager per account. Before you can create a new Trial instance, you must delete the existing Trial instance and its reclamation." - default = "standard" - validation { - condition = var.existing_secrets_manager_crn == null ? contains(["standard", "trial"], var.secrets_manager_service_plan) : true - error_message = "Only 'standard' and 'trial' are allowed values for 'secrets_manager_service_plan'. Applies only if not providing a value for the 'existing_secrets_manager_crn' input." - } -} - -variable "skip_secrets_manager_iam_auth_policy" { - type = bool - description = "Whether to skip the creation of the IAM authorization policies required to enable the IAM credentials engine (if you are using an existing Secrets Manager instance, attempting to re-create can cause conflicts if the policies already exist). If set to false, policies will be created that grants the Secrets Manager instance 'Operator' access to the IAM identity service, and 'Groups Service Member Manage' access to the IAM groups service." - default = false -} - -variable "secrets_manager_resource_tags" { - type = list(string) - description = "The list of resource tags you want to associate with your Secrets Manager instance. Applies only if `existing_secrets_manager_crn` is not provided." - default = [] -} - -variable "secrets_manager_endpoint_type" { - type = string - description = "The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications." - default = "private" - validation { - condition = contains(["public", "private"], var.secrets_manager_endpoint_type) - error_message = "The specified service endpoint is not a valid selection!" - } -} - -variable "secrets_manager_allowed_network" { - type = string - description = "The types of service endpoints to set on the Secrets Manager instance. Possible values are `private-only` or `public-and-private`." - default = "private-only" - validation { - condition = contains(["private-only", "public-and-private"], var.secrets_manager_allowed_network) - error_message = "The specified allowed_network is not a valid selection!" - } -} - -variable "skip_secrets_manager_kms_iam_auth_policy" { - type = bool - description = "Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances in the resource group to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable." - default = false -} - -variable "secret_groups" { - type = list(object({ - secret_group_name = string - secret_group_description = optional(string) - create_access_group = optional(bool, true) - access_group_name = optional(string) - access_group_roles = optional(list(string), ["SecretsReader"]) - access_group_tags = optional(list(string)) - })) - description = "Secret Manager secret group and access group configurations. If a prefix input variable is specified, it is added to the `access_group_name` value in the `-value` format. If you do not wish to create any groups, set the value to `[]`." - nullable = false - default = [ - { - secret_group_name = "General" - secret_group_description = "A general purpose secrets group with an associated access group which has a secrets reader role" - create_access_group = true - access_group_name = "general-secrets-group-access-group" - access_group_roles = ["SecretsReader"] - } - ] - validation { - error_message = "The name of the secret group cannot be null or empty string." - condition = length([ - for group in var.secret_groups : - true if(group.secret_group_name == "" || group.secret_group_name == null) - ]) == 0 - } - validation { - error_message = "When creating an access group, a list of roles must be specified." - condition = length([ - for group in var.secret_groups : - true if(group.create_access_group && group.access_group_roles == null) - ]) == 0 - } -} - -variable "secrets_manager_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "(Optional, list) List of CBR rules to create." - default = [] - # Validation happens in the rule module -} - -######################################################################################################################## -# Event Notifications -######################################################################################################################## - -variable "existing_event_notifications_instance_crn" { - type = string - description = "The CRN of the Event Notifications service used to enable lifecycle notifications for your Secrets Manager instance." - default = null -} - -variable "skip_secrets_manager_event_notifications_iam_auth_policy" { - type = bool - description = "If set to true, this skips the creation of a service to service authorization from Secrets Manager to Event Notifications. If false, the service to service authorization is created." - default = false -} - -variable "event_notifications_email_list" { - type = list(string) - description = "The list of email address to target out when Secrets Manager triggers an event" - default = [] -} - -variable "event_notifications_from_email" { - type = string - description = "The email address used to send any Secrets Manager event coming via Event Notifications" - default = "compliancealert@ibm.com" -} - -variable "event_notifications_reply_to_email" { - type = string - description = "The email address specified in the 'reply_to' section for any Secret Manager event coming via Event Notifications" - default = "no-reply@ibm.com" -} - -############################################################## -# COS -############################################################## - -variable "existing_cos_instance_crn" { - type = string - description = "The CRN of an existing Object Storage instance." - default = null -} - -variable "cos_instance_name" { - description = "The name for the IBM Cloud Object Storage instance provisioned by this solution. If a value is passed for `prefix`, the instance will be named with the prefix value in the format of `-value`." - type = string - default = "cos-instance" -} - -variable "cos_instance_plan" { - description = "The plan to use when Object Storage instances are created." - type = string - default = "standard" - validation { - condition = contains(["standard", "cos-one-rate-plan"], var.cos_instance_plan) - error_message = "The specified plan is not a valid selection!" - } -} - -variable "cos_instance_resource_tags" { - description = "A list of resource tags to apply to the Object Storage instance." - type = list(string) - default = [] -} - -variable "cos_instance_access_tags" { - type = list(string) - description = "A list of access tags to apply to the Object Storage instance created by the module." - default = [] -} - -variable "skip_secrets_manager_cos_iam_auth_policy" { - type = bool - default = false - description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Cloud Object Storage. Set to `true` to use an existing policy." -} - -variable "service_cred" { # pragma: allowlist secret - type = list(object({ - secret_group_name = string # pragma: allowlist secret - secret_group_description = optional(string) # pragma: allowlist secret - existing_secret_group = optional(bool) # pragma: allowlist secret - service_credentials = list(object({ # pragma: allowlist secret - secret_name = string # pragma: allowlist secret - service_credentials_source_service_role_crn = string # pragma: allowlist secret - secret_labels = optional(list(string)) # pragma: allowlist secret - secret_auto_rotation = optional(bool) # pragma: allowlist secret - secret_auto_rotation_unit = optional(string) # pragma: allowlist secret - secret_auto_rotation_interval = optional(number) # pragma: allowlist secret - service_credentials_ttl = optional(string) # pragma: allowlist secret - service_credential_secret_description = optional(string) # pragma: allowlist secret - - })) - })) - default = [] - description = "Service configuration for COS." - - validation { - # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select Cloud Object Storage and select the role - condition = alltrue([ - for group in var.service_cred : alltrue([ - # crn:v?:bluemix; two non-empty segments; three possibly empty segments; :serviceRole or role: non-empty segment - for credential in group.service_credentials : can(regex("^crn:v[0-9]:bluemix(:..*){2}(:.*){3}:(serviceRole|role):..*$", credential.service_credentials_source_service_role_crn)) - ]) - ]) - error_message = "service_credentials_source_service_role_crn must be a serviceRole CRN. See https://cloud.ibm.com/iam/roles" - } - - validation { - condition = length(var.service_cred) > 0 ? var.existing_secrets_manager_crn != null : true - error_message = "When passing a value for 'service_credential', a value must be passed for 'existing_secrets_manager_crn'." - } -} - -variable "cos_instance_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - tags = optional(list(object({ - name = string - value = string - })), []) - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The list of context-based restriction rules to create for the instance." - default = [] - # Validation happens in the rule module -} - -######################################################################################################################## -# Cloud Monitoring -######################################################################################################################## - -variable "existing_cloud_monitoring_crn" { - type = string - default = null - description = "The CRN of an existing Cloud Monitoring instance. If not supplied, a new instance will be created." -} - -variable "cloud_monitoring_instance_name" { - type = string - description = "The name of the IBM Cloud Monitoring instance to create. If the prefix variable is passed, the name of the instance is prefixed to the value in the `-value` format." - default = "cloud-monitoring" -} - -variable "cloud_monitoring_resource_tags" { - type = list(string) - description = "Tags associated with the IBM Cloud Monitoring instance (Optional, array of strings)." - default = [] -} - -variable "cloud_monitoring_access_tags" { - type = list(string) - description = "A list of access tags to apply to the IBM Cloud Monitoring instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." - default = [] -} - -variable "disable_access_key_creation" { - type = bool - description = "When set to true, disables the creation of a default manager access key which is required by agents to ingest metrics." - default = false -} - -variable "cloud_monitoring_resource_keys" { - description = "A list of maps representing resource keys to create for the IBM Cloud Monitoring instance. Each entry defines a single resource key. Use this list to manage custom keys and handle key rotation." - type = list(object({ - name = string - generate_hmac_credentials = optional(bool, false) # pragma: allowlist secret - role = optional(string, "Manager") - service_id_crn = optional(string, null) - })) - default = [] -} - -variable "cloud_monitoring_plan" { - type = string - description = "The IBM Cloud Monitoring plan to provision. Available values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." - default = "graduated-tier" - - validation { - condition = can(regex("^lite$|^graduated-tier$|^graduated-tier-sysdig-secure-plus-monitor$", var.cloud_monitoring_plan)) - error_message = "The plan value must be one of the following: lite, graduated-tier and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only)." - } - - validation { - condition = (var.cloud_monitoring_plan != "graduated-tier-sysdig-secure-plus-monitor") || var.region == "eu-fr2" - error_message = "When cloud_monitoring_plan is graduated-tier-sysdig-secure-plus-monitor region should be set to eu-fr2." - } -} - -variable "enable_platform_metrics" { - type = bool - description = "When set to `true`, the IBM Cloud Monitoring instance collects the platform metrics." - default = false -} - -######################################################################################################################## -# Metrics Routing -######################################################################################################################## - -variable "metrics_routing_target_name" { - type = string - description = "The name of the IBM Cloud Metrics Routing target where metrics are collected. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format." - default = "cloud-monitoring-target" -} - -variable "metrics_routing_route_name" { - type = string - description = "The name of the IBM Cloud Metrics Routing route for the default route that indicate what metrics are routed in a region and where to store them. If the prefix variable is passed, the name of the target is prefixed to the value in the `-value` format." - default = "metrics-routing-route" -} - -variable "enable_metrics_routing_to_cloud_monitoring" { - type = bool - description = "Whether to enable metrics routing from IBM Cloud Metric Routing to Cloud Monitoring." - default = true -} - -variable "enable_primary_metadata_region" { - type = bool - description = "When set to `true`, sets `primary_metadata_region` to `region`, storing Metrics Router metadata in that region. When `false`, no region is set and the default global region is used. For new accounts, creating targets and routes will fail until primary_metadata_region is set, so it is recommended to default enable_primary_metadata_region to true." - default = true -} - -variable "metrics_router_routes" { - type = list(object({ - name = string - rules = list(object({ - action = string - targets = list(object({ - id = string - })) - inclusion_filters = list(object({ - operand = string - operator = string - values = list(string) - })) - })) - })) - default = [] - description = "Routes for IBM Cloud Metrics Routing." -} - -variable "cloud_monitoring_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The list of context-based restriction rules to create for the instance." - default = [] - # Validation happens in the rule module -} - -######################################################################################################################## -# Cloud Logs -######################################################################################################################## - -variable "existing_cloud_logs_crn" { - type = string - default = null - description = "The CRN of an existing Cloud Logs instance. If not supplied, a new instance will be created." -} - -variable "cloud_logs_instance_name" { - type = string - description = "The name of the IBM Cloud Logs instance to create. If a prefix input variable is specified, the prefix is added to the name in the `-` format." - default = "cloud-logs" -} - -variable "cloud_logs_resource_tags" { - type = list(string) - description = "Tags associated with the IBM Cloud Logs instance (Optional, array of strings)." - default = [] -} - -variable "cloud_logs_access_tags" { - type = list(string) - description = "A list of access tags to apply to the IBM Cloud Logs instance created by the DA. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." - default = [] -} - -variable "cloud_logs_retention_period" { - type = number - description = "The number of days IBM Cloud Logs will retain the logs data in Priority insights. Allowed values: 7, 14, 30, 60, 90." - default = 7 - - validation { - condition = contains([7, 14, 30, 60, 90], var.cloud_logs_retention_period) - error_message = "Valid values 'cloud_logs_retention_period' are: 7, 14, 30, 60, 90" - } -} - -variable "existing_event_notifications_instances" { - type = list(object({ - crn = string - integration_name = optional(string) - skip_iam_auth_policy = optional(bool, false) - })) - default = [] - description = "List of Event Notifications instance details for routing critical events that occur in your IBM Cloud Logs." -} - -variable "cloud_logs_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "(Optional, list) List of context-based restrictions rules to create." - default = [] -} - -variable "cloud_logs_data_cos_bucket_name" { - type = string - nullable = true - default = "cloud-logs-logs-bucket" - description = "The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format." -} - -variable "cloud_logs_metrics_cos_bucket_name" { - type = string - nullable = true - default = "cloud-logs-metrics-bucket" - description = "The name of an to be given to a new bucket inside the existing Object Storage instance to use for IBM Cloud Logs. If a prefix input variable is specified, the prefix is added to the name in the `-` format." -} - -variable "skip_cloud_logs_cos_auth_policy" { - type = bool - description = "To skip creating an IAM authorization policy that allows the IBM Cloud logs to write to the Cloud Object Storage bucket, set this variable to `true`." - default = false -} - - - -variable "kms_encryption_enabled_buckets" { - description = "Set to true to enable KMS encryption on the Object Storage buckets created for the IBM Cloud Logs instance. When set to true, a value must be passed for either `existing_cluster_kms_key_crn` or `existing_kms_instance_crn` (to create a new key). Can not be set to true if passing a value for `existing_cloud_logs_crn`." - type = bool - default = false - nullable = false - - validation { - condition = var.kms_encryption_enabled_buckets ? var.existing_cloud_logs_crn == null : true - error_message = "'kms_encryption_enabled_buckets' should be false if passing a value for 'existing_cloud_logs_crn' as existing Cloud Logs instance will already have a bucket attached." - } - - validation { - condition = var.existing_kms_instance_crn != null ? var.kms_encryption_enabled_buckets : true - error_message = "If passing a value for 'existing_kms_instance_crn', you should set 'kms_encryption_enabled_buckets' to true." - } - - validation { - condition = var.existing_cluster_kms_key_crn != null ? var.kms_encryption_enabled_buckets : true - error_message = "If passing a value for 'existing_cluster_kms_key_crn', you should set 'kms_encryption_enabled_buckets' to true." - } - - validation { - condition = var.kms_encryption_enabled_buckets ? ((var.existing_cluster_kms_key_crn != null || var.existing_kms_instance_crn != null) ? true : false) : true - error_message = "Either 'existing_cluster_kms_key_crn' or 'existing_kms_instance_crn' is required if 'kms_encryption_enabled_buckets' is set to true." - } -} - -variable "append_random_bucket_name_suffix" { - type = bool - description = "Append random generated suffix (4 characters long) to the newly provisioned IBM Cloud Logs Object Storage bucket names." - default = true -} - -variable "management_endpoint_type_for_buckets" { - description = "The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Possible values: `public`, `private`, `direct`. If you specify `private`, enable virtual routing and forwarding in your account, and the Terraform runtime must have access to the the IBM Cloud private network." - type = string - default = "direct" - validation { - condition = contains(["public", "private", "direct"], var.management_endpoint_type_for_buckets) - error_message = "The specified management_endpoint_type_for_buckets is not a valid selection!" - } -} - -variable "cos_buckets_class" { - type = string - default = "smart" - description = "The storage class of the newly provisioned IBM Cloud Logs Object Storage buckets. Possible values: `standard` or `smart`. Applies only if `existing_cloud_logs_crn` is not provided." - validation { - condition = contains(["standard", "smart"], var.cos_buckets_class) - error_message = "Allowed values for cos_bucket_class are \"standard\" or \"smart\"." - } -} - -############################################################################## -# Logs Routing -############################################################################## - -variable "logs_routing_tenant_regions" { - type = list(any) - default = [] - description = "Pass a list of regions to create a tenant for that is targeted to the Cloud Logs instance created by this module. To manage platform logs that are generated by IBM Cloud® services in a region of IBM Cloud, you must create a tenant in each region that you operate. Leave the list empty if you don't want to create any tenants. NOTE: You can only have 1 tenant per region in an account." - nullable = false -} - -variable "skip_logs_routing_auth_policy" { - description = "Whether to create an IAM authorization policy that permits the Logs Routing server 'Sender' access to the IBM Cloud Logs instance created by this Deployable Architecture." - type = bool - default = false -} - -variable "logs_policies" { - type = list(object({ - logs_policy_name = string - logs_policy_description = optional(string, null) - logs_policy_priority = string - application_rule = optional(list(object({ - name = string - rule_type_id = string - }))) - subsystem_rule = optional(list(object({ - name = string - rule_type_id = string - }))) - log_rules = optional(list(object({ - severities = list(string) - }))) - archive_retention = optional(list(object({ - id = string - }))) - })) - description = "Configuration of Cloud Logs policies." - default = [] - - validation { - condition = alltrue([for config in var.logs_policies : (length(config.logs_policy_name) <= 4096 ? true : false)]) - error_message = "Maximum length of logs_policy_name allowed is 4096 chars." - } - - validation { - condition = alltrue([for config in var.logs_policies : contains(["type_unspecified", "type_block", "type_low", "type_medium", "type_high"], config.logs_policy_priority)]) - error_message = "The specified priority for logs policy is not a valid selection. Allowed values are: type_unspecified, type_block, type_low, type_medium, type_high." - } - - validation { - condition = alltrue( - [for config in var.logs_policies : - (config.application_rule != null ? - (alltrue([for rule in config.application_rule : - contains(["unspecified", "is", "is_not", "start_with", "includes"], rule.rule_type_id)])) - : true) - ]) - error_message = "Identifier of application_rule 'rule_type_id' is not a valid selection. Allowed values are: unspecified, is, is_not, start_with, includes." - } - - validation { - condition = alltrue( - [for config in var.logs_policies : - (config.application_rule != null ? - (alltrue([for rule in config.application_rule : - can(regex("^[\\p{L}\\p{N}\\p{P}\\p{Z}\\p{S}\\p{M}]+$", rule.name)) && length(rule.name) <= 4096 && length(rule.name) > 1])) - : true) - ]) - error_message = "The name of the application_rule does not meet the required criteria." - } - - validation { - condition = alltrue( - [for config in var.logs_policies : - (config.log_rules != null && length(config.log_rules) > 0 ? true : false) - ]) - error_message = "The log_rules can not be empty and must contain at least 1 item." - } - - validation { - condition = alltrue( - [for config in var.logs_policies : - (config.log_rules != null ? - (alltrue([for rule in config.log_rules : - alltrue([for severity in rule["severities"] : - contains(["unspecified", "debug", "verbose", "info", "warning", "error", "critical"], severity)])])) - : true - )]) - error_message = "The 'severities' of log_rules is not a valid selection. Allowed values are: unspecified, debug, verbose, info, warning, error, critical." - } - - validation { - condition = alltrue( - [for config in var.logs_policies : - (config.subsystem_rule != null ? - (alltrue([for rule in config.subsystem_rule : - contains(["unspecified", "is", "is_not", "start_with", "includes"], rule.rule_type_id)])) - : true - )]) - error_message = "Identifier of subsystem_rule 'rule_type_id' is not a valid selection. Allowed values are: unspecified, is, is_not, start_with, includes." - } - - validation { - condition = alltrue( - [for config in var.logs_policies : - (config.subsystem_rule != null ? - (alltrue([for rule in config.subsystem_rule : - can(regex("^[\\p{L}\\p{N}\\p{P}\\p{Z}\\p{S}\\p{M}]+$", rule.name)) && length(rule.name) <= 4096 && length(rule.name) > 1])) - : true) - ]) - error_message = "The name of the subsystem_rule does not meet the required criteria." - } - - validation { - condition = alltrue( - [for config in var.logs_policies : - (config.archive_retention != null ? - (alltrue( - [for rule in config.archive_retention : can(regex("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", rule.id))] - )) : true - )]) - error_message = "The id of the archive_retention does not meet the required criteria." - } -} - -############################################################################## -# Activity Tracker Event Routing -############################################################################## - -variable "enable_activity_tracker_event_routing_to_cos_bucket" { - type = bool - description = "When set to `true`, you must provide a value for `existing_cos_instance_crn` to enable event routing from Activity Tracker to a Object Storage bucket." - default = true - - validation { - condition = var.enable_activity_tracker_event_routing_to_cos_bucket || var.enable_activity_tracker_event_routing_to_cloud_logs - error_message = "At least one of 'enable_activity_tracker_event_routing_to_cos_bucket' or 'enable_activity_tracker_event_routing_to_cloud_logs' must be true to route audit events to COS bucket or Cloud Logs instance." - } - -} - -variable "activity_tracker_cos_target_bucket_name" { - type = string - default = "at-events-cos-bucket" - description = "The name of the Cloud Object Storage bucket to create for the Cloud Object Storage target to store AT events. Cloud Object Storage bucket names are globally unique. If the `add_bucket_name_suffix` variable is set to `true`, 4 random characters are added to this name to ensure that the name of the bucket is globally unique. If the prefix input variable is passed, the name of the instance is prefixed to the value in the `-value` format." -} - -variable "existing_activity_tracker_cos_target_bucket_name" { - type = string - nullable = true - default = null - description = "The name of an existing bucket within the Cloud Object Storage instance in which to store IBM Cloud Activity Tracker Event Routing. If an existing Cloud Object Storage bucket is not specified, a bucket is created." -} - -variable "existing_activity_tracker_cos_target_bucket_endpoint" { - type = string - nullable = true - default = null - description = "The name of an existing Cloud Object Storage bucket endpoint to use for setting up IBM Cloud Activity Tracker Event Routing. If an existing endpoint is not specified, the endpoint of the new Cloud Object Storage bucket is used." -} - -variable "cos_target_name" { - type = string - description = "Name of the cos target for activity tracker event routing." - default = null -} - -variable "cloud_logs_target_name" { - type = string - description = "Name of the cloud logs target for activity tracker event routing." - default = null -} - -variable "activity_tracker_cos_route_name" { - type = string - description = "Name of the cos route for activity tracker event routing." - default = null -} - -variable "activity_tracker_cloud_logs_route_name" { - type = string - description = "Name of the cloud logs route for activity tracker event routing." - default = null -} - -variable "activity_tracker_cos_target_bucket_class" { - type = string - default = "smart" - description = "The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`." - validation { - condition = contains(["standard", "vault", "cold", "smart", "onerate_active"], var.activity_tracker_cos_target_bucket_class) - error_message = "Specify one of the following values for the `cos_bucket_class`: `standard`, `vault`, `cold`, `smart`, or `onerate_active`." - } -} - -variable "activity_tracker_cos_bucket_access_tags" { - type = list(string) - default = [] - description = "A list of optional access tags to add to the IBM Cloud Activity Tracker Event Routing Cloud Object Storage bucket." -} - -variable "activity_tracker_cos_bucket_retention_policy" { - type = object({ - default = optional(number, 90) - maximum = optional(number, 350) - minimum = optional(number, 90) - permanent = optional(bool, false) - }) - description = "The retention policy of the IBM Cloud Activity Tracker Event Routing COS target bucket." - default = null -} - -variable "enable_activity_tracker_event_routing_to_cloud_logs" { - type = bool - description = "When set to `true`, you must provide a value for `existing_cloud_logs_crn` to enable event routing from Activity Tracker to a Cloud Logs instance." - default = true -} - -variable "skip_activity_tracker_cos_auth_policy" { - type = bool - description = "To skip creating an IAM authorization policy that allows the Activity Tracker to write to the Cloud Object Storage instance, set this variable to `true`." - default = false -} - -######################################################################################################################## -# App Config variables -######################################################################################################################## - -variable "app_config_name" { - type = string - description = "Name for the App Configuration service instance." - default = "app-config" - nullable = false -} - -variable "app_config_plan" { - type = string - description = "Plan for the App Configuration service instance." - default = "enterprise" - nullable = false -} - -variable "app_config_service_endpoints" { - type = string - description = "Service Endpoints for the App Configuration service instance, valid endpoints are public or public-and-private." - default = "public-and-private" - nullable = false - - validation { - condition = contains(["public", "public-and-private"], var.app_config_service_endpoints) - error_message = "Value for service endpoints must be one of the following: \"public\" or \"public-and-private\"." - } -} - -variable "app_config_collections" { - description = "(Optional, list) A list of collections to be added to the App Configuration instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-app-configuration/tree/main/solutions/fully-configurable/DA-collections.md)." - type = list(object({ - name = string - collection_id = string - description = optional(string, null) - tags = optional(string, null) - })) - default = [] - - validation { - condition = ( - var.app_config_plan != "lite" || - length(var.app_config_collections) <= 1 - ) - error_message = "When using the 'lite' plan, you can define at most 1 App Configuration collection." - } -} - -variable "app_config_tags" { - type = list(string) - description = "Optional list of tags to be added to the App Config instance." - default = [] -} - -variable "enable_config_aggregator" { - description = "Set to true to enable configuration aggregator. By setting to true a trusted profile will be created with the required access to record configuration data from all resources across regions in your account. [Learn more](https://cloud.ibm.com/docs/app-configuration?topic=app-configuration-ac-configuration-aggregator)." - type = bool - default = true - nullable = false - - # Lite plan does not support enabling Config Aggregator as mention in doc : https://cloud.ibm.com/docs/app-configuration?topic=app-configuration-ac-configuration-aggregator - validation { - condition = !(var.enable_config_aggregator && var.app_config_plan == "lite") - error_message = "The configuration aggregator cannot be enabled when the app_config_plan is set to 'lite'. Please use a different plan (e.g., 'basic', 'standardv2', or 'enterprise')." - } -} - -variable "config_aggregator_trusted_profile_name" { - description = "The name to give the trusted profile that will be created if `enable_config_aggregator` is set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." - type = string - default = "config-aggregator-trusted-profile" - - validation { - condition = var.enable_config_aggregator ? var.config_aggregator_trusted_profile_name != null : true - error_message = "'config_aggregator_trusted_profile_name' cannot be null if 'enable_config_aggregator' is true." - } -} - -variable "config_aggregator_resource_collection_regions" { - type = list(string) - description = "From which region do you want to collect configuration data? Only applies if `enable_config_aggregator` is set to true." - default = ["all"] -} - -variable "config_aggregator_enterprise_id" { - type = string - description = "If the account is an enterprise account, this value should be set to the enterprise ID (NOTE: This is different to the account ID). " - default = null - - validation { - condition = !var.enable_config_aggregator ? var.config_aggregator_enterprise_id == null : true - error_message = "A value can only be passed for 'config_aggregator_enterprise_id' if 'enable_config_aggregator' is true." - } -} - -variable "config_aggregator_enterprise_trusted_profile_name" { - description = "The name to give the enterprise viewer trusted profile with that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." - type = string - default = "config-aggregator-enterprise-trusted-profile" - - validation { - condition = var.enable_config_aggregator && var.config_aggregator_enterprise_id != null ? var.config_aggregator_enterprise_trusted_profile_name != null : true - error_message = "'config_aggregator_enterprise_trusted_profile_name' cannot be null if 'enable_config_aggregator' is true and a value is being passed for 'config_aggregator_enterprise_id'." - } -} - -variable "config_aggregator_enterprise_trusted_profile_template_name" { - description = "The name to give the trusted profile template that will be created if `enable_config_aggregator` is set to `true` and a value is passed for `config_aggregator_enterprise_id`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." - type = string - default = "config-aggregator-trusted-profile-template" - - validation { - condition = var.enable_config_aggregator && var.config_aggregator_enterprise_id != null ? var.config_aggregator_enterprise_trusted_profile_template_name != null : true - error_message = "'config_aggregator_enterprise_trusted_profile_template_name' cannot be null if 'enable_config_aggregator' is true and a value is being passed for 'config_aggregator_enterprise_id'." - } -} - -variable "config_aggregator_enterprise_account_group_ids_to_assign" { - type = list(string) - default = ["all"] - description = "A list of enterprise account group IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all account groups. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`." - nullable = false - - validation { - condition = contains(var.config_aggregator_enterprise_account_group_ids_to_assign, "all") ? length(var.config_aggregator_enterprise_account_group_ids_to_assign) == 1 : true - error_message = "When specifying 'all' in the list, you cannot add any other values to the list" - } -} - -variable "config_aggregator_enterprise_account_ids_to_assign" { - type = list(string) - default = [] - description = "A list of enterprise account IDs to assign the trusted profile template to in order for the accounts to be scanned. Supports passing the string 'all' in the list to assign to all accounts. Only applies if `enable_config_aggregator` is true and a value is being passed for `config_aggregator_enterprise_id`." - nullable = false - - validation { - condition = contains(var.config_aggregator_enterprise_account_ids_to_assign, "all") ? length(var.config_aggregator_enterprise_account_ids_to_assign) == 1 : true - error_message = "When specifying 'all' in the list, you cannot add any other values to the list" - } -} - -variable "skip_app_config_kms_auth_policy" { - type = bool - description = "Set to true to skip the creation of an IAM authorization policy that permits App configuration instances in the resource group to read the encryption key from the KMS instance in the same account. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the other account." - default = false -} - -variable "skip_app_config_event_notifications_auth_policy" { - type = bool - description = "Set to true to skip the creation of an IAM authorization policy that permits App configuration instances to integrate with Event Notification in the same account." - default = false -} - -variable "app_config_event_notifications_source_name" { - type = string - description = "The name by which Event Notifications source will be created in the existing Event Notification instance." - default = "app-config-en" -} - -variable "apprapp_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md)." - default = [] -} - -####################################################################################################################### -# SCC Workload Protection -####################################################################################################################### - -variable "scc_workload_protection_instance_name" { - description = "The name for the Workload Protection instance that is created by this solution. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format." - type = string - default = "scc-workload-protection" -} - -variable "scc_workload_protection_trusted_profile_name" { - description = "The name to give the trusted profile that is created by this module if `cspm_enabled` is `true. Must begin with a letter. If a prefix input variable is specified, the prefix is added to the name in the `-` format." - type = string - default = "workload-protection-trusted-profile" - validation { - condition = can(regex("^[a-zA-Z][a-zA-Z0-9\\-_\\.]+$", var.scc_workload_protection_trusted_profile_name)) - error_message = "The trusted profile name must begin with a letter and can only contain letters, numbers, hyphens, underscores, and periods." - } - validation { - condition = !(var.cspm_enabled && var.scc_workload_protection_trusted_profile_name == null) - error_message = "Cannot be `null` if `cspm_enabled` is `true`." - } -} - -variable "scc_workload_protection_instance_tags" { - type = list(string) - description = "The list of tags to add to the Workload Protection instance." - default = [] -} - -variable "scc_workload_protection_resource_key_tags" { - type = list(string) - description = "The tags associated with the Workload Protection resource key." - default = [] -} - -variable "scc_workload_protection_access_tags" { - type = list(string) - description = "A list of access tags to apply to the Workload Protection instance. Maximum length: 128 characters. Possible characters are A-Z, 0-9, spaces, underscores, hyphens, periods, and colons." - default = [] - - validation { - condition = alltrue([ - for tag in var.scc_workload_protection_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 - ]) - error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\", see https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits for more details" - } -} - -variable "scc_workload_protection_service_plan" { - description = "The pricing plan for the Workload Protection instance service. Possible values: `free-trial`, `graduated-tier`." - type = string - default = "graduated-tier" - validation { - error_message = "Plan for Workload Protection instances can only be `free-trial` or `graduated-tier`." - condition = contains( - ["free-trial", "graduated-tier"], - var.scc_workload_protection_service_plan - ) - } -} - -variable "cspm_enabled" { - description = "Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service." - type = bool - default = true - nullable = false -} - -variable "scc_wp_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - tags = optional(list(object({ - name = string - value = string - })), []) - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The list of context-based restriction rules to create for the instance." - default = [] - # Validation happens in the rule module -} - -####################################################################################################################### -# VPC and VPE -####################################################################################################################### - -variable "enable_vpc_flow_logs" { - description = "To enable VPC Flow logs, set this to true." - type = bool - nullable = false - default = false -} - -variable "vpc_name" { - default = "vpc" - description = "Name of the VPC. If a prefix input variable is specified, the prefix is added to the name in the `-` format." - type = string -} - -variable "flow_logs_cos_bucket_name" { - description = "Name of the Cloud Object Storage bucket to be created to collect VPC flow logs." - type = string - default = "flow-logs-bucket" -} - -variable "vpc_resource_tags" { - type = list(string) - description = "The list of tags to add to the VPC instance." - default = [] -} - -variable "vpc_access_tags" { - type = list(string) - description = "The list of access tags to add to the VPC instance." - default = [] -} - -variable "vpc_flow_logs_access_tags" { - type = list(string) - description = "The list of access tags to add to the VPC instance." - default = [] -} - -variable "flow_logs_cos_bucket_archive_days" { - description = "The number of days before the `archive_type` rule action takes effect for the flow logs cloud object storage bucket." - type = number - default = 90 -} - -variable "flow_logs_cos_bucket_archive_type" { - description = "The storage class or archive type you want the object to transition to in the flow logs cloud object storage bucket." - type = string - default = "Glacier" - validation { - condition = contains(["Glacier", "Accelerated"], var.flow_logs_cos_bucket_archive_type) - error_message = "The specified flow_logs_cos_bucket_archive_type is not a valid selection!" - } -} - -variable "flow_logs_cos_bucket_expire_days" { - description = "The number of days before the expire rule action takes effect for the flow logs cloud object storage bucket." - type = number - default = 366 -} - -variable "flow_logs_cos_bucket_enable_object_versioning" { - description = "Set it to true if object versioning is enabled so that multiple versions of an object are retained in the flow logs cloud object storage bucket. Cannot be used if `flow_logs_cos_bucket_enable_retention` is true." - type = bool - nullable = false - default = false - - validation { - condition = var.flow_logs_cos_bucket_enable_object_versioning ? (var.flow_logs_cos_bucket_enable_retention ? false : true) : true - error_message = "`flow_logs_cos_bucket_enable_object_versioning` cannot set true if `flow_logs_cos_bucket_enable_retention` is true." - } -} - -variable "flow_logs_cos_bucket_enable_retention" { - description = "Set to true to enable retention for the flow logs cloud object storage bucket." - type = bool - nullable = false - default = false -} - -variable "flow_logs_cos_bucket_default_retention_days" { - description = "The number of days that an object can remain unmodified in the flow logs cloud object storage bucket." - type = number - default = 90 -} - -variable "flow_logs_cos_bucket_maximum_retention_days" { - description = "The maximum number of days that an object can be kept unmodified in the flow logs cloud object storage." - type = number - default = 350 -} - -variable "flow_logs_cos_bucket_minimum_retention_days" { - description = "The minimum number of days that an object must be kept unmodified in the flow logs cloud object storage." - type = number - default = 90 -} - -variable "flow_logs_cos_bucket_enable_permanent_retention" { - description = "Whether permanent retention status is enabled for the flow logs cloud object storage bucket." - type = bool - nullable = false - default = false -} - -variable "subnets" { - description = "List of subnets for the vpc. For each item in each array, a subnet will be created. Items can be either CIDR blocks or total ipv4 addresses. Public gateways will be enabled only in zones where a gateway has been createds." - type = object({ - zone-1 = list(object({ - name = string - cidr = string - public_gateway = optional(bool) - acl_name = string - no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true - subnet_tags = optional(list(string), []) - })) - zone-2 = optional(list(object({ - name = string - cidr = string - public_gateway = optional(bool) - acl_name = string - no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true - subnet_tags = optional(list(string), []) - }))) - zone-3 = optional(list(object({ - name = string - cidr = string - public_gateway = optional(bool) - acl_name = string - no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true - subnet_tags = optional(list(string), []) - }))) - }) - - default = { - zone-1 = [ - { - name = "subnet-a" - cidr = "10.10.10.0/24" - public_gateway = true - acl_name = "vpc-acl" - no_addr_prefix = false - } - ], - zone-2 = [ - { - name = "subnet-b" - cidr = "10.20.10.0/24" - public_gateway = true - acl_name = "vpc-acl" - no_addr_prefix = false - } - ], - zone-3 = [ - { - name = "subnet-c" - cidr = "10.30.10.0/24" - public_gateway = true - acl_name = "vpc-acl" - no_addr_prefix = false - } - ] - } - - validation { - condition = alltrue([for key, value in var.subnets : value != null ? length([for subnet in value : subnet.public_gateway if subnet.public_gateway]) > 1 ? false : true : true]) - error_message = "var.subnets has more than one public gateway in a zone. Only one public gateway can be attached to a zone for the virtual private cloud." - } -} - -variable "default_network_acl_name" { - description = "Name of the Default ACL. If null, a name will be automatically generated." - type = string - default = null -} - -variable "default_security_group_name" { - description = "Name of the Default Security Group. If null, a name will be automatically generated." - type = string - default = null -} - -variable "default_routing_table_name" { - description = "Name of the Default Routing Table. If null, a name will be automatically generated." - type = string - default = null -} - -variable "network_acls" { - description = "The list of ACLs to create. Provide at least one rule for each ACL." - type = list( - object({ - name = string - add_ibm_cloud_internal_rules = optional(bool) - add_vpc_connectivity_rules = optional(bool) - prepend_ibm_rules = optional(bool) - rules = list( - object({ - name = string - action = string - destination = string - direction = string - source = string - tcp = optional( - object({ - port_max = optional(number) - port_min = optional(number) - source_port_max = optional(number) - source_port_min = optional(number) - }) - ) - udp = optional( - object({ - port_max = optional(number) - port_min = optional(number) - source_port_max = optional(number) - source_port_min = optional(number) - }) - ) - icmp = optional( - object({ - type = optional(number) - code = optional(number) - }) - ) - }) - ) - }) - ) - - default = [ - { - name = "vpc-acl" - add_ibm_cloud_internal_rules = true - add_vpc_connectivity_rules = true - prepend_ibm_rules = true - rules = [ - { - name = "allow-443-inbound-source" - action = "allow" - direction = "inbound" - tcp = { - source_port_min = 443 - source_port_max = 443 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - }, - { - name = "allow-443-inbound-dest" - action = "allow" - direction = "inbound" - tcp = { - port_max = 443 - port_min = 443 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - }, - { - name = "allow-all-80-inbound" - action = "allow" - direction = "inbound" - tcp = { - source_port_min = 80 - source_port_max = 80 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - }, - { - name = "allow-all-ingress-inbound" - action = "allow" - direction = "inbound" - tcp = { - source_port_min = 30000 - source_port_max = 32767 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - }, - { - name = "allow-443-outbound-source" - action = "allow" - direction = "outbound" - tcp = { - source_port_min = 443 - source_port_max = 443 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - }, - { - name = "allow-443-outbound-dest" - action = "allow" - direction = "outbound" - tcp = { - port_min = 443 - port_max = 443 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - }, - { - name = "allow-all-80-outbound" - action = "allow" - direction = "outbound" - tcp = { - port_min = 80 - port_max = 80 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - }, - { - name = "allow-all-ingress-outbound" - action = "allow" - direction = "outbound" - tcp = { - port_min = 30000 - port_max = 32767 - } - destination = "0.0.0.0/0" - source = "0.0.0.0/0" - } - ] - } - ] - - validation { - error_message = "ACL rule actions can only be `allow` or `deny`." - condition = length(distinct( - flatten([ - # Check through rules - for rule in flatten([var.network_acls[*].rules]) : - # Return false action is not valid - false if !contains(["allow", "deny"], rule.action) - ]) - )) == 0 - } - - validation { - error_message = "ACL rule direction can only be `inbound` or `outbound`." - condition = length(distinct( - flatten([ - # Check through rules - for rule in flatten([var.network_acls[*].rules]) : - # Return false if direction is not valid - false if !contains(["inbound", "outbound"], rule.direction) - ]) - )) == 0 - } - - validation { - error_message = "ACL rule names must match the regex pattern ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$." - condition = length(distinct( - flatten([ - # Check through rules - for rule in flatten([var.network_acls[*].rules]) : - # Return false if direction is not valid - false if !can(regex("^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$", rule.name)) - ]) - )) == 0 - } - -} - -############################################################################## -# Default Security Group Rules -############################################################################## - -variable "security_group_rules" { - description = "A list of security group rules to be added to the default vpc security group (default empty)." - default = [] - type = list( - object({ - name = string - direction = string - remote = optional(string) - local = optional(string) - ip_version = optional(string) - tcp = optional( - object({ - port_max = optional(number) - port_min = optional(number) - }) - ) - udp = optional( - object({ - port_max = optional(number) - port_min = optional(number) - }) - ) - icmp = optional( - object({ - type = optional(number) - code = optional(number) - }) - ) - }) - ) - - validation { - error_message = "Security group rule direction can only be `inbound` or `outbound`." - condition = (var.security_group_rules == null || length(var.security_group_rules) == 0) ? true : length(distinct( - flatten([ - # Check through rules - for rule in var.security_group_rules : - # Return false if direction is not valid - false if !contains(["inbound", "outbound"], rule.direction) - ]) - )) == 0 - } - - validation { - error_message = "Security group rule names must match the regex pattern ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$." - condition = (var.security_group_rules == null || length(var.security_group_rules) == 0) ? true : length(distinct( - flatten([ - # Check through rules - for rule in var.security_group_rules : - # Return false if direction is not valid - false if !can(regex("^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$", rule.name)) - ]) - )) == 0 - } -} - -variable "clean_default_security_group_acl" { - description = "Remove all rules from the default VPC security group and VPC ACL (less permissive)." - type = bool - nullable = false - default = true -} - -############################################################################## -# Address Prefixes -############################################################################## - -variable "address_prefixes" { - description = "The IP range that will be defined for the VPC for a certain location. Use only with manual address prefixes." - type = object({ - zone-1 = optional(list(string)) - zone-2 = optional(list(string)) - zone-3 = optional(list(string)) - }) - default = { - zone-1 = null - zone-2 = null - zone-3 = null - } - validation { - error_message = "Keys for `use_public_gateways` must be in the order `zone-1`, `zone-2`, `zone-3`." - condition = var.address_prefixes == null ? true : ( - (length(var.address_prefixes) == 1 && keys(var.address_prefixes)[0] == "zone-1") || - (length(var.address_prefixes) == 2 && keys(var.address_prefixes)[0] == "zone-1" && keys(var.address_prefixes)[1] == "zone-2") || - (length(var.address_prefixes) == 3 && keys(var.address_prefixes)[0] == "zone-1" && keys(var.address_prefixes)[1] == "zone-2") && keys(var.address_prefixes)[2] == "zone-3" - ) - } -} - -############################################################################## -# Add routes to VPC -############################################################################## - -variable "routes" { - description = "Allows you to specify the next hop for packets based on their destination address." - type = list( - object({ - name = string - route_direct_link_ingress = optional(bool) - route_transit_gateway_ingress = optional(bool) - route_vpc_zone_ingress = optional(bool) - routes = optional( - list( - object({ - action = optional(string) - zone = number - destination = string - next_hop = string - }) - )) - }) - ) - default = [] -} - -variable "skip_vpc_cos_iam_auth_policy" { - description = "To skip creating an IAM authorization policy that allows the VPC to access the Cloud Object Storage, set this variable to `true`. Required only if `enable_vpc_flow_logs` is set to true." - type = bool - nullable = false - default = false -} - -variable "vpn_gateways" { - description = "List of VPN Gateways to create." - nullable = false - type = list( - object({ - name = string - subnet_name = string # Do not include prefix, use same name as in `var.subnets` - mode = optional(string) - resource_group = optional(string) - access_tags = optional(list(string), []) - }) - ) - - default = [] -} - -variable "vpe_gateway_cloud_services" { - description = "The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`." - type = set(object({ - service_name = string - vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name. - allow_dns_resolution_binding = optional(bool, false) - })) - default = [] -} - -variable "vpe_gateway_cloud_service_by_crn" { - description = "The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`." - type = set( - object({ - crn = string - vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name. - service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn. - allow_dns_resolution_binding = optional(bool, true) - }) - ) - default = [] -} - -variable "vpe_gateway_service_endpoints" { - description = "Service endpoints to use to create endpoint gateways. Can be `public`, or `private`." - type = string - default = "private" - - validation { - error_message = "Service endpoints can only be `public` or `private`." - condition = contains(["public", "private"], var.vpe_gateway_service_endpoints) - } -} - -variable "vpe_gateway_security_group_ids" { - - # Currently unused — the DA doesn't create any custom security groups. - # The default security group (automatically created with the VPC) is attached to the VPE gateway since no other security groups are present. - # May be useful in the future when DA supports using an existing VPC with custom security groups or if DA supports creating additional security groups we can take `vpe_gateway_security_group_names` as input. - - description = "List of security group ids to attach to each endpoint gateway." - type = list(string) - default = null # Let this default value be null instead of []. Provider issue - https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4546 -} - -variable "vpe_gateway_reserved_ips" { - description = "Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used when a user passes their existing reserved ips created here and not attempt to recreate those." - type = object({ - name = optional(string) # reserved ip name - }) - default = {} -} - -######################################################################################################################## -# OCP VPC cluster -######################################################################################################################## - -variable "cluster_name" { - type = string - description = "The name of the new IBM Cloud OpenShift Cluster. If a `prefix` input variable is specified, it is added to this name in the `-value` format." - default = "openshift" -} - -variable "default_worker_pool_machine_type" { - type = string - description = "The machine type for worker nodes." - default = "bx2.4x16" - validation { - condition = length(regexall("^[a-z0-9]+(?:\\.[a-z0-9]+)*\\.\\d+x\\d+(?:\\.[a-z0-9]+)?$", var.default_worker_pool_machine_type)) > 0 - error_message = "Invalid value provided for the machine type." - } -} - -variable "default_worker_pool_workers_per_zone" { - type = number - description = "Number of worker nodes in each zone of the cluster." - default = 1 -} - -variable "default_worker_pool_operating_system" { - type = string - description = "The operating system installed on the worker nodes." - default = "RHCOS" -} - -variable "default_worker_pool_labels" { - type = map(string) - description = "A set of key-value labels assigned to the worker pool for identification." - default = {} -} - -variable "default_pool_minimum_number_of_nodes" { - type = number - description = "The minimum number of worker nodes allowed in the pool, ensuring at least one worker is always running." - default = 1 -} - -variable "default_pool_maximum_number_of_nodes" { - type = number - description = "The maximum number of worker nodes allowed in the pool, preventing the pool from exceeding three workers." - default = 3 -} - -variable "additional_security_group_ids" { - type = list(string) - description = "A list of security group IDs that are attached to the worker nodes for additional network security controls." - default = [] -} - -variable "additional_worker_pools" { - type = list(object({ - vpc_subnets = optional(list(object({ - id = string - zone = string - cidr_block = string - })), []) - pool_name = string - machine_type = string - workers_per_zone = number - operating_system = string - labels = optional(map(string)) - minSize = optional(number) - secondary_storage = optional(string) - maxSize = optional(number) - enableAutoscaling = optional(bool) - additional_security_group_ids = optional(list(string)) - })) - description = "List of additional worker pools." - default = [] -} - -variable "enable_autoscaling_for_default_pool" { - type = bool - description = "Set `true` to enable automatic scaling of worker based on workload demand." - default = false -} - -variable "addons" { - type = object({ - debug-tool = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - image-key-synchronizer = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - openshift-data-foundation = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - vpc-file-csi-driver = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - static-route = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - cluster-autoscaler = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - vpc-block-csi-driver = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - ibm-storage-operator = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - openshift-ai = optional(object({ - version = optional(string) - parameters_json = optional(string) - })) - }) - description = "Map of OCP cluster add-on versions to install (NOTE: The 'vpc-block-csi-driver' add-on is installed by default for VPC clusters and 'ibm-storage-operator' is installed by default in OCP 4.15 and later, however you can explicitly specify it here if you wish to choose a later version than the default one). [Check supported addons and versions here](https://cloud.ibm.com/docs/containers?topic=containers-supported-cluster-addon-versions)." - nullable = false - default = {} -} - -variable "openshift_version" { - type = string - description = "Version of the OpenShift cluster to provision." - default = "4.19" -} - -variable "cluster_resource_tags" { - type = list(string) - description = "Metadata labels describing this cluster deployment, i.e. test." - default = [] -} - -variable "access_tags" { - type = list(string) - description = "A list of access tags to apply to the resources created by the module." - default = [] -} - -variable "ocp_entitlement" { - type = string - description = "Value that is applied to the entitlements for OCP cluster provisioning." - default = null -} - -variable "additional_lb_security_group_ids" { - description = "List of additional security group IDs to add to the load balancers associated with the cluster. Ensure that the `number_of_lbs` variable is set to the number of Load Balancers associated with the cluster. This comes in addition to the IBM maintained security group." - type = list(string) - default = [] - nullable = false -} - -variable "number_of_lbs" { - description = "The total number of Load Balancers in the cluster that should be associated with the security groups defined in `additional_lb_security_group_ids` variable." - type = number - default = 1 - nullable = false -} - -variable "additional_vpe_security_group_ids" { - description = "Additional security groups to add to all existing load balancers. This comes in addition to the IBM maintained security group." - type = object({ - master = optional(list(string), []) - registry = optional(list(string), []) - api = optional(list(string), []) - }) - default = {} -} - -variable "allow_default_worker_pool_replacement" { - type = bool - description = "Set to true to allow the module to recreate a default worker pool. Only use in the case where you are getting an error indicating that the default worker pool cannot be replaced on apply. Once the default worker pool is handled separately, if you wish to make any change to the default worker pool which requires the re-creation of the default pool set this variable to true." - default = false - nullable = false -} - -variable "attach_ibm_managed_security_group" { - description = "Specify whether to attach the IBM-defined default security group (whose name is kube-) to all worker nodes. Only applicable if `custom_security_group_ids` is set." - type = bool - default = true -} - -variable "cluster_config_endpoint_type" { - description = "Specify which type of endpoint to use for cluster config access: 'default', 'private', 'vpe', 'link'. A 'default' value uses the default endpoint of the cluster." - type = string - default = "default" - nullable = false -} - -variable "verify_worker_network_readiness" { - type = bool - description = "By setting this to true, a script runs kubectl commands to verify that all worker nodes can communicate successfully with the master. If the runtime does not have access to the kube cluster to run kubectl commands, set this value to false." - default = true -} - -variable "cluster_ready_when" { - type = string - description = "The cluster is ready based on one of the following:: MasterNodeReady (not recommended), OneWorkerNodeReady, Normal, IngressReady." - default = "IngressReady" -} - -variable "custom_security_group_ids" { - description = "Security groups to add to all worker nodes. This comes in addition to the IBM maintained security group if `attach_ibm_managed_security_group` is set to true. If this variable is set, the default VPC security group is NOT assigned to the worker nodes." - type = list(string) - default = null -} - -variable "allow_outbound_traffic" { - type = bool - description = "Set to true to allow public outbound access from the cluster workers." - default = true -} - -variable "allow_public_access_to_cluster_management" { - type = bool - description = "Set to true to access the cluster through a public cloud service endpoint." - default = true -} - -variable "enable_ocp_console" { - description = "Flag to specify whether to enable or disable the OpenShift console. If set to `null` the module does not modify the current setting on the cluster. Keep in mind that when this input is set to `true` or `false` on a cluster with private only endpoint enabled, the runtime must be able to access the private endpoint." - type = bool - default = null - nullable = true -} - -variable "ignore_worker_pool_size_changes" { - type = bool - description = "Enable if using worker autoscaling. Stops Terraform managing worker count." - default = false -} - -variable "manage_all_addons" { - type = bool - default = false - nullable = false - description = "Instructs deployable architecture to manage all cluster addons, even if addons were installed outside of the module. If set to 'true' this deployable architecture destroys any addons that were installed by other sources." -} - -variable "pod_subnet_cidr" { - type = string - description = "Specify a custom subnet CIDR to provide private IP addresses for pods. The subnet must have a CIDR of at least `/23` or larger. Default value is `172.30.0.0/16` when the variable is set to `null`." - default = null -} - -variable "service_subnet_cidr" { - type = string - description = "Specify a custom subnet CIDR to provide private IP addresses for services. The subnet must be at least `/24` or larger. Default value is `172.21.0.0/16` when the variable is set to `null`." - default = null -} - -variable "worker_pools_taints" { - type = map(list(object({ key = string, value = string, effect = string }))) - description = "Optional, Map of lists containing node taints by node-pool name." - default = null -} - -variable "enable_secrets_manager_integration" { - type = bool - description = "Integrate with IBM Cloud Secrets Manager so you can centrally manage Ingress subdomain certificates and other secrets." - default = true - nullable = false -} - -variable "secrets_manager_secret_group_id" { - type = string - description = "Secret group ID where Ingress secrets are stored in the Secrets Manager instance. If 'enable_secrets_manager_integration' is set to true and 'secrets_manager_secret_group_id' is not provided, a new group will be created with the same name as cluster_id." - default = null -} - -variable "skip_ocp_secrets_manager_iam_auth_policy" { - type = bool - description = "To skip creating auth policy that allows OCP cluster 'Manager' role access in the existing Secrets Manager instance for managing ingress certificates." - default = false -} - -variable "ocp_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - tags = optional(list(object({ - name = string - value = string - })), []) - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "The list of context-based restriction rules to create." - default = [] -} diff --git a/modules/containerized_app_landing_zone/version.tf b/modules/containerized_app_landing_zone/version.tf deleted file mode 100644 index 6d52d17c2..000000000 --- a/modules/containerized_app_landing_zone/version.tf +++ /dev/null @@ -1,13 +0,0 @@ -terraform { - required_version = ">=1.9.0" - required_providers { - ibm = { - source = "IBM-Cloud/ibm" - version = ">= 1.78.2, < 2.0.0" - } - time = { - source = "hashicorp/time" - version = ">= 0.9.1, < 1.0.0" - } - } -} From 20d634f60d175fd2ef947e0cce03b57a688b84b0 Mon Sep 17 00:00:00 2001 From: mukul-palit Date: Thu, 18 Dec 2025 14:02:50 +0530 Subject: [PATCH 15/15] update monolith example --- README.md | 2 +- .../containerized_app_landing_zone/README.md | 151 ++- .../kubeconfig/.gitignore | 6 + .../kubeconfig/README.md | 2 + .../containerized_app_landing_zone/main.tf | 949 +++++++++++++++++- .../containerized_app_landing_zone/outputs.tf | 92 +- .../variables.tf | 80 +- .../containerized_app_landing_zone/version.tf | 4 + tests/other_test.go | 6 +- 9 files changed, 1109 insertions(+), 183 deletions(-) create mode 100644 examples/containerized_app_landing_zone/kubeconfig/.gitignore create mode 100644 examples/containerized_app_landing_zone/kubeconfig/README.md diff --git a/README.md b/README.md index 6c0d2ae45..bdedcce4a 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ By default, the module automatically downloads the required dependencies if they *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
- *
Deploy to IBM Cloud button
+ *
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
*
Deploy to IBM Cloud button
diff --git a/examples/containerized_app_landing_zone/README.md b/examples/containerized_app_landing_zone/README.md index 2d910b98a..bd1759ca5 100644 --- a/examples/containerized_app_landing_zone/README.md +++ b/examples/containerized_app_landing_zone/README.md @@ -1,10 +1,145 @@ -# IBM Cloud OpenShift Landing Zone with Integrated Services Example +# Landing zone for containerized applications with OpenShift example -A simple example that shows how to provision a multi zone OCP VPC cluster as well as all foundational infrastructure and supporting services required for a secure and compliant OpenShift (OCP) cluster deployment on IBM Cloud VPC. +This example provides a **terraform implementation** of the secure landing zone architecture - a production-grade Red Hat OpenShift platform on IBM Cloud VPC by providing a fully integrated ecosystem. Rather than just provisioning compute resources, it orchestrates the critical **operational glue** required for enterprise workloads—automatically wiring together **Key Management**, **Secrets Manager**, **Cloud Logs**, **Cloud Monitoring**, **Cloud Object Storage** and **Events Notification**. This comprehensive approach reduces operational overhead and eliminates manual configuration errors, ensuring your environment is secure, observable, and ready. -The following resources are provisioned by this example: -* A new resource group if an existing resource group is not passed. -* Monitoring agent. -* A Trusted Profile with Sender role to logs service. -* Logs agent. -* All the resources that are provisioned by calling the `containerized_app_landing_zone` module can be referred [here](../../modules/containerized_app_landing_zone/README.md). +Secure, Compliant, and Scalable Designed to support a wide range of business needs, the architecture is secure by design and fully configurable. It incorporates robust compliance features, such as **SCC Workload Protection**, while allowing you to tailor specific integrations and worker pools to your requirements. This flexibility enables organizations to standardize on a single, reliable architectural pattern that streamlines security approvals and scales effortlessly with business demand. + +### Reference Architecture + +![Architecture Diagram](../../reference-architectures/deployable-architecture-ocp-cluster.svg) + +### Components + +The primary goal of this example is to provision an OpenShift cluster on VPC and automatically configure the necessary supporting services, including: +* `VPC Infrastructure`: The base VPC, subnets, and network access controls (ACLs) for the OpenShift cluster. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/landing-zone-vpc/ibm/8.9.1) about the service module. +* `Key Management (KMS)`: Optional provision and configuration of an IBM Key Protect or Hyper Protect Crypto Services (HPCS) instance for encrypting cluster and boot volumes. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/kms-all-inclusive/ibm/5.4.5) about the service module. +* `Secrets Management`: Optional provision and configuration of an IBM Secrets Manager instance to securely store service credentials and other secrets. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/secrets-manager/ibm/2.11.9) about the service module. +* `Cloud Object Storage (COS)`: Optional provision and configuration of COS instances and buckets for flow logs, activity tracker, and other data storage needs. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/cos/ibm/10.5.9) about the service module. +* `Monitoring & Logging`: Optional provision and configuration of IBM Cloud Monitoring and IBM Cloud Logs instances for centralized observability. Learn more about the [Cloud Monitoring](https://registry.terraform.io/modules/terraform-ibm-modules/cloud-monitoring/ibm/1.11.0) and [Cloud Logs](https://registry.terraform.io/modules/terraform-ibm-modules/cloud-logs/ibm/1.10.0) service module. +* `Activity Tracker and Event Routing`: Configure event routing for platform audit logs to a COS bucket or IBM Cloud Logs. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/activity-tracker/ibm/1.5.0) about the service module. +* `Security & Compliance`: Optional integration with IBM Cloud Security and Compliance Center (SCC) Workload Protection. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/scc-workload-protection/ibm/1.16.4) about the service module. +* `VPE Gateways`: Optional configuration of Virtual Private Endpoint (VPE) gateways for secure private connectivity to cloud services. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/vpe-gateway/ibm/4.6.6) about the service module. +* `Event Notifications`: Optional provision and configuration of IBM Cloud Event Notifications for centralized event routing and management, with support for KMS encryption and failed event collection in COS. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/event-notifications/ibm/2.7.0) about the service module. +* `App Configuration`: Optional provision and configuration of IBM Cloud App Configuration for centralized feature flag and property management, securely integrated with KMS and Event Notifications. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/app-configuration/ibm/1.14.2) about the service module. +* `Context-Based Restrictions (CBR)`: Optional support for defining and attaching network access rules (CBR zones and rules) to all supported services (KMS, COS, Secrets Manager) to enforce zero-trust networking. [Learn more](https://registry.terraform.io/modules/terraform-ibm-modules/cbr/ibm/1.34.0) about the service module. + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >=1.9.0 | +| [helm](#requirement\_helm) | >= 3.0.0, <4.0.0 | +| [ibm](#requirement\_ibm) | >= 1.78.2, < 2.0.0 | +| [kubernetes](#requirement\_kubernetes) | >= 2.16.1 | +| [restapi](#requirement\_restapi) | >= 2.0.1 | +| [time](#requirement\_time) | >= 0.9.1, < 1.0.0 | + +### Modules + +| Name | Source | Version | +|------|--------|---------| +| [activity\_tracker](#module\_activity\_tracker) | terraform-ibm-modules/activity-tracker/ibm | 1.5.0 | +| [app\_config](#module\_app\_config) | terraform-ibm-modules/app-configuration/ibm | 1.14.2 | +| [at\_cos\_bucket](#module\_at\_cos\_bucket) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | +| [cloud\_logs](#module\_cloud\_logs) | terraform-ibm-modules/cloud-logs/ibm | 1.10.0 | +| [cloud\_logs\_buckets](#module\_cloud\_logs\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | +| [cloud\_monitoring](#module\_cloud\_monitoring) | terraform-ibm-modules/cloud-monitoring/ibm | 1.11.0 | +| [cos](#module\_cos) | terraform-ibm-modules/cos/ibm//modules/fscloud | 10.5.9 | +| [en\_cos\_buckets](#module\_en\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | +| [event\_notifications](#module\_event\_notifications) | terraform-ibm-modules/event-notifications/ibm | 2.7.0 | +| [kms](#module\_kms) | terraform-ibm-modules/kms-all-inclusive/ibm | 5.4.5 | +| [logs\_agent](#module\_logs\_agent) | terraform-ibm-modules/logs-agent/ibm | 1.10.0 | +| [metrics\_routing](#module\_metrics\_routing) | terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing | 1.11.0 | +| [monitoring\_agent](#module\_monitoring\_agent) | terraform-ibm-modules/monitoring-agent/ibm | 1.19.0 | +| [ocp\_base](#module\_ocp\_base) | ../.. | n/a | +| [resource\_group](#module\_resource\_group) | terraform-ibm-modules/resource-group/ibm | 1.4.0 | +| [scc\_wp](#module\_scc\_wp) | terraform-ibm-modules/scc-workload-protection/ibm | 1.16.4 | +| [secret\_group](#module\_secret\_group) | terraform-ibm-modules/secrets-manager-secret-group/ibm | 1.3.15 | +| [secrets\_manager](#module\_secrets\_manager) | terraform-ibm-modules/secrets-manager/ibm | 2.11.9 | +| [trusted\_profile](#module\_trusted\_profile) | terraform-ibm-modules/trusted-profile/ibm | 3.2.0 | +| [vpc](#module\_vpc) | terraform-ibm-modules/landing-zone-vpc/ibm | 8.9.1 | +| [vpc\_cos\_buckets](#module\_vpc\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 10.5.8 | +| [vpe\_gateway](#module\_vpe\_gateway) | terraform-ibm-modules/vpe-gateway/ibm | 4.6.6 | + +### Resources + +| Name | Type | +|------|------| +| [ibm_en_subscription_email.apprapp_email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | +| [ibm_en_subscription_email.en_email_subscription](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_subscription_email) | resource | +| [ibm_en_topic.en_apprapp_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | +| [ibm_en_topic.en_sm_topic](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/en_topic) | resource | +| [ibm_iam_authorization_policy.cos_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [ibm_iam_authorization_policy.en_secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [terraform_data.delete_secrets](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | +| [time_sleep.wait_for_cos_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [time_sleep.wait_for_en_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [time_sleep.wait_for_secrets_manager](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [ibm_container_cluster_config.cluster_config](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/container_cluster_config) | data source | +| [ibm_en_destinations.en_apprapp_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | +| [ibm_en_destinations.en_sm_destinations](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/en_destinations) | data source | +| [ibm_iam_auth_token.auth_token](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/iam_auth_token) | data source | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [event\_notifications\_email\_list](#input\_event\_notifications\_email\_list) | The list of email address to target out when an event is triggered | `list(string)` | `[]` | no | +| [existing\_resource\_group\_name](#input\_existing\_resource\_group\_name) | The name of an existing resource group to provision the resources. | `string` | `"Default"` | no | +| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The IBM Cloud api token | `string` | n/a | yes | +| [prefix](#input\_prefix) | Prefix for name of all resource created by this example | `string` | `"ocp-lz"` | no | +| [provider\_visibility](#input\_provider\_visibility) | Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. | `string` | `"private"` | no | +| [region](#input\_region) | Region where resources are created | `string` | `"us-south"` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| [activity\_tracker\_cos\_target\_bucket\_name](#output\_activity\_tracker\_cos\_target\_bucket\_name) | he name of the object storage bucket which is set as activity tracker event routing target to collect audit events. | +| [activity\_tracker\_routes](#output\_activity\_tracker\_routes) | The map of created Activity Tracker Event Routing routes | +| [activity\_tracker\_targets](#output\_activity\_tracker\_targets) | The map of created Activity Tracker Event Routing targets | +| [cloud\_logs\_crn](#output\_cloud\_logs\_crn) | The id of the provisioned IBM Cloud Logs instance. | +| [cloud\_logs\_guid](#output\_cloud\_logs\_guid) | The guid of the provisioned IBM Cloud Logs instance. | +| [cloud\_logs\_name](#output\_cloud\_logs\_name) | The name of the provisioned IBM Cloud Logs instance. | +| [cloud\_monitoring\_access\_key](#output\_cloud\_monitoring\_access\_key) | The IBM Cloud Monitoring access key for agents to use | +| [cloud\_monitoring\_access\_key\_name](#output\_cloud\_monitoring\_access\_key\_name) | The name of the IBM Cloud Monitoring access key for agents to use | +| [cloud\_monitoring\_crn](#output\_cloud\_monitoring\_crn) | The id of the provisioned IBM Cloud Monitoring instance. | +| [cloud\_monitoring\_guid](#output\_cloud\_monitoring\_guid) | The guid of the provisioned IBM Cloud Monitoring instance. | +| [cloud\_monitoring\_name](#output\_cloud\_monitoring\_name) | The name of the provisioned IBM Cloud Monitoring instance. | +| [cluster\_crn](#output\_cluster\_crn) | The Cloud Resource Name (CRN) of the provisioned OpenShift cluster. | +| [cluster\_id](#output\_cluster\_id) | The unique identifier assigned to the provisioned OpenShift cluster. | +| [cluster\_name](#output\_cluster\_name) | The name of the provisioned OpenShift cluster. | +| [cos\_instance\_crn](#output\_cos\_instance\_crn) | COS instance crn | +| [cos\_instance\_guid](#output\_cos\_instance\_guid) | COS instance guid | +| [events\_notification\_crn](#output\_events\_notification\_crn) | Event Notification crn | +| [events\_notification\_guid](#output\_events\_notification\_guid) | Event Notification guid | +| [kms\_account\_id](#output\_kms\_account\_id) | The account ID of the KMS instance. | +| [kms\_guid](#output\_kms\_guid) | KMS instance GUID | +| [kms\_instance\_crn](#output\_kms\_instance\_crn) | The CRN of the KMS instance | +| [logs\_bucket\_crn](#output\_logs\_bucket\_crn) | Logs Cloud Object Storage bucket CRN | +| [metrics\_bucket\_crn](#output\_metrics\_bucket\_crn) | Metrics Cloud Object Storage bucket CRN | +| [network\_acls](#output\_network\_acls) | List of shortnames and IDs of network ACLs. | +| [ocp\_version](#output\_ocp\_version) | The version of OpenShift running on the provisioned cluster. | +| [private\_path\_subnet\_id](#output\_private\_path\_subnet\_id) | The IDs of the subnets. | +| [public\_gateways](#output\_public\_gateways) | Map of the public gateways by zone. | +| [scc\_workload\_protection\_crn](#output\_scc\_workload\_protection\_crn) | SCC Workload Protection instance CRN | +| [scc\_workload\_protection\_id](#output\_scc\_workload\_protection\_id) | SCC Workload Protection instance ID | +| [scc\_workload\_protection\_name](#output\_scc\_workload\_protection\_name) | SCC Workload Protection instance name | +| [secrets\_manager\_crn](#output\_secrets\_manager\_crn) | CRN of the Secrets Manager instance | +| [secrets\_manager\_guid](#output\_secrets\_manager\_guid) | GUID of Secrets Manager instance | +| [secrets\_manager\_region](#output\_secrets\_manager\_region) | Region of the Secrets Manager instance | +| [subnet\_detail\_list](#output\_subnet\_detail\_list) | A list of subnets containing names, CIDR blocks, and zones. | +| [subnet\_detail\_map](#output\_subnet\_detail\_map) | A map of subnets containing IDs, CIDR blocks, and zones. | +| [subnet\_ids](#output\_subnet\_ids) | The IDs of the subnets. | +| [subnet\_zone\_list](#output\_subnet\_zone\_list) | A list of subnet IDs and subnet zones. | +| [vpc\_crn](#output\_vpc\_crn) | CRN of the VPC created. | +| [vpc\_flow\_logs](#output\_vpc\_flow\_logs) | Details of the VPC flow logs collector. | +| [vpc\_id](#output\_vpc\_id) | ID of the VPC created. | +| [vpc\_name](#output\_vpc\_name) | Name of the VPC created. | +| [vpe\_crn](#output\_vpe\_crn) | The CRN of the endpoint gateway. | +| [vpe\_ips](#output\_vpe\_ips) | The reserved IPs for endpoint gateways. | +| [vpn\_gateways\_data](#output\_vpn\_gateways\_data) | Details of VPN gateways data. | +| [vpn\_gateways\_name](#output\_vpn\_gateways\_name) | List of names of VPN gateways. | +| [workerpools](#output\_workerpools) | A list of worker pools associated with the provisioned cluster | + diff --git a/examples/containerized_app_landing_zone/kubeconfig/.gitignore b/examples/containerized_app_landing_zone/kubeconfig/.gitignore new file mode 100644 index 000000000..632a28fbd --- /dev/null +++ b/examples/containerized_app_landing_zone/kubeconfig/.gitignore @@ -0,0 +1,6 @@ +# Ignore everything +* + +# But not these files... +!.gitignore +!README.md diff --git a/examples/containerized_app_landing_zone/kubeconfig/README.md b/examples/containerized_app_landing_zone/kubeconfig/README.md new file mode 100644 index 000000000..e85afee8d --- /dev/null +++ b/examples/containerized_app_landing_zone/kubeconfig/README.md @@ -0,0 +1,2 @@ +This directory must exist in source control so the `ibm_container_cluster_config` data lookup can use it to place the +config.yml used to connect to a kubernetes cluster. diff --git a/examples/containerized_app_landing_zone/main.tf b/examples/containerized_app_landing_zone/main.tf index d020b2adc..acfb444a3 100644 --- a/examples/containerized_app_landing_zone/main.tf +++ b/examples/containerized_app_landing_zone/main.tf @@ -1,6 +1,6 @@ -######################################################################################################################## +######################################################################################################### # Resource group -######################################################################################################################## +######################################################################################################### module "resource_group" { source = "terraform-ibm-modules/resource-group/ibm" @@ -8,60 +8,911 @@ module "resource_group" { existing_resource_group_name = var.existing_resource_group_name } -######################################################################################################################## -# OpenShift cluster integrated with other services -######################################################################################################################## - -module "openshift_landing_zone" { - source = "../../modules/containerized_app_landing_zone" - prefix = var.prefix - region = var.region - ibmcloud_api_key = var.ibmcloud_api_key - provider_visibility = var.provider_visibility - resource_group_id = module.resource_group.resource_group_id - kms_encryption_enabled_cluster = true - existing_kms_instance_crn = var.existing_kms_instance_crn - existing_cluster_kms_key_crn = var.existing_cluster_kms_key_crn - kms_endpoint_type = "private" - key_protect_allowed_network = "private-only" - kms_encryption_enabled_boot_volume = true - existing_boot_volume_kms_key_crn = var.existing_boot_volume_kms_key_crn - kms_plan = "tiered-pricing" - en_service_plan = "standard" - en_service_endpoints = "public-and-private" - existing_secrets_manager_crn = var.existing_secrets_manager_crn - secrets_manager_service_plan = "standard" - secrets_manager_endpoint_type = "private" - existing_event_notifications_instance_crn = var.existing_event_notifications_instance_crn - existing_cos_instance_crn = var.existing_cos_instance_crn - cos_instance_plan = "standard" - management_endpoint_type_for_buckets = "direct" - existing_cloud_monitoring_crn = var.existing_cloud_monitoring_crn - cloud_monitoring_plan = "graduated-tier" - existing_cloud_logs_crn = var.existing_cloud_logs_crn - scc_workload_protection_service_plan = "graduated-tier" - enable_vpc_flow_logs = true - app_config_plan = "enterprise" - app_config_service_endpoints = "public-and-private" +######################################################################################################### +# KMS +######################################################################################################### + +locals { + cluster_key_ring_name = "${var.prefix}-cluster-key-ring" + cluster_key_name = "${var.prefix}-cluster-key" + boot_volume_key_ring_name = "${var.prefix}-boot-volume-key-ring" + boot_volume_key_name = "${var.prefix}-boot-volume-key" + keys = [{ + key_ring_name = local.cluster_key_ring_name + existing_key_ring = false + keys = [ + { + key_name = local.cluster_key_name + standard_key = false + rotation_interval_month = 3 + dual_auth_delete_enabled = false + force_delete = true + } + ] + }, + { + key_ring_name = local.boot_volume_key_ring_name + existing_key_ring = false + keys = [ + { + key_name = local.boot_volume_key_name + standard_key = false + rotation_interval_month = 3 + dual_auth_delete_enabled = false + force_delete = true + } + ] + } + ] +} + + +module "kms" { + source = "terraform-ibm-modules/kms-all-inclusive/ibm" + version = "5.4.5" + resource_group_id = module.resource_group.resource_group_id + region = var.region + create_key_protect_instance = true + key_protect_instance_name = "${var.prefix}-key-protect" + key_protect_plan = "tiered-pricing" + enable_metrics = true + key_protect_allowed_network = "private-only" # Possible values are 'private-only', or 'public-and-private'. + key_ring_endpoint_type = "private" # Possible values are `public` or `private`. + key_endpoint_type = "private" # Possible values are `public` or `private`. + keys = [for key in local.keys : key if key != null] +} + +######################################################################################################### +# Cloud Monitoring +######################################################################################################### + +locals { + default_metrics_router_route = [{ + name = "${var.prefix}-metrics-routing-route" + rules = [{ + action = "send" + targets = [{ + id = module.metrics_routing.metrics_router_targets["${var.prefix}-cloud-monitoring-target"].id + }] + inclusion_filters = [] + }] + }] +} + +module "cloud_monitoring" { + source = "terraform-ibm-modules/cloud-monitoring/ibm" + version = "1.11.0" + resource_group_id = module.resource_group.resource_group_id + region = var.region + instance_name = "${var.prefix}-cloud-monitoring" + plan = "graduated-tier" # Possible values are `lite` and `graduated-tier` and graduated-tier-sysdig-secure-plus-monitor (available in region eu-fr2 only). + service_endpoints = "public-and-private" + disable_access_key_creation = false + enable_platform_metrics = false +} + +module "metrics_routing" { + source = "terraform-ibm-modules/cloud-monitoring/ibm//modules/metrics_routing" + version = "1.11.0" + metrics_router_targets = [ + { + destination_crn = module.cloud_monitoring.crn + target_name = "${var.prefix}-cloud-monitoring-target" + target_region = var.region + skip_metrics_router_auth_policy = false + } + ] + + metrics_router_routes = local.default_metrics_router_route + metrics_router_settings = { primary_metadata_region = var.region } +} + +######################################################################################################### +# Event Notifications +######################################################################################################### + +locals { + en_cos_bucket_name = "${var.prefix}-base-event-notifications-bucket" +} + +module "event_notifications" { + source = "terraform-ibm-modules/event-notifications/ibm" + version = "2.7.0" + resource_group_id = module.resource_group.resource_group_id + region = var.region + name = "${var.prefix}-event-notifications" + plan = "standard" # Possible values are `lite`, `standard`. + service_endpoints = "public-and-private" # Possible values are `public`, `private`, `public-and-private`. + # KMS Related + kms_encryption_enabled = true + kms_endpoint_url = module.kms.kms_private_endpoint + existing_kms_instance_crn = module.kms.key_protect_crn + root_key_id = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].key_id + skip_en_kms_auth_policy = false + # COS Related + cos_integration_enabled = true + cos_bucket_name = module.en_cos_buckets.buckets[local.en_cos_bucket_name].bucket_name + cos_instance_id = module.cos.cos_instance_id + skip_en_cos_auth_policy = false + cos_endpoint = "https://${module.en_cos_buckets.buckets[local.en_cos_bucket_name].s3_endpoint_direct}" +} + +locals { + en_cos_bucket_config = [{ + bucket_name = local.en_cos_bucket_name + add_bucket_name_suffix = true + kms_encryption_enabled = true + kms_guid = module.kms.kms_guid + kms_key_crn = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn + skip_iam_authorization_policy = false + management_endpoint_type = "direct" # Possible values are `public`, `private` or `direct`. + storage_class = "smart" # Possible values are `standard` or `smart`. + resource_instance_id = module.cos.cos_instance_id + region_location = var.region + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + metrics_monitoring_crn = module.cloud_monitoring.crn + } + force_delete = true + }] +} + +module "en_cos_buckets" { + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.8" + bucket_configs = local.en_cos_bucket_config +} + +######################################################################################################### +# Service Credentials +######################################################################################################### + +# create a service authorization between Secrets Manager and the target service (Event Notification) +resource "ibm_iam_authorization_policy" "en_secrets_manager_key_manager" { + source_service_name = "secrets-manager" + source_resource_instance_id = module.secrets_manager.secrets_manager_guid + target_service_name = "event-notifications" + target_resource_instance_id = module.event_notifications.guid + roles = ["Key Manager"] + description = "Allow Secrets Manager instance to manage key for the event-notification instance" +} + +# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 +resource "time_sleep" "wait_for_en_authorization_policy" { + depends_on = [ibm_iam_authorization_policy.en_secrets_manager_key_manager] + create_duration = "30s" +} + +######################################################################################################### +# Secrets Manager +######################################################################################################### + +locals { + secret_groups = [ + { + secret_group_name = "General" + secret_group_description = "A general purpose secrets group with an associated access group which has a secrets reader role" + create_access_group = true + access_group_name = "general-secrets-group-access-group" + access_group_roles = ["SecretsReader"] + } + ] + secret_groups_with_prefix = [ + for group in local.secret_groups : merge(group, { + access_group_name = group.access_group_name != null ? "${var.prefix}-${group.access_group_name}" : null + }) + ] + # parsed_existing_en_instance_crn = split(":", module.event_notifications.crn) + # existing_en_guid = length(local.parsed_existing_en_instance_crn) > 0 ? local.parsed_existing_en_instance_crn[7] : null +} + +module "secrets_manager" { + source = "terraform-ibm-modules/secrets-manager/ibm" + version = "2.11.9" + resource_group_id = module.resource_group.resource_group_id + region = var.region + secrets_manager_name = "${var.prefix}-secrets-manager" + sm_service_plan = "standard" # Possible values are `standard` or `trial`. + skip_iam_authorization_policy = false + # kms dependency + is_hpcs_key = false + kms_encryption_enabled = true + kms_key_crn = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn + skip_kms_iam_authorization_policy = false + # event notifications dependency + enable_event_notification = true + existing_en_instance_crn = module.event_notifications.crn + skip_en_iam_authorization_policy = false + endpoint_type = "private" # Possible values are `public` or `private`. + allowed_network = "private-only" # Possible values are 'private-only', or 'public-and-private'. + secrets = local.secret_groups_with_prefix +} + +######################################################################################################### +# Secrets Manager Event Notifications Configuration +######################################################################################################### + +data "ibm_en_destinations" "en_sm_destinations" { + instance_guid = module.event_notifications.guid +} + +# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5533 +resource "time_sleep" "wait_for_secrets_manager" { + depends_on = [module.secrets_manager] + create_duration = "30s" +} + +resource "ibm_en_topic" "en_sm_topic" { + depends_on = [time_sleep.wait_for_secrets_manager] + instance_guid = module.event_notifications.guid + name = "Topic for Secrets Manager instance ${module.secrets_manager.secrets_manager_guid}" + description = "Topic for Secrets Manager events routing" + sources { + id = module.secrets_manager.secrets_manager_crn + rules { + enabled = true + event_type_filter = "$.*" + } + } +} + +resource "ibm_en_subscription_email" "en_email_subscription" { + count = length(var.event_notifications_email_list) > 0 ? 1 : 0 + instance_guid = module.event_notifications.guid + name = "Email for Secrets Manager Subscription" + description = "Subscription for Secret Manager Events" + destination_id = [for s in toset(data.ibm_en_destinations.en_sm_destinations.destinations) : s.id if s.type == "smtp_ibm"][0] + topic_id = ibm_en_topic.en_sm_topic.topic_id + attributes { + add_notification_payload = true + reply_to_mail = "no-reply@ibm.com" + reply_to_name = "Secret Manager Event Notifications Bot" + from_name = "compliancealert@ibm.com" + invited = var.event_notifications_email_list + } +} + +######################################################################################################### +# COS +######################################################################################################### + +module "cos" { + source = "terraform-ibm-modules/cos/ibm//modules/fscloud" + version = "10.5.9" + resource_group_id = module.resource_group.resource_group_id + create_cos_instance = true + cos_instance_name = "${var.prefix}-cos-instance" + cos_plan = "standard" # Possible values are `standard` or `cos-one-rate-plan`. +} + +######################################################################################################### +# Secrets Manager service credentials for COS +######################################################################################################### + +# create s2s auth policy with Secrets Manager +resource "ibm_iam_authorization_policy" "cos_secrets_manager_key_manager" { + source_service_name = "secrets-manager" + source_resource_instance_id = module.secrets_manager.secrets_manager_guid + target_service_name = "cloud-object-storage" + target_resource_instance_id = module.cos.cos_instance_guid + roles = ["Key Manager"] + description = "Allow Secrets Manager with instance id ${module.secrets_manager.secrets_manager_guid} to manage key for the COS instance" +} + +# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 +resource "time_sleep" "wait_for_cos_authorization_policy" { + depends_on = [ibm_iam_authorization_policy.cos_secrets_manager_key_manager] + create_duration = "30s" +} + +######################################################################################################### +# Cloud Logs +######################################################################################################### + +locals { + data_bucket_name = "${var.prefix}-cloud-logs-logs-bucket" + metrics_bucket_name = "${var.prefix}-cloud-logs-metrics-bucket" +} + +module "cloud_logs" { + depends_on = [time_sleep.wait_for_cos_authorization_policy] + source = "terraform-ibm-modules/cloud-logs/ibm" + version = "1.10.0" + resource_group_id = module.resource_group.resource_group_id + region = var.region + instance_name = "${var.prefix}-cloud-logs" + plan = "standard" # not a variable because there is only one option + service_endpoints = "public-and-private" # not a variable because there is only one option + data_storage = { + logs_data = { + enabled = true + bucket_crn = module.cloud_logs_buckets.buckets[local.data_bucket_name].bucket_crn + bucket_endpoint = module.cloud_logs_buckets.buckets[local.data_bucket_name].s3_endpoint_direct + skip_cos_auth_policy = false + }, + metrics_data = { + enabled = true + bucket_crn = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].bucket_crn + bucket_endpoint = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].s3_endpoint_direct + skip_cos_auth_policy = false + } + } + skip_logs_routing_auth_policy = false +} + +module "cloud_logs_buckets" { + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.8" + bucket_configs = [ + { + bucket_name = local.data_bucket_name + kms_key_crn = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn + kms_guid = module.kms.kms_guid + kms_encryption_enabled = false + region_location = var.region + resource_instance_id = module.cos.cos_instance_id + add_bucket_name_suffix = true + management_endpoint_type = "direct" + storage_class = "smart" + force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + metrics_monitoring_crn = module.cloud_monitoring.crn + } + }, + { + bucket_name = local.metrics_bucket_name + kms_key_crn = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn + kms_guid = module.kms.kms_guid + kms_encryption_enabled = false + region_location = var.region + resource_instance_id = module.cos.cos_instance_id + add_bucket_name_suffix = true + management_endpoint_type = "direct" + storage_class = "smart" + skip_iam_authorization_policy = true + force_delete = true # If this is set to false, and the bucket contains data, the destroy will fail. Setting it to false on destroy has no impact, it has to be set on apply, so hence hard coding to true." + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + metrics_monitoring_crn = module.cloud_monitoring.crn + } + } + ] +} + +######################################################################################################### +# Activity Tracker +######################################################################################################### + +locals { + activity_tracker_bucket_config = { + class = "smart" + name = local.activity_tracker_cos_target_bucket_name + } + + at_buckets_config = local.activity_tracker_bucket_config != null ? [local.activity_tracker_bucket_config] : [] + + archive_rule = length(local.at_buckets_config) != 0 ? { + enable = true + days = 90 + type = "Glacier" + } : null + + expire_rule = length(local.at_buckets_config) != 0 ? { + enable = true + days = 366 + } : null + activity_tracker_cos_target_bucket_name = "${var.prefix}-at-events-cos-bucket" + activity_tracker_cos_route = [{ + route_name = "${var.prefix}-at-cos-route" + locations = ["*"] + target_ids = [module.activity_tracker.activity_tracker_targets[module.cos.cos_instance_name].id] + }] + activity_tracker_cloud_logs_route = [{ + route_name = "${var.prefix}-at-cloud-logs-route" + locations = ["*"] + target_ids = [module.activity_tracker.activity_tracker_targets[module.cos.cos_instance_name].id] + }] + activity_tracker_routes = concat(local.activity_tracker_cos_route, local.activity_tracker_cloud_logs_route) +} + +module "activity_tracker" { + source = "terraform-ibm-modules/activity-tracker/ibm" + version = "1.5.0" + cos_targets = [ + { + bucket_name = module.at_cos_bucket.buckets[local.activity_tracker_cos_target_bucket_name].bucket_name + endpoint = module.at_cos_bucket.buckets[local.activity_tracker_cos_target_bucket_name].s3_endpoint_private + instance_id = module.cos.cos_instance_crn + target_region = var.region + target_name = module.cos.cos_instance_name + skip_atracker_cos_iam_auth_policy = false + service_to_service_enabled = true + } + ] + + cloud_logs_targets = [ + { + instance_id = module.cloud_logs.crn + target_region = var.region + target_name = module.cos.cos_instance_name + } + ] + + # Routes + activity_tracker_routes = local.activity_tracker_routes +} + +module "at_cos_bucket" { + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.8" + bucket_configs = [ + for value in local.at_buckets_config : + { + bucket_name = value.name + add_bucket_name_suffix = true + kms_guid = module.kms.kms_guid + kms_encryption_enabled = false + kms_key_crn = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn + skip_iam_authorization_policy = false + management_endpoint_type = "direct" + storage_class = "smart" + resource_instance_id = module.cos.cos_instance_id + region_location = var.region + force_delete = true + archive_rule = local.archive_rule + expire_rule = local.expire_rule + metrics_monitoring = { + usage_metrics_enabled = true + request_metrics_enabled = true + # If `existing_monitoring_crn` is not passed, metrics are sent to the instance associated to the container's location unless otherwise specified in the Metrics Router service configuration. + metrics_monitoring_crn = module.cloud_monitoring.crn + } + activity_tracking = { + read_data_events = true + write_data_events = true + management_events = true + } + } + ] +} + +######################################################################################################### +# App Config +######################################################################################################### + +module "app_config" { + source = "terraform-ibm-modules/app-configuration/ibm" + version = "1.14.2" + resource_group_id = module.resource_group.resource_group_id + region = var.region + app_config_name = "${var.prefix}-app-config" + app_config_plan = "enterprise" + app_config_service_endpoints = "public-and-private" # Possible values are `public` or `public-and-private`. + enable_config_aggregator = true + config_aggregator_trusted_profile_name = "${var.prefix}-config-aggregator-trusted-profile" + config_aggregator_resource_collection_regions = ["all"] + config_aggregator_enterprise_trusted_profile_name = "${var.prefix}-config-aggregator-enterprise-trusted-profile" + config_aggregator_enterprise_trusted_profile_template_name = "${var.prefix}-config-aggregator-trusted-profile-template" + config_aggregator_enterprise_account_group_ids_to_assign = ["all"] + kms_encryption_enabled = true + skip_app_config_kms_auth_policy = false + existing_kms_instance_crn = module.kms.key_protect_crn + kms_endpoint_url = module.kms.kms_private_endpoint + root_key_id = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].key_id + enable_event_notifications = true + skip_app_config_event_notifications_auth_policy = false + existing_event_notifications_instance_crn = module.event_notifications.crn + event_notifications_endpoint_url = module.event_notifications.event_notifications_private_endpoint + app_config_event_notifications_source_name = "${var.prefix}-app-config-en" + event_notifications_integration_description = "The App Configuration integration to send notifications of events to users from the Event Notifications instance GUID ${module.event_notifications.guid}" +} + +######################################################################################################### +# App Configuration Event Notifications Configuration +######################################################################################################### + +data "ibm_en_destinations" "en_apprapp_destinations" { + instance_guid = module.event_notifications.guid +} + +resource "ibm_en_topic" "en_apprapp_topic" { + depends_on = [module.app_config] + instance_guid = module.event_notifications.guid + name = "Topic for App Configuration instance ${module.app_config.app_config_guid}" + description = "Topic for App Configuration events routing" + sources { + id = module.app_config.app_config_crn + rules { + enabled = true + event_type_filter = "$.*" + } + } +} + +resource "ibm_en_subscription_email" "apprapp_email_subscription" { + count = length(var.event_notifications_email_list) > 0 ? 1 : 0 + instance_guid = module.event_notifications.guid + name = "Email for App Configuration Subscription" + description = "Subscription for App Configuration Events" + destination_id = [for s in toset(data.ibm_en_destinations.en_apprapp_destinations.destinations) : s.id if s.type == "smtp_ibm"][0] + topic_id = ibm_en_topic.en_apprapp_topic.topic_id + attributes { + add_notification_payload = true + reply_to_mail = "no-reply@ibm.com" + reply_to_name = "App Configuration Event Notifications Bot" + from_name = "compliancealert@ibm.com" + invited = var.event_notifications_email_list + } +} + +######################################################################################################### +# SCC Workload Protection +######################################################################################################### + +module "scc_wp" { + source = "terraform-ibm-modules/scc-workload-protection/ibm" + version = "1.16.4" + name = "${var.prefix}-scc-workload-protection" + region = var.region + resource_group_id = module.resource_group.resource_group_id + resource_key_name = "${var.prefix}-scc-workload-protection-key" + cloud_monitoring_instance_crn = module.cloud_monitoring.crn + scc_wp_service_plan = "graduated-tier" # Possible values are `free-trial` or `graduated-tier`. + app_config_crn = module.app_config.app_config_crn + scc_workload_protection_trusted_profile_name = "${var.prefix}-workload-protection-trusted-profile" + cspm_enabled = true +} + +######################################################################################################### +# COS Bucket for VPC flow logs +######################################################################################################### + + +locals { + vpc_flow_logs_bucket_name = "${var.prefix}-flow-logs-bucket" + # configuration for the flow logs bucket + flow_logs_bucket_config = [{ + bucket_name = local.vpc_flow_logs_bucket_name + add_bucket_name_suffix = true + kms_encryption_enabled = false + kms_guid = module.kms.kms_guid + kms_key_crn = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].crn + skip_iam_authorization_policy = true + management_endpoint_type = "direct" + storage_class = "smart" + resource_instance_id = module.cos.cos_instance_id + region_location = var.region + force_delete = true + archive_rule = { + enable = true + days = 90 + type = "Glacier" # Possible values are `Glacier` or `Accelerated`. + } + expire_rule = { + enable = true + days = 366 + } + object_versioning_enabled = false + }] +} + +# Create COS bucket using the defined bucket configuration +module "vpc_cos_buckets" { + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "10.5.8" + bucket_configs = local.flow_logs_bucket_config +} + +######################################################################################################### +# VPC +######################################################################################################### + +locals { + subnets = { + zone-1 = [ + { + name = "subnet-a" + cidr = "10.10.10.0/24" + public_gateway = true + acl_name = "vpc-acl" + no_addr_prefix = false + } + ], + zone-2 = [ + { + name = "subnet-b" + cidr = "10.20.10.0/24" + public_gateway = true + acl_name = "vpc-acl" + no_addr_prefix = false + } + ], + zone-3 = [ + { + name = "subnet-c" + cidr = "10.30.10.0/24" + public_gateway = true + acl_name = "vpc-acl" + no_addr_prefix = false + } + ] + } + + network_acls = [ + { + name = "vpc-acl" + add_ibm_cloud_internal_rules = true + add_vpc_connectivity_rules = true + prepend_ibm_rules = true + rules = [ + { + name = "allow-443-inbound-source" + action = "allow" + direction = "inbound" + tcp = { + source_port_min = 443 + source_port_max = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-443-inbound-dest" + action = "allow" + direction = "inbound" + tcp = { + port_max = 443 + port_min = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-80-inbound" + action = "allow" + direction = "inbound" + tcp = { + source_port_min = 80 + source_port_max = 80 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-ingress-inbound" + action = "allow" + direction = "inbound" + tcp = { + source_port_min = 30000 + source_port_max = 32767 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-443-outbound-source" + action = "allow" + direction = "outbound" + tcp = { + source_port_min = 443 + source_port_max = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-443-outbound-dest" + action = "allow" + direction = "outbound" + tcp = { + port_min = 443 + port_max = 443 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-80-outbound" + action = "allow" + direction = "outbound" + tcp = { + port_min = 80 + port_max = 80 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + }, + { + name = "allow-all-ingress-outbound" + action = "allow" + direction = "outbound" + tcp = { + port_min = 30000 + port_max = 32767 + } + destination = "0.0.0.0/0" + source = "0.0.0.0/0" + } + ] + } + ] + # create 'use_public_gateways' object + public_gateway_object = { + for key, value in local.subnets : key => value != null ? length([for sub in value : sub.public_gateway if sub.public_gateway]) > 0 ? [for sub in value : sub.public_gateway if sub.public_gateway][0] : false : false + } +} + +# Create VPC +module "vpc" { + source = "terraform-ibm-modules/landing-zone-vpc/ibm" + version = "8.9.1" + resource_group_id = module.resource_group.resource_group_id + region = var.region + create_vpc = true + name = "vpc" + prefix = var.prefix + subnets = local.subnets + network_acls = local.network_acls + clean_default_sg_acl = true + use_public_gateways = local.public_gateway_object + address_prefixes = { + zone-1 = null + zone-2 = null + zone-3 = null + } + enable_vpc_flow_logs = true + create_authorization_policy_vpc_to_cos = true + existing_cos_instance_guid = module.cos.cos_instance_guid + existing_storage_bucket_name = module.vpc_cos_buckets.buckets[local.vpc_flow_logs_bucket_name].bucket_name +} + +######################################################################################################### +# VPE Gateway +######################################################################################################### + +module "vpe_gateway" { + source = "terraform-ibm-modules/vpe-gateway/ibm" + version = "4.6.6" + resource_group_id = module.resource_group.resource_group_id + region = var.region + prefix = var.prefix + vpc_name = module.vpc.vpc_name + vpc_id = module.vpc.vpc_id + subnet_zone_list = module.vpc.subnet_zone_list + service_endpoints = "private" # Possible values are `private` or `public`. +} + +######################################################################################################### +# OCP VPC cluster +######################################################################################################### + +locals { + vpc_subnets = { + # The default behavior is to deploy the worker pool across all subnets within the VPC. + "default" = [ + for subnet in module.vpc.subnet_zone_list : + { + id = subnet.id + zone = subnet.zone + cidr_block = subnet.cidr + } + ] + } + + worker_pools = [ + { + subnet_prefix = "default" + pool_name = "default" + machine_type = "bx2.4x16" + workers_per_zone = 1 + resource_group_id = module.resource_group.resource_group_id + operating_system = "RHCOS" + minSize = 1 + maxSize = 3 + enableAutoscaling = false + boot_volume_encryption_kms_config = { + crk = module.kms.keys[format("%s.%s", local.boot_volume_key_ring_name, local.boot_volume_key_name)].key_id + kms_instance_id = module.kms.kms_guid + kms_account_id = module.kms.kms_account_id + } + additional_security_group_ids = [] + } + ] + cluster_name = "${var.prefix}-openshift" + kms_config = { + crk_id = module.kms.keys[format("%s.%s", local.cluster_key_ring_name, local.cluster_key_name)].key_id + instance_id = module.kms.kms_guid + private_endpoint = true + account_id = module.kms.kms_account_id + } +} + +module "ocp_base" { + source = "../.." + resource_group_id = module.resource_group.resource_group_id + region = var.region + cluster_name = local.cluster_name + force_delete_storage = true + use_existing_cos = true + existing_cos_id = module.cos.cos_instance_crn + vpc_id = module.vpc.vpc_id + vpc_subnets = local.vpc_subnets + ocp_version = "4.19" + worker_pools = local.worker_pools + kms_config = local.kms_config + existing_secrets_manager_instance_crn = module.secrets_manager.secrets_manager_crn + secrets_manager_secret_group_id = module.secret_group.secret_group_id +} + +resource "terraform_data" "delete_secrets" { + input = { + secret_id = module.secret_group.secret_group_id + provider_visibility = var.provider_visibility + secrets_manager_instance_id = module.secrets_manager.secrets_manager_guid + secrets_manager_region = module.secrets_manager.secrets_manager_region + secrets_manager_endpoint = "private" + } + # api key in triggers_replace to avoid it to be printed out in clear text in terraform_data output + triggers_replace = { + api_key = var.ibmcloud_api_key + } + provisioner "local-exec" { + when = destroy + command = "${path.module}/../../solutions/fully-configurable/scripts/delete_secrets.sh ${self.input.secret_id} ${self.input.provider_visibility} ${self.input.secrets_manager_instance_id} ${self.input.secrets_manager_region} ${self.input.secrets_manager_endpoint}" + interpreter = ["/bin/bash", "-c"] + + environment = { + API_KEY = self.triggers_replace.api_key + } + } +} + +module "secret_group" { + source = "terraform-ibm-modules/secrets-manager-secret-group/ibm" + version = "1.3.15" + region = module.secrets_manager.secrets_manager_region + secrets_manager_guid = module.secrets_manager.secrets_manager_guid + secret_group_name = module.ocp_base.cluster_id + secret_group_description = "Secret group for storing ingress certificates for cluster ${local.cluster_name} with id: ${module.ocp_base.cluster_id}" + endpoint_type = "private" } data "ibm_container_cluster_config" "cluster_config" { - cluster_name_id = module.openshift_landing_zone.cluster_id + cluster_name_id = module.ocp_base.cluster_id resource_group_id = module.resource_group.resource_group_id - config_dir = "${path.module}/../../kubeconfig" + config_dir = "${path.module}/kubeconfig" } -############################################################################## +######################################################################################################### # Monitoring Agents -############################################################################## +######################################################################################################### module "monitoring_agent" { source = "terraform-ibm-modules/monitoring-agent/ibm" version = "1.19.0" - cluster_id = module.openshift_landing_zone.cluster_id + cluster_id = module.ocp_base.cluster_id cluster_resource_group_id = module.resource_group.resource_group_id is_vpc_cluster = true - access_key = module.openshift_landing_zone.cloud_monitoring_access_key + access_key = module.cloud_monitoring.access_key instance_region = var.region metrics_filter = [{ exclude = "metricA.*" }, { include = "metricB.*" }] container_filter = [{ type = "exclude", parameter = "kubernetes.namespace.name", name = "kube-system" }] @@ -70,9 +921,9 @@ module "monitoring_agent" { agent_mode = "troubleshooting" } -############################################################################## +######################################################################################################### # Logs Agent -############################################################################## +######################################################################################################### locals { logs_agent_namespace = "ibm-observe" @@ -95,7 +946,7 @@ module "trusted_profile" { cr_type = "ROKS_SA" unique_identifier = "logs-agent-link" links = [{ - crn = module.openshift_landing_zone.cluster_crn + crn = module.ocp_base.cluster_crn namespace = local.logs_agent_namespace name = local.logs_agent_name }] @@ -106,16 +957,16 @@ module "trusted_profile" { module "logs_agent" { source = "terraform-ibm-modules/logs-agent/ibm" version = "1.10.0" - cluster_id = module.openshift_landing_zone.cluster_id + cluster_id = module.ocp_base.cluster_id cluster_resource_group_id = module.resource_group.resource_group_id logs_agent_trusted_profile_id = module.trusted_profile.trusted_profile.id logs_agent_namespace = local.logs_agent_namespace logs_agent_name = local.logs_agent_name - cloud_logs_ingress_endpoint = module.openshift_landing_zone.cloud_logs_ingress_private_endpoint + cloud_logs_ingress_endpoint = module.cloud_logs.ingress_private_endpoint cloud_logs_ingress_port = 3443 logs_agent_additional_metadata = [{ key = "cluster_id" - value = module.openshift_landing_zone.cluster_id + value = module.ocp_base.cluster_id }] logs_agent_resources = { limits = { diff --git a/examples/containerized_app_landing_zone/outputs.tf b/examples/containerized_app_landing_zone/outputs.tf index 48c60d019..04820d97d 100644 --- a/examples/containerized_app_landing_zone/outputs.tf +++ b/examples/containerized_app_landing_zone/outputs.tf @@ -3,28 +3,28 @@ ############################################################################## output "cluster_name" { - value = module.openshift_landing_zone.cluster_name + value = module.ocp_base.cluster_name description = "The name of the provisioned OpenShift cluster." } output "cluster_id" { - value = module.openshift_landing_zone.cluster_id + value = module.ocp_base.cluster_id description = "The unique identifier assigned to the provisioned OpenShift cluster." } output "cluster_crn" { description = "The Cloud Resource Name (CRN) of the provisioned OpenShift cluster." - value = module.openshift_landing_zone.cluster_crn + value = module.ocp_base.cluster_crn } output "workerpools" { description = "A list of worker pools associated with the provisioned cluster" - value = module.openshift_landing_zone.workerpools + value = module.ocp_base.workerpools } output "ocp_version" { description = "The version of OpenShift running on the provisioned cluster." - value = module.openshift_landing_zone.ocp_version + value = module.ocp_base.ocp_version } @@ -34,17 +34,17 @@ output "ocp_version" { output "vpc_name" { description = "Name of the VPC created." - value = module.openshift_landing_zone.vpc_name + value = module.vpc.vpc_name } output "vpc_id" { description = "ID of the VPC created." - value = module.openshift_landing_zone.vpc_id + value = module.vpc.vpc_id } output "vpc_crn" { description = "CRN of the VPC created." - value = module.openshift_landing_zone.vpc_crn + value = module.vpc.vpc_crn } ############################################################################## @@ -53,7 +53,7 @@ output "vpc_crn" { output "public_gateways" { description = "Map of the public gateways by zone." - value = module.openshift_landing_zone.public_gateways + value = module.vpc.public_gateways } ############################################################################## @@ -62,7 +62,7 @@ output "public_gateways" { output "vpc_flow_logs" { description = "Details of the VPC flow logs collector." - value = module.openshift_landing_zone.vpc_flow_logs + value = module.vpc.vpc_flow_logs } ############################################################################## @@ -71,7 +71,7 @@ output "vpc_flow_logs" { output "network_acls" { description = "List of shortnames and IDs of network ACLs." - value = module.openshift_landing_zone.network_acls + value = module.vpc.network_acls } ############################################################################## @@ -80,27 +80,27 @@ output "network_acls" { output "subnet_ids" { description = "The IDs of the subnets." - value = module.openshift_landing_zone.subnet_ids + value = module.vpc.subnet_ids } output "private_path_subnet_id" { description = "The IDs of the subnets." - value = length(module.openshift_landing_zone.subnet_ids) > 0 ? module.openshift_landing_zone.subnet_ids[0] : null + value = length(module.vpc.subnet_ids) > 0 ? module.vpc.subnet_ids[0] : null } output "subnet_detail_list" { description = "A list of subnets containing names, CIDR blocks, and zones." - value = module.openshift_landing_zone.subnet_detail_list + value = module.vpc.subnet_detail_list } output "subnet_zone_list" { description = "A list of subnet IDs and subnet zones." - value = module.openshift_landing_zone.subnet_zone_list + value = module.vpc.subnet_zone_list } output "subnet_detail_map" { description = "A map of subnets containing IDs, CIDR blocks, and zones." - value = module.openshift_landing_zone.subnet_detail_map + value = module.vpc.subnet_detail_map } ############################################################################## @@ -109,12 +109,12 @@ output "subnet_detail_map" { output "vpn_gateways_name" { description = "List of names of VPN gateways." - value = module.openshift_landing_zone.vpn_gateways_name + value = module.vpc.vpn_gateways_name } output "vpn_gateways_data" { description = "Details of VPN gateways data." - value = module.openshift_landing_zone.vpn_gateways_data + value = module.vpc.vpn_gateways_data } ############################################################################## @@ -123,12 +123,12 @@ output "vpn_gateways_data" { output "vpe_ips" { description = "The reserved IPs for endpoint gateways." - value = module.openshift_landing_zone.vpe_ips + value = module.vpe_gateway.vpe_ips } output "vpe_crn" { description = "The CRN of the endpoint gateway." - value = module.openshift_landing_zone.vpe_crn + value = module.vpe_gateway.crn } ############################################################################## @@ -137,16 +137,16 @@ output "vpe_crn" { output "kms_guid" { description = "KMS instance GUID" - value = module.openshift_landing_zone.kms_guid + value = module.kms.kms_guid } output "kms_account_id" { description = "The account ID of the KMS instance." - value = module.openshift_landing_zone.kms_account_id + value = module.kms.kms_account_id } output "kms_instance_crn" { - value = module.openshift_landing_zone.kms_instance_crn + value = module.kms.key_protect_crn description = "The CRN of the KMS instance" } @@ -156,12 +156,12 @@ output "kms_instance_crn" { output "events_notification_crn" { description = "Event Notification crn" - value = module.openshift_landing_zone.events_notification_crn + value = module.event_notifications.crn } output "events_notification_guid" { description = "Event Notification guid" - value = module.openshift_landing_zone.events_notification_guid + value = module.event_notifications.guid } ############################################################################## @@ -170,16 +170,16 @@ output "events_notification_guid" { output "secrets_manager_guid" { description = "GUID of Secrets Manager instance" - value = module.openshift_landing_zone.secrets_manager_guid + value = module.secrets_manager.secrets_manager_guid } output "secrets_manager_crn" { - value = module.openshift_landing_zone.secrets_manager_crn + value = module.secrets_manager.secrets_manager_crn description = "CRN of the Secrets Manager instance" } output "secrets_manager_region" { - value = module.openshift_landing_zone.secrets_manager_region + value = module.secrets_manager.secrets_manager_region description = "Region of the Secrets Manager instance" } @@ -189,12 +189,12 @@ output "secrets_manager_region" { output "cos_instance_crn" { description = "COS instance crn" - value = module.openshift_landing_zone.cos_instance_crn + value = module.cos.cos_instance_crn } output "cos_instance_guid" { description = "COS instance guid" - value = module.openshift_landing_zone.cos_instance_guid + value = module.cos.cos_instance_guid } ############################################################################## @@ -202,26 +202,26 @@ output "cos_instance_guid" { ############################################################################## output "cloud_monitoring_crn" { - value = module.openshift_landing_zone.cloud_monitoring_crn + value = module.cloud_monitoring.crn description = "The id of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_name" { - value = module.openshift_landing_zone.cloud_monitoring_name + value = module.cloud_monitoring.name description = "The name of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_guid" { - value = module.openshift_landing_zone.cloud_monitoring_guid + value = module.cloud_monitoring.guid description = "The guid of the provisioned IBM Cloud Monitoring instance." } output "cloud_monitoring_access_key_name" { - value = module.openshift_landing_zone.cloud_monitoring_access_key_name + value = module.cloud_monitoring.access_key_name description = "The name of the IBM Cloud Monitoring access key for agents to use" } output "cloud_monitoring_access_key" { - value = module.openshift_landing_zone.cloud_monitoring_access_key + value = module.cloud_monitoring.access_key description = "The IBM Cloud Monitoring access key for agents to use" sensitive = true } @@ -231,28 +231,28 @@ output "cloud_monitoring_access_key" { ############################################################################## output "cloud_logs_crn" { - value = module.openshift_landing_zone.cloud_logs_crn + value = module.cloud_logs.crn description = "The id of the provisioned IBM Cloud Logs instance." } output "cloud_logs_guid" { - value = module.openshift_landing_zone.cloud_logs_guid + value = module.cloud_logs.guid description = "The guid of the provisioned IBM Cloud Logs instance." } output "cloud_logs_name" { - value = module.openshift_landing_zone.cloud_logs_name + value = module.cloud_logs.name description = "The name of the provisioned IBM Cloud Logs instance." } output "logs_bucket_crn" { description = "Logs Cloud Object Storage bucket CRN" - value = module.openshift_landing_zone.logs_bucket_crn + value = module.cloud_logs_buckets.buckets[local.data_bucket_name].bucket_crn } output "metrics_bucket_crn" { description = "Metrics Cloud Object Storage bucket CRN" - value = module.openshift_landing_zone.metrics_bucket_crn + value = module.cloud_logs_buckets.buckets[local.metrics_bucket_name].bucket_crn } ############################################################################## @@ -260,17 +260,17 @@ output "metrics_bucket_crn" { ############################################################################## output "activity_tracker_cos_target_bucket_name" { - value = module.openshift_landing_zone.activity_tracker_cos_target_bucket_name + value = module.at_cos_bucket.buckets[local.activity_tracker_cos_target_bucket_name].bucket_name description = "he name of the object storage bucket which is set as activity tracker event routing target to collect audit events." } output "activity_tracker_targets" { - value = module.openshift_landing_zone.activity_tracker_targets + value = module.activity_tracker.activity_tracker_targets description = "The map of created Activity Tracker Event Routing targets" } output "activity_tracker_routes" { - value = module.openshift_landing_zone.activity_tracker_routes + value = module.activity_tracker.activity_tracker_routes description = "The map of created Activity Tracker Event Routing routes" } @@ -280,15 +280,15 @@ output "activity_tracker_routes" { output "scc_workload_protection_id" { description = "SCC Workload Protection instance ID" - value = module.openshift_landing_zone.scc_workload_protection_id + value = module.scc_wp.id } output "scc_workload_protection_crn" { description = "SCC Workload Protection instance CRN" - value = module.openshift_landing_zone.scc_workload_protection_crn + value = module.scc_wp.crn } output "scc_workload_protection_name" { description = "SCC Workload Protection instance name" - value = module.openshift_landing_zone.scc_workload_protection_name + value = module.scc_wp.name } diff --git a/examples/containerized_app_landing_zone/variables.tf b/examples/containerized_app_landing_zone/variables.tf index 1e9483155..5f25467bb 100644 --- a/examples/containerized_app_landing_zone/variables.tf +++ b/examples/containerized_app_landing_zone/variables.tf @@ -40,80 +40,8 @@ variable "existing_resource_group_name" { default = "Default" } -variable "existing_event_notifications_instance_crn" { - type = string - description = "The CRN of the Event Notifications service used to enable lifecycle notifications for your Secrets Manager instance." - default = null -} - -variable "existing_kms_instance_crn" { - type = string - default = null - description = "The CRN of an existing KMS instance." - - validation { - condition = anytrue([ - can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)), - var.existing_kms_instance_crn == null, - ]) - error_message = "The provided KMS instance CRN in the input 'existing_kms_instance_crn' in not valid." - } -} - -variable "existing_cluster_kms_key_crn" { - type = string - default = null - description = "The CRN of an existing KMS key to use for encrypting the Object Storage of the Cluster. If no value is set for this variable, specify a value for `existing_kms_instance_crn` variable to create a key ring and key." - - validation { - condition = anytrue([ - can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_cluster_kms_key_crn)), - var.existing_cluster_kms_key_crn == null, - ]) - error_message = "The provided KMS key CRN in the input 'existing_cluster_kms_key_crn' in not valid." - } - - validation { - condition = var.existing_cluster_kms_key_crn != null ? var.existing_kms_instance_crn == null : true - error_message = "A value should not be passed for 'existing_kms_instance_crn' when passing an existing key value using the 'existing_cluster_kms_key_crn' input." - } -} - -variable "existing_boot_volume_kms_key_crn" { - type = string - default = null - description = "The CRN of an existing KMS key to use to encrypt the the block storage volumes for VPC. If no value is set for this variable, specify a value for either the `existing_kms_instance_crn` variable to create a key ring and key." - - validation { - condition = anytrue([ - can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_boot_volume_kms_key_crn)), - var.existing_boot_volume_kms_key_crn == null, - ]) - error_message = "The provided KMS key CRN in the input 'existing_boot_volume_kms_key_crn' in not valid." - } -} - -variable "existing_secrets_manager_crn" { - type = string - description = "The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created." - default = null -} - - -variable "existing_cos_instance_crn" { - type = string - description = "The CRN of an existing Object Storage instance." - default = null -} - -variable "existing_cloud_monitoring_crn" { - type = string - default = null - description = "The CRN of an existing Cloud Monitoring instance. If not supplied, a new instance will be created." -} - -variable "existing_cloud_logs_crn" { - type = string - default = null - description = "The CRN of an existing Cloud Logs instance. If not supplied, a new instance will be created." +variable "event_notifications_email_list" { + type = list(string) + description = "The list of email address to target out when an event is triggered" + default = [] } diff --git a/examples/containerized_app_landing_zone/version.tf b/examples/containerized_app_landing_zone/version.tf index a1a72fb06..5ea3aca45 100644 --- a/examples/containerized_app_landing_zone/version.tf +++ b/examples/containerized_app_landing_zone/version.tf @@ -17,5 +17,9 @@ terraform { source = "hashicorp/kubernetes" version = ">= 2.16.1" } + time = { + source = "hashicorp/time" + version = ">= 0.9.1, < 1.0.0" + } } } diff --git a/tests/other_test.go b/tests/other_test.go index 1fa0b7dc6..a82f00a67 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -203,6 +203,7 @@ func TestOpenshiftLandingZoneExample(t *testing.T) { TarIncludePatterns: []string{ "*.tf", openshiftLandingZoneExampleDir + "/*.tf", + openshiftLandingZoneExampleDir + "/kubeconfig/*.*", fullyConfigurableTerraformDir + "/scripts/*.*", "/scripts/*.*", "kubeconfig/*.*", @@ -212,7 +213,6 @@ func TestOpenshiftLandingZoneExample(t *testing.T) { "modules/kube-audit/scripts/*.*", "modules/kube-audit/helm-charts/kube-audit/*.*", "modules/kube-audit/helm-charts/kube-audit/templates/*.*", - "modules/containerized_app_landing_zone/*.tf", }, TemplateFolder: openshiftLandingZoneExampleDir, Tags: []string{"openshift-landing-zone-test"}, @@ -220,7 +220,7 @@ func TestOpenshiftLandingZoneExample(t *testing.T) { WaitJobCompleteMinutes: 240, IgnoreAdds: testhelper.Exemptions{ List: []string{ - "module.openshift_landing_zone.module.scc_wp.restapi_object.cspm", + "module.scc_wp.restapi_object.cspm", }, }, IgnoreUpdates: testhelper.Exemptions{ @@ -230,7 +230,7 @@ func TestOpenshiftLandingZoneExample(t *testing.T) { "module.monitoring_agent.helm_release.cloud_monitoring_agent", // Have to ignore account settings as other tests may be updating them concurrently // which can cause consistency test to fail if not ignored. - "module.openshift_landing_zone.module.metrics_routing[0].ibm_metrics_router_settings.metrics_router_settings[0]", + "metrics_routing[0].ibm_metrics_router_settings.metrics_router_settings[0]", }, }, })