diff --git a/README.md b/README.md index 7cd4f0d28..4e318c93b 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ By default, the module automatically downloads the required dependencies if they * [Submodules](./modules) * [fscloud](./modules/fscloud) * [kube-audit](./modules/kube-audit) + * [monolith](./modules/monolith) * [worker-pool](./modules/worker-pool) * [Examples](./examples) *
@@ -37,6 +38,7 @@ By default, the module automatically downloads the required dependencies if they * * * + * * * [Contributing](#contributing) diff --git a/examples/monolith/README.md b/examples/monolith/README.md new file mode 100644 index 000000000..dc3552bfa --- /dev/null +++ b/examples/monolith/README.md @@ -0,0 +1,23 @@ +# 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. + +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 diff --git a/examples/monolith/main.tf b/examples/monolith/main.tf new file mode 100644 index 000000000..d56c3c17c --- /dev/null +++ b/examples/monolith/main.tf @@ -0,0 +1,218 @@ +######################################################################################################################## +# 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 + 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 + 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 + 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 +} + +######################################################################################################################## +# 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..d18185c01 --- /dev/null +++ b/examples/monolith/outputs.tf @@ -0,0 +1,303 @@ +######################################################################################################################## +# 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" +} + +############################################################################## +# 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 +############################################################################## + +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..586793129 --- /dev/null +++ b/examples/monolith/variables.tf @@ -0,0 +1,663 @@ +######################################################################################################################## +# 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 "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 + 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 "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 `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 `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\_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 `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 `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 `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 `[| 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 `
"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 `
"all"
]
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 `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 `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 `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\_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.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 `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)
})
)
})
)
})
)
[| 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. |
{
"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
}
}
]
}
]
list(| `[]` | 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 `
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
})
))
})
)
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 `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))
})) | [| 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. |
{
"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"
}
]
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 `list(| `[]` | no | +| [service\_cred](#input\_service\_cred) | Service configuration for COS. |
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)
})
)
})
)
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 |
+| [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 `set(| `[]` | 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 `
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)
})
)
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(| `[]` | 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 | +| [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 | +| [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..7a33e6fad --- /dev/null +++ b/modules/monolith/main.tf @@ -0,0 +1,925 @@ +################################################################################# +# 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}" + + 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 +} diff --git a/modules/monolith/outputs.tf b/modules/monolith/outputs.tf new file mode 100644 index 000000000..b66be2b21 --- /dev/null +++ b/modules/monolith/outputs.tf @@ -0,0 +1,322 @@ +############################################################################## +# 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 +} + +############################################################################## +# 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 +############################################################################## + +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..4025f2ec9 --- /dev/null +++ b/modules/monolith/variables.tf @@ -0,0 +1,2019 @@ +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 `
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), [])
})
)