From 09422f505307d6c310150fb815dde526c9130d35 Mon Sep 17 00:00:00 2001 From: whoffler Date: Thu, 1 May 2025 14:51:57 +0100 Subject: [PATCH 01/22] fully configurable elasticsearch solution --- .catalog-onboard-pipeline.yaml | 8 +- .secrets.baseline | 4 +- cra-config.yaml | 5 +- ibm_catalog.json | 328 ++++++++++++- .../DA-cbr_rules.md | 0 .../DA-types.md | 0 .../README.md | 6 +- .../catalogValidationValues.json.template | 8 + .../{standard => fully-configurable}/main.tf | 23 +- .../{standard => fully-configurable}/moved.tf | 0 .../outputs.tf | 16 + .../provider.tf | 0 .../variables.tf | 95 +++- .../version.tf | 0 solutions/security-enforced/README.md | 18 + .../catalogValidationValues.json.template | 8 + solutions/security-enforced/main.tf | 58 +++ solutions/security-enforced/outputs.tf | 61 +++ solutions/security-enforced/variables.tf | 438 ++++++++++++++++++ solutions/security-enforced/version.tf | 14 + .../catalogValidationValues.json.template | 8 - tests/pr_test.go | 110 +++-- 22 files changed, 1110 insertions(+), 98 deletions(-) rename solutions/{standard => fully-configurable}/DA-cbr_rules.md (100%) rename solutions/{standard => fully-configurable}/DA-types.md (100%) rename solutions/{standard => fully-configurable}/README.md (93%) create mode 100644 solutions/fully-configurable/catalogValidationValues.json.template rename solutions/{standard => fully-configurable}/main.tf (95%) rename solutions/{standard => fully-configurable}/moved.tf (100%) rename solutions/{standard => fully-configurable}/outputs.tf (75%) rename solutions/{standard => fully-configurable}/provider.tf (100%) rename solutions/{standard => fully-configurable}/variables.tf (88%) rename solutions/{standard => fully-configurable}/version.tf (100%) create mode 100644 solutions/security-enforced/README.md create mode 100644 solutions/security-enforced/catalogValidationValues.json.template create mode 100644 solutions/security-enforced/main.tf create mode 100644 solutions/security-enforced/outputs.tf create mode 100644 solutions/security-enforced/variables.tf create mode 100644 solutions/security-enforced/version.tf delete mode 100644 solutions/standard/catalogValidationValues.json.template diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml index 9a791ad9..fc5dd94b 100644 --- a/.catalog-onboard-pipeline.yaml +++ b/.catalog-onboard-pipeline.yaml @@ -6,7 +6,13 @@ offerings: catalog_id: 7df1e4ca-d54c-4fd0-82ce-3d13247308cd offering_id: 7ee5876d-6e30-49d1-be25-259a442085e8 variations: - - name: standard + - name: fully-configurable + mark_ready: true + install_type: fullstack + scc: + instance_id: 1c7d5f78-9262-44c3-b779-b28fe4d88c37 + region: us-south + - name: security-enforced mark_ready: true install_type: fullstack scc: diff --git a/.secrets.baseline b/.secrets.baseline index a933ea3d..8f9a8e14 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-03-02T09:01:42Z", + "generated_at": "2025-03-24T11:10:21Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -87,7 +87,7 @@ "verified_result": null } ], - "solutions/standard/DA-types.md": [ + "solutions/fully-configurable/DA-types.md": [ { "hashed_secret": "44cdfc3615970ada14420caaaa5c5745fca06002", "is_secret": false, diff --git a/cra-config.yaml b/cra-config.yaml index 8a1d6b57..cc4289fa 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -1,12 +1,11 @@ # More info about this file at https://github.com/terraform-ibm-modules/common-pipeline-assets/blob/main/.github/workflows/terraform-test-pipeline.md#cra-config-yaml version: "v1" CRA_TARGETS: - - CRA_TARGET: "solutions/standard" # Target directory for CRA scan. If not provided, the CRA Scan will not be run. + - CRA_TARGET: "solutions/fully-configurable" # Target directory for CRA scan. If not provided, the CRA Scan will not be run. CRA_IGNORE_RULES_FILE: "cra-tf-validate-ignore-rules.json" # CRA Ignore file to use. If not provided, it checks the repo root directory for `cra-tf-validate-ignore-rules.json` PROFILE_ID: "fe96bd4d-9b37-40f2-b39f-a62760e326a3" # SCC profile ID (currently set to 'IBM Cloud Framework for Financial Services' '1.7.0' profile). CRA_ENVIRONMENT_VARIABLES: TF_VAR_existing_kms_instance_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" TF_VAR_existing_kms_key_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9:key:76170fae-4e0c-48c3-8ebe-326059ebb533" TF_VAR_provider_visibility: "public" - TF_VAR_resource_group_name: "test-es-cra" - TF_VAR_use_existing_resource_group: false + TF_VAR_existing_resource_group_name: "geretain-test-elasticsearch" diff --git a/ibm_catalog.json b/ibm_catalog.json index b6bc40dd..d651221a 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -22,7 +22,7 @@ "nosql" ], "short_description": "Creates and configures an instance of IBM Cloud Databases for Elasticsearch.", - "long_description": "This architecture supports creating and configuring an instance of Databases for Elasticsearch with KMS encryption.", + "long_description": "This architecture supports creating and configuring an instance of [Databases for Elasticsearch](https://www.ibm.com/products/databases-for-elasticsearch), with optional KMS encryption. This Terraform-based automation is part of a broader suite of IBM-maintained Infrastructure as Code (IaC) asset collection, each following the naming pattern \"Cloud automation for *servicename*\" and focusing on single IBM Cloud service. These single-service deployable architectures can be used on their own to streamline and automate service deployments through an [IaC approach](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-understanding-projects), or assembled together into a broader [automated IaC stack](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-config-stack) to automate the deployment of an end-to-end solution architecture.", "offering_docs_url": "https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/README.md", "offering_icon_url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/main/images/elasticsearch_icon.svg", "provider_name": "IBM", @@ -51,10 +51,10 @@ ], "flavors": [ { - "label": "Standard", - "name": "standard", + "label": "Fully configurable", + "name": "fully-configurable", "install_type": "fullstack", - "working_directory": "solutions/standard", + "working_directory": "solutions/fully-configurable", "compliance": { "authority": "scc-v3", "profiles": [ @@ -112,12 +112,16 @@ ] }, { - "key": "use_existing_resource_group", - "required": true - }, - { - "key": "resource_group_name", - "required": true + "key": "existing_resource_group_name", + "required": true, + "custom_config": { + "type": "resource_group", + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "identifier": "rg_name" + } + } }, { "key": "prefix", @@ -178,7 +182,7 @@ ] }, { - "key": "name" + "key": "elasticsearch_name" }, { "key": "existing_elasticsearch_instance_crn" @@ -196,6 +200,19 @@ } ] }, + { + "key": "service_endpoints", + "options": [ + { + "displayname": "private", + "value": "private" + }, + { + "displayname": "public", + "value": "public" + } + ] + }, { "key": "elasticsearch_version", "required": false, @@ -220,10 +237,10 @@ ] }, { - "key": "tags" + "key": "elasticsearch_tags" }, { - "key": "access_tags" + "key": "elasticsearch_access_tags" }, { "key": "auto_scaling" @@ -325,7 +342,7 @@ "key": "skip_es_kms_auth_policy" }, { - "key": "backup_crn" + "key": "elasticsearch_backup_crn" }, { "key": "enable_elser_model" @@ -389,6 +406,289 @@ "key": "cbr_rules" } ] + }, + { + "label": "Security Enforced", + "name": "security-enforced", + "install_type": "fullstack", + "working_directory": "solutions/security-enforced", + "compliance": { + "authority": "scc-v3", + "profiles": [ + { + "profile_name": "IBM Cloud Framework for Financial Services", + "profile_version": "1.6.0" + } + ] + }, + "iam_permissions": [ + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "service_name": "databases-for-elasticsearch" + } + ], + "architecture": { + "descriptions": "This architecture creates an instance of IBM Cloud Databases for Elasticsearch instance with KMS encryption. Supports autoscaling.", + "features": [ + { + "title": " Creates an instance of Databases for Elasticsearch", + "description": "This architecture creates an instance of IBM Cloud Databases for Elasticsearch with KMS encryption. It accepts or creates a resource group, and provides autoscaling rules." + } + ], + "diagrams": [ + { + "diagram": { + "caption": "Databases for Elasticsearch instance on IBM Cloud", + "url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/main/reference-architecture/deployable-architecture-elasticsearch.svg", + "type": "image/svg+xml" + }, + "description": "This architecture supports creating and configuring an instance of Databases for Elasticsearch instance with KMS encryption." + } + ] + }, + "configuration": [ + { + "key": "ibmcloud_api_key" + }, + { + "key": "existing_resource_group_name", + "required": true, + "custom_config": { + "type": "resource_group", + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "identifier": "rg_name" + } + } + }, + { + "key": "prefix", + "required": true, + "description": "Prefix to add to all resources created by this solution. To not use any prefix value, you can enter the string `__NULL__`." + }, + { + "key": "region", + "required": true, + "options": [ + { + "displayname": "Chennai (che01)", + "value": "che01" + }, + { + "displayname": "Dallas (us-south)", + "value": "us-south" + }, + { + "displayname": "Frankfurt (eu-de)", + "value": "eu-de" + }, + { + "displayname": "London (eu-gb)", + "value": "eu-gb" + }, + { + "displayname": "Madrid (eu-es)", + "value": "eu-es" + }, + { + "displayname": "Osaka (jp-osa)", + "value": "jp-osa" + }, + { + "displayname": "Paris (par01)", + "value": "par01" + }, + { + "displayname": "Sao Paulo (br-sao)", + "value": "br-sao" + }, + { + "displayname": "Sydney (au-syd)", + "value": "au-syd" + }, + { + "displayname": "Toronto (ca-tor)", + "value": "ca-tor" + }, + { + "displayname": "Tokyo (jp-tok)", + "value": "jp-tok" + }, + { + "displayname": "Washington (us-east)", + "value": "us-east" + } + ] + }, + { + "key": "elasticsearch_name" + }, + { + "key": "existing_elasticsearch_instance_crn" + }, + { + "key": "plan", + "options": [ + { + "displayname": "enterprise", + "value": "enterprise" + }, + { + "displayname": "platinum", + "value": "platinum" + } + ] + }, + { + "key": "elasticsearch_version", + "required": false, + "default_value": "__NULL__", + "options": [ + { + "displayname": "preferred", + "value": "__NULL__" + }, + { + "displayname": "8.15", + "value": "8.15" + }, + { + "displayname": "8.12", + "value": "8.12" + }, + { + "displayname": "8.10", + "value": "8.10" + } + ] + }, + { + "key": "elasticsearch_tags" + }, + { + "key": "elasticsearch_access_tags" + }, + { + "key": "auto_scaling" + }, + { + "key": "members" + }, + { + "key": "member_memory_mb" + }, + { + "key": "member_cpu_count" + }, + { + "key": "member_disk_mb" + }, + { + "key": "member_host_flavor" + }, + { + "key": "admin_pass" + }, + { + "key": "users" + }, + { + "key": "service_credential_names" + }, + { + "key": "existing_secrets_manager_instance_crn" + }, + { + "key": "service_credential_secrets" + }, + { + "key": "use_existing_admin_pass_secrets_manager_secret_group" + }, + { + "key": "admin_pass_secrets_manager_secret_name" + }, + { + "key": "admin_pass_secrets_manager_secret_group" + }, + { + "key": "skip_elasticsearch_to_secrets_manager_auth_policy" + }, + { + "key": "ibmcloud_kms_api_key" + }, + { + "key": "existing_kms_instance_crn", + "required": true + }, + { + "key": "existing_kms_key_crn" + }, + { + "key": "existing_backup_kms_key_crn" + }, + { + "key": "use_default_backup_encryption_key" + }, + { + "key": "elasticsearch_key_ring_name" + }, + { + "key": "elasticsearch_key_name" + }, + { + "key": "skip_es_kms_auth_policy" + }, + { + "key": "elasticsearch_backup_crn" + }, + { + "key": "enable_elser_model" + }, + { + "key": "elser_model_type", + "options": [ + { + "displayname": ".elser_model_1", + "value": ".elser_model_1" + }, + { + "displayname": ".elser_model_2", + "value": ".elser_model_2" + }, + { + "displayname": ".elser_model_2_linux-x86_64", + "value": ".elser_model_2_linux-x86_64" + } + ] + }, + { + "key": "enable_kibana_dashboard" + }, + { + "key": "kibana_code_engine_new_project_name" + }, + { + "key": "kibana_code_engine_new_app_name" + }, + { + "key": "existing_code_engine_project_id" + }, + { + "key": "kibana_registry_namespace_image" + }, + { + "key": "kibana_image_digest" + }, + { + "key": "kibana_image_port" + }, + { + "key": "cbr_rules" + } + ] } ] } diff --git a/solutions/standard/DA-cbr_rules.md b/solutions/fully-configurable/DA-cbr_rules.md similarity index 100% rename from solutions/standard/DA-cbr_rules.md rename to solutions/fully-configurable/DA-cbr_rules.md diff --git a/solutions/standard/DA-types.md b/solutions/fully-configurable/DA-types.md similarity index 100% rename from solutions/standard/DA-types.md rename to solutions/fully-configurable/DA-types.md diff --git a/solutions/standard/README.md b/solutions/fully-configurable/README.md similarity index 93% rename from solutions/standard/README.md rename to solutions/fully-configurable/README.md index 8fd577c9..90a35ed7 100644 --- a/solutions/standard/README.md +++ b/solutions/fully-configurable/README.md @@ -1,8 +1,10 @@ -# IBM Cloud Databases for Elasticsearch +# IBM Cloud Databases for Elasticsearch (Fully Configurable) + +## Prerequisites +- An existing resource group This architecture creates an instance of IBM Cloud Databases for Elasticsearch and supports provisioning of the following resources: -- A resource group, if one is not passed in. - A KMS root key, if one is not passed in. - An IBM Cloud Databases for Elasticsearch instance with KMS encryption. - Autoscaling rules for the database instance, if provided. diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template new file mode 100644 index 00000000..b6b32f18 --- /dev/null +++ b/solutions/fully-configurable/catalogValidationValues.json.template @@ -0,0 +1,8 @@ +{ + "ibmcloud_api_key": $VALIDATION_APIKEY, + "region": "us-south", + "elasticsearch_tags": $TAGS, + "elasticsearch_name": $PREFIX, + "existing_resource_group_name": "geretain-test-permanent", + "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN +} diff --git a/solutions/standard/main.tf b/solutions/fully-configurable/main.tf similarity index 95% rename from solutions/standard/main.tf rename to solutions/fully-configurable/main.tf index fd4240df..4ff37f22 100644 --- a/solutions/standard/main.tf +++ b/solutions/fully-configurable/main.tf @@ -5,23 +5,15 @@ module "resource_group" { source = "terraform-ibm-modules/resource-group/ibm" version = "1.2.0" - resource_group_name = var.use_existing_resource_group == false ? ((var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.resource_group_name}" : var.resource_group_name) : null - existing_resource_group_name = var.use_existing_resource_group == true ? var.resource_group_name : null + existing_resource_group_name = var.existing_resource_group_name } -####################################################################################################################### -# KMS related variable validation -# (approach based on https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400) -# -# TODO: Replace with terraform cross variable validation: https://github.ibm.com/GoldenEye/issues/issues/10836 -####################################################################################################################### - ####################################################################################################################### # KMS encryption key ####################################################################################################################### locals { - create_new_kms_key = var.existing_elasticsearch_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? 1 : 0 # no need to create any KMS resources if using existing Elasticsearch, passing an existing key, or using IBM owned keys + create_new_kms_key = var.existing_elasticsearch_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? 1 : 0 # no need to create any KMS resources if encryption not enabled, using existing Elasticsearch, passing an existing key, or using IBM owned keys elasticsearch_key_name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.elasticsearch_key_name}" : var.elasticsearch_key_name elasticsearch_key_ring_name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.elasticsearch_key_ring_name}" : var.elasticsearch_key_ring_name } @@ -276,22 +268,23 @@ data "ibm_database_connection" "existing_connection" { # Create new instance module "elasticsearch" { count = var.existing_elasticsearch_instance_crn != null ? 0 : 1 - source = "../../modules/fscloud" + source = "../.." depends_on = [time_sleep.wait_for_authorization_policy, time_sleep.wait_for_backup_kms_authorization_policy] resource_group_id = module.resource_group.resource_group_id - name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.name}" : var.name + name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.elasticsearch_name}" : var.elasticsearch_name region = var.region plan = var.plan skip_iam_authorization_policy = var.skip_es_kms_auth_policy elasticsearch_version = var.elasticsearch_version + service_endpoints = var.service_endpoints use_ibm_owned_encryption_key = var.use_ibm_owned_encryption_key kms_key_crn = local.kms_key_crn backup_encryption_key_crn = local.backup_kms_key_crn use_same_kms_key_for_backups = local.use_same_kms_key_for_backups use_default_backup_encryption_key = var.use_default_backup_encryption_key - backup_crn = var.backup_crn - access_tags = var.access_tags - tags = var.tags + backup_crn = var.elasticsearch_backup_crn + access_tags = var.elasticsearch_access_tags + tags = var.elasticsearch_tags admin_pass = local.admin_pass users = var.users members = var.members diff --git a/solutions/standard/moved.tf b/solutions/fully-configurable/moved.tf similarity index 100% rename from solutions/standard/moved.tf rename to solutions/fully-configurable/moved.tf diff --git a/solutions/standard/outputs.tf b/solutions/fully-configurable/outputs.tf similarity index 75% rename from solutions/standard/outputs.tf rename to solutions/fully-configurable/outputs.tf index bc00a5ae..a42defc6 100644 --- a/solutions/standard/outputs.tf +++ b/solutions/fully-configurable/outputs.tf @@ -59,3 +59,19 @@ output "kibana_app_endpoint" { description = "Code Engine Kibana endpoint URL" value = var.enable_kibana_dashboard ? module.code_engine_kibana[0].app[local.code_engine_app_name].endpoint : null } + +output "cbr_rule_ids" { + description = "CBR rule ids created to restrict Elasticsearch" + value = module.elasticsearch[0].cbr_rule_ids != null ? module.elasticsearch[0].cbr_rule_ids : null +} + +output "adminuser" { + description = "Database admin user name" + value = module.elasticsearch[0].adminuser != null ? module.elasticsearch[0].adminuser : null +} + +output "certificate_base64" { + description = "Database connection certificate" + value = module.elasticsearch[0].certificate_base64 != null ? module.elasticsearch[0].certificate_base64 : null + sensitive = true +} diff --git a/solutions/standard/provider.tf b/solutions/fully-configurable/provider.tf similarity index 100% rename from solutions/standard/provider.tf rename to solutions/fully-configurable/provider.tf diff --git a/solutions/standard/variables.tf b/solutions/fully-configurable/variables.tf similarity index 88% rename from solutions/standard/variables.tf rename to solutions/fully-configurable/variables.tf index 8657adfe..9a4daccd 100644 --- a/solutions/standard/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -8,11 +8,18 @@ variable "ibmcloud_api_key" { sensitive = true } +variable "existing_resource_group_name" { + type = string + description = "The name of an existing resource group to provision the Databases for Elasticsearch in." + default = "Default" + nullable = false +} + variable "provider_visibility" { description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints)." type = string default = "private" - + nullable = false 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'." @@ -21,29 +28,28 @@ variable "provider_visibility" { variable "prefix" { type = string - description = "Prefix to add to all resources created by this solution. To not use any prefix value, you can set this value to `null` or an empty string." - default = "dev" + description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To not use any prefix value, you can set this value to `null` or an empty string." + nullable = true + validation { + condition = (var.prefix == null ? true : + alltrue([ + can(regex("^[a-z]{0,1}[-a-z0-9]{0,14}[a-z0-9]{0,1}$", var.prefix)), + length(regexall("^.*--.*", var.prefix)) == 0 + ]) + ) + error_message = "Prefix must begin with a lowercase letter, contain only lowercase letters, numbers, and - characters. Prefixes must end with a lowercase letter or number and be 16 or fewer characters." + } } ############################################################################## # Input Variables ############################################################################## -variable "resource_group_name" { - type = string - description = "The name of a new or an existing resource group to provision the Databases for Elasicsearch in. If a prefix input variable is specified, the prefix is added to the name in the `-` format." -} - -variable "use_existing_resource_group" { - type = bool - description = "Whether to use an existing resource group." - default = false -} - -variable "name" { +variable "elasticsearch_name" { type = string description = "The name of the Databases for Elasticsearch instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format." default = "elasticsearch" + nullable = false } variable "elasticsearch_version" { @@ -52,7 +58,7 @@ variable "elasticsearch_version" { default = null } -variable "backup_crn" { +variable "elasticsearch_backup_crn" { type = string description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." default = null @@ -70,7 +76,6 @@ variable "region" { type = string description = "The region where you want to deploy your instance, or the region in which your existing instance is in." default = "us-south" - validation { condition = var.existing_elasticsearch_instance_crn != null && var.region != local.existing_elasticsearch_region ? false : true error_message = "The region detected in the 'existing_elasticsearch_instance_crn' value must match the value of the 'region' input variable when passing an existing instance." @@ -81,24 +86,39 @@ variable "plan" { type = string description = "The name of the service plan for your Databases for Elasticsearch instance. Possible values: `enterprise`, `platinum`." default = "platinum" + nullable = false +} + +variable "service_endpoints" { + type = string + description = "Specify whether you want to enable public, or both public and private service endpoints. Possible values: `public`, `public-and-private`" + default = "private" + nullable = false + validation { + condition = contains(["public", "private"], var.service_endpoints) + error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`" + } } variable "existing_elasticsearch_instance_crn" { type = string default = null description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." + nullable = true } variable "enable_elser_model" { type = bool description = "Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch)" default = false + nullable = false } variable "elser_model_type" { type = string description = "Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. Applies only if also 'plan' is set to 'platinum' and 'enable_elser_model' is enabled. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html)" default = ".elser_model_2_linux-x86_64" + nullable = false validation { condition = contains([".elser_model_1", ".elser_model_2", ".elser_model_2_linux-x86_64"], var.elser_model_type) error_message = "The specified elser_model_type is not a valid selection!" @@ -160,24 +180,24 @@ variable "users" { type = optional(string) role = optional(string) })) - description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/standard/DA-types.md)." + description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." default = [] sensitive = true } variable "service_credential_names" { type = map(string) - description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/standard/DA-types.md)." + description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." default = {} } -variable "tags" { +variable "elasticsearch_tags" { type = list(any) description = "The list of tags to be added to the Databases for Elasticsearch instance." default = [] } -variable "access_tags" { +variable "elasticsearch_access_tags" { type = list(string) description = "A list of access tags to apply to the Databases for Elasticsearch instance created by the solution. [Learn more](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." default = [] @@ -210,7 +230,7 @@ variable "auto_scaling" { rate_units = optional(string, "mb") }) }) - description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/standard/DA-types.md)." + description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." default = null } @@ -252,18 +272,33 @@ variable "existing_kms_instance_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. Applies only if `use_ibm_owned_encryption_key` is false. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_instance_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_kms_instance_crn' should not be set" + } } variable "existing_kms_key_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_key_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_kms_key_crn' should not be set" + } } variable "existing_backup_kms_key_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" + } } variable "use_default_backup_encryption_key" { @@ -315,6 +350,16 @@ variable "existing_secrets_manager_instance_crn" { type = string default = null description = "The CRN of existing secrets manager to use to create service credential secrets for Databases for Elasticsearch instance." + + validation { + condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_group != null : true + error_message = "`admin_pass_secrets_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set." + } + + validation { + condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_name != null : true + error_message = "`admin_pass_secrets_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set." + } } variable "existing_secrets_manager_endpoint_type" { @@ -345,7 +390,7 @@ variable "service_credential_secrets" { })) })) default = [] - description = "Service credential secrets configuration for Databases for Elasticsearch. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/standard/DA-types.md#service-credential-secrets)." + description = "Service credential secrets configuration for Databases for Elasticsearch. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#service-credential-secrets)." validation { # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select the IBM Cloud Database and select the role @@ -459,7 +504,7 @@ variable "kibana_image_port" { } variable "kibana_visibility" { - description = "Specify the visibility of Kibana application in order to define which endpoint is available for receiving the requests. Valid values are 'local_public', 'local_private' and 'local' and it is only applicable if `enable_kibana_dashboard` is true. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/standard/DA-types.md#options-for-kibana_visibility)." + description = "Specify the visibility of Kibana application in order to define which endpoint is available for receiving the requests. Valid values are 'local_public', 'local_private' and 'local' and it is only applicable if `enable_kibana_dashboard` is true. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#options-for-kibana_visibility)." type = string default = "local_private" validation { @@ -488,6 +533,6 @@ variable "cbr_rules" { })) }))) })) - description = "(Optional, list) List of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/standard/DA-cbr_rules.md)" + description = "(Optional, list) List of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-cbr_rules.md)" default = [] } diff --git a/solutions/standard/version.tf b/solutions/fully-configurable/version.tf similarity index 100% rename from solutions/standard/version.tf rename to solutions/fully-configurable/version.tf diff --git a/solutions/security-enforced/README.md b/solutions/security-enforced/README.md new file mode 100644 index 00000000..49071c03 --- /dev/null +++ b/solutions/security-enforced/README.md @@ -0,0 +1,18 @@ +# IBM Cloud Databases for Elasticsearch (Security Enforced) + +## Prerequisites +- An existing resource group + +This architecture creates an instance of IBM Cloud Databases for Elasticsearch and supports provisioning of the following resources: + +- A KMS root key, if one is not passed in. +- An IBM Cloud Databases for Elasticsearch instance with KMS encryption. +- Autoscaling rules for the database instance, if provided. +- Install and start the Elastic's Natural Language Processing model, if enabled. +- Kibana dashboard for Elasticsearch, if enabled. + +**Note on accessing Kibana:** If Kibana is enabled, you can access the Kibana application over a IBM private network using the method outlined [here](https://cloud.ibm.com/docs/codeengine?topic=codeengine-vpe). + +![fscloud-elastic-search](../../reference-architecture/deployable-architecture-elasticsearch.svg) + +:exclamation: **Important:** This solution is not intended to be called by other modules because it contains a provider configuration and is not compatible with the `for_each`, `count`, and `depends_on` arguments. For more information, see [Providers Within Modules](https://developer.hashicorp.com/terraform/language/modules/develop/providers). diff --git a/solutions/security-enforced/catalogValidationValues.json.template b/solutions/security-enforced/catalogValidationValues.json.template new file mode 100644 index 00000000..b6b32f18 --- /dev/null +++ b/solutions/security-enforced/catalogValidationValues.json.template @@ -0,0 +1,8 @@ +{ + "ibmcloud_api_key": $VALIDATION_APIKEY, + "region": "us-south", + "elasticsearch_tags": $TAGS, + "elasticsearch_name": $PREFIX, + "existing_resource_group_name": "geretain-test-permanent", + "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN +} diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf new file mode 100644 index 00000000..fc289d59 --- /dev/null +++ b/solutions/security-enforced/main.tf @@ -0,0 +1,58 @@ +module "elasticsearch" { + source = "../fully-configurable" + ibmcloud_api_key = var.ibmcloud_api_key + existing_resource_group_name = var.existing_resource_group_name + provider_visibility = "private" + prefix = var.prefix + elasticsearch_name = var.elasticsearch_name + elasticsearch_version = var.elasticsearch_version + elasticsearch_backup_crn = var.elasticsearch_backup_crn + region = var.region + plan = var.plan + existing_elasticsearch_instance_crn = var.existing_elasticsearch_instance_crn + enable_elser_model = var.enable_elser_model + elser_model_type = var.elser_model_type + # ICD hosting model properties + members = var.members + member_cpu_count = var.member_cpu_count + member_disk_mb = var.member_disk_mb + member_host_flavor = var.member_host_flavor + member_memory_mb = var.member_memory_mb + admin_pass = var.admin_pass + users = var.users + service_credential_names = var.service_credential_names + elasticsearch_tags = var.elasticsearch_tags + elasticsearch_access_tags = var.elasticsearch_access_tags + # Auto Scaling + auto_scaling = var.auto_scaling + # Encryption + use_ibm_owned_encryption_key = false + existing_kms_instance_crn = var.existing_kms_instance_crn + existing_kms_key_crn = var.existing_kms_key_crn + existing_backup_kms_key_crn = var.existing_backup_kms_key_crn + use_default_backup_encryption_key = var.use_default_backup_encryption_key + kms_endpoint_type = "private" + skip_es_kms_auth_policy = var.skip_es_kms_auth_policy + elasticsearch_key_ring_name = var.elasticsearch_key_ring_name + elasticsearch_key_name = var.elasticsearch_key_name + ibmcloud_kms_api_key = var.ibmcloud_kms_api_key + # Secrets Manager Service Credentials + service_endpoints = "private" + existing_secrets_manager_instance_crn = var.existing_secrets_manager_instance_crn + existing_secrets_manager_endpoint_type = "private" + service_credential_secrets = var.service_credential_secrets + skip_elasticsearch_to_secrets_manager_auth_policy = var.skip_elasticsearch_to_secrets_manager_auth_policy + admin_pass_secrets_manager_secret_group = var.admin_pass_secrets_manager_secret_group + use_existing_admin_pass_secrets_manager_secret_group = var.use_existing_admin_pass_secrets_manager_secret_group + admin_pass_secrets_manager_secret_name = var.admin_pass_secrets_manager_secret_name + # Kibana Configuration + kibana_code_engine_new_project_name = var.kibana_code_engine_new_project_name + kibana_code_engine_new_app_name = var.kibana_code_engine_new_app_name + existing_code_engine_project_id = var.existing_code_engine_project_id + enable_kibana_dashboard = var.enable_kibana_dashboard + kibana_registry_namespace_image = var.kibana_registry_namespace_image + kibana_image_digest = var.kibana_image_digest + kibana_image_port = var.kibana_image_port + kibana_visibility = "local_private" + cbr_rules = var.cbr_rules +} diff --git a/solutions/security-enforced/outputs.tf b/solutions/security-enforced/outputs.tf new file mode 100644 index 00000000..7c64dc70 --- /dev/null +++ b/solutions/security-enforced/outputs.tf @@ -0,0 +1,61 @@ +############################################################################## +# Outputs +############################################################################## + +output "id" { + description = "Elasticsearch instance id" + value = module.elasticsearch.id +} + +output "guid" { + description = "Elasticsearch instance guid" + value = module.elasticsearch.guid +} + +output "version" { + description = "Elasticsearch instance version" + value = module.elasticsearch.version +} + +output "crn" { + description = "Elasticsearch instance crn" + value = module.elasticsearch.crn +} + +output "cbr_rule_ids" { + description = "CBR rule ids created to restrict Elasticsearch" + value = module.elasticsearch.cbr_rule_ids +} + +output "service_credentials_json" { + description = "Service credentials json map" + value = module.elasticsearch.service_credentials_json + sensitive = true +} + +output "service_credentials_object" { + description = "Service credentials object" + value = module.elasticsearch.service_credentials_object + sensitive = true +} + +output "adminuser" { + description = "Database admin user name" + value = module.elasticsearch.adminuser +} + +output "hostname" { + description = "Database connection hostname" + value = module.elasticsearch.hostname +} + +output "port" { + description = "Database connection port" + value = module.elasticsearch.port +} + +output "certificate_base64" { + description = "Database connection certificate" + value = module.elasticsearch.certificate_base64 + sensitive = true +} diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf new file mode 100644 index 00000000..b82ea807 --- /dev/null +++ b/solutions/security-enforced/variables.tf @@ -0,0 +1,438 @@ +############################################################################## +# DA extra +############################################################################## + +variable "ibmcloud_api_key" { + type = string + description = "The IBM Cloud API key to deploy resources." + sensitive = true +} + +variable "existing_resource_group_name" { + type = string + description = "The name of an existing resource group to provision the Databases for Elasticsearch in." + default = "Default" + nullable = false +} + +variable "prefix" { + type = string + description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To not use any prefix value, you can set this value to `null` or an empty string." + nullable = true + validation { + condition = (var.prefix == null ? true : + alltrue([ + can(regex("^[a-z]{0,1}[-a-z0-9]{0,14}[a-z0-9]{0,1}$", var.prefix)), + length(regexall("^.*--.*", var.prefix)) == 0 + ]) + ) + error_message = "Prefix must begin with a lowercase letter, contain only lowercase letters, numbers, and - characters. Prefixes must end with a lowercase letter or number and be 16 or fewer characters." + } +} + +############################################################################## +# Input Variables +############################################################################## + +variable "elasticsearch_name" { + type = string + description = "The name of the Databases for Elasticsearch instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + default = "elasticsearch" + nullable = false +} + +variable "elasticsearch_version" { + type = string + description = "The version of the Databases for Elasticsearch instance. If no value is specified, the current preferred version of Databases for Elasticsearch is used." + default = null +} + +variable "elasticsearch_backup_crn" { + type = string + description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." + default = null +} + +variable "region" { + type = string + description = "The region where you want to deploy your instance, or the region in which your existing instance is in." + default = "us-south" + nullable = false +} + +variable "plan" { + type = string + description = "The name of the service plan for your Databases for Elasticsearch instance. Possible values: `enterprise`, `platinum`." + default = "platinum" + nullable = false +} + +variable "existing_elasticsearch_instance_crn" { + type = string + default = null + description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." + nullable = true +} + +variable "enable_elser_model" { + type = bool + description = "Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch)" + default = false + nullable = false +} + +variable "elser_model_type" { + type = string + description = "Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. Applies only if also 'plan' is set to 'platinum' and 'enable_elser_model' is enabled. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html)" + default = ".elser_model_2_linux-x86_64" + nullable = false + validation { + condition = contains([".elser_model_1", ".elser_model_2", ".elser_model_2_linux-x86_64"], var.elser_model_type) + error_message = "The specified elser_model_type is not a valid selection!" + } +} + +############################################################################## +# ICD hosting model properties +############################################################################## + + +variable "members" { + type = number + description = "The number of members that are allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." + default = 3 +} + +variable "member_cpu_count" { + type = number + description = "The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." + default = 3 +} + +variable "member_disk_mb" { + type = number + description = "The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." + default = 5120 +} + +# Use new hosting model for all DA +variable "member_host_flavor" { + type = string + description = "The host flavor per member. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor)." + default = "b3c.4x16.encrypted" + # Prevent null or "", require multitenant or a machine type + validation { + condition = (length(var.member_host_flavor) > 0) + error_message = "Member host flavor must be specified. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor)." + } +} + +variable "member_memory_mb" { + type = number + description = "The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)" + default = 4096 +} + +variable "admin_pass" { + type = string + description = "The password for the database administrator. If the admin password is null, then it is created automatically. You must set 'existing_secrets_manager_instance_crn' to store admin pass into secrets manager. You can specify more users in a user block." + default = null + sensitive = true +} + +variable "users" { + type = list(object({ + name = string + password = string # pragma: allowlist secret + type = optional(string) + role = optional(string) + })) + description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + default = [] + sensitive = true +} + +variable "service_credential_names" { + type = map(string) + description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + default = {} +} + +variable "elasticsearch_tags" { + type = list(any) + description = "The list of tags to be added to the Databases for Elasticsearch instance." + default = [] +} + +variable "elasticsearch_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Databases for Elasticsearch instance created by the solution. [Learn more](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." + default = [] +} + +############################################################## +# Auto Scaling +############################################################## + +variable "auto_scaling" { + type = object({ + disk = object({ + capacity_enabled = optional(bool, false) + free_space_less_than_percent = optional(number, 10) + io_above_percent = optional(number, 90) + io_enabled = optional(bool, false) + io_over_period = optional(string, "15m") + rate_increase_percent = optional(number, 10) + rate_limit_mb_per_member = optional(number, 3670016) + rate_period_seconds = optional(number, 900) + rate_units = optional(string, "mb") + }) + memory = object({ + io_above_percent = optional(number, 90) + io_enabled = optional(bool, false) + io_over_period = optional(string, "15m") + rate_increase_percent = optional(number, 10) + rate_limit_mb_per_member = optional(number, 114688) + rate_period_seconds = optional(number, 900) + rate_units = optional(string, "mb") + }) + }) + description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + default = null +} + +############################################################## +# Encryption +############################################################## + +variable "existing_kms_instance_crn" { + type = string + description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. Applies only if `use_ibm_owned_encryption_key` is false. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_instance_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_kms_instance_crn' should not be set" + } + + validation { + condition = ( + length(compact([var.existing_kms_instance_crn, var.existing_kms_key_crn, var.existing_backup_kms_key_crn])) == 1 ? true : false + ) + error_message = "To enable KMS encryption one of 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn' must be set." + } + + validation { + condition = var.existing_kms_instance_crn == null ? var.existing_kms_key_crn != null : true + error_message = "When using an existing elasticsearch instance 'existing_kms_instance_crn' should not be set" + } +} + +variable "existing_kms_key_crn" { + type = string + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_key_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_kms_key_crn' should not be set" + } +} + +variable "existing_backup_kms_key_crn" { + type = string + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" + } +} + +variable "use_default_backup_encryption_key" { + type = bool + description = "When `use_ibm_owned_encryption_key` is set to false, backups will be encrypted with either the key specified in `existing_kms_key_crn`, in `existing_backup_kms_key_crn`, or with a new key that will be created in the instance specified in the `existing_kms_instance_crn` input. If you do not want to use your own key for backups encryption, you can set this to `true` to use the IBM Cloud Databases default encryption for backups. Alternatively set `use_ibm_owned_encryption_key` to true to use the default encryption for both backups and deployment data." + default = false +} + +variable "skip_es_kms_auth_policy" { + type = bool + description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true." + default = false +} + +variable "elasticsearch_key_ring_name" { + type = string + default = "elasticsearch-key-ring" + description = "The name for the key ring created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "elasticsearch_key_name" { + type = string + default = "elasticsearch-key" + description = "The name for the key created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." +} + +variable "ibmcloud_kms_api_key" { + type = string + description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Elastic Search instance. Leave this input empty if the same account owns both instances." + sensitive = true + default = null +} + +############################################################################## +## Secrets Manager Service Credentials +############################################################################## + +variable "existing_secrets_manager_instance_crn" { + type = string + default = null + description = "The CRN of existing secrets manager to use to create service credential secrets for Databases for Elasticsearch instance." + + validation { + condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_group != null : true + error_message = "`admin_pass_secrets_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set." + } + + validation { + condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_name != null : true + error_message = "`admin_pass_secrets_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set." + } +} + +variable "service_credential_secrets" { + type = list(object({ + secret_group_name = string + secret_group_description = optional(string) + existing_secret_group = optional(bool) + service_credentials = list(object({ + secret_name = string + service_credentials_source_service_role_crn = string + secret_labels = optional(list(string)) + secret_auto_rotation = optional(bool) + secret_auto_rotation_unit = optional(string) + secret_auto_rotation_interval = optional(number) + service_credentials_ttl = optional(string) + service_credential_secret_description = optional(string) + + })) + })) + default = [] + description = "Service credential secrets configuration for Databases for Elasticsearch. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#service-credential-secrets)." + + validation { + # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select the IBM Cloud Database and select the role + condition = alltrue([ + for group in var.service_credential_secrets : alltrue([ + # crn:v?:bluemix; two non-empty segments; three possibly empty segments; :serviceRole or role: non-empty segment + for credential in group.service_credentials : can(regex("^crn:v[0-9]:bluemix(:..*){2}(:.*){3}:(serviceRole|role):..*$", credential.service_credentials_source_service_role_crn)) + ]) + ]) + error_message = "service_credentials_source_service_role_crn must be a serviceRole CRN. See https://cloud.ibm.com/iam/roles" + } + + validation { + condition = length(var.service_credential_secrets) > 0 ? var.existing_secrets_manager_instance_crn != null : true + error_message = "existing_secrets_manager_instance_crn` is required when adding service credentials to a secrets manager secret." + } +} + +variable "skip_elasticsearch_to_secrets_manager_auth_policy" { + type = bool + default = false + description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for Elasticsearch. Set to `true` to use an existing policy." +} + +variable "admin_pass_secrets_manager_secret_group" { + type = string + description = "The name of a new or existing secrets manager secret group for admin password. To use existing secret group, `use_existing_admin_pass_secrets_manager_secret_group` must be set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + default = "elasticsearch-secrets" +} + +variable "use_existing_admin_pass_secrets_manager_secret_group" { + type = bool + description = "Whether to use an existing secrets manager secret group for admin password." + default = false +} + +variable "admin_pass_secrets_manager_secret_name" { + type = string + description = "The name of a new elasticsearch administrator secret. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + default = "elasticsearch-admin-password" +} + +############################################################## +# Kibana Configuration +############################################################## + +variable "kibana_code_engine_new_project_name" { + type = string + description = "The Code Engine project name. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + default = "ce-kibana-project" +} + +variable "kibana_code_engine_new_app_name" { + type = string + description = "The Code Engine application name. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + default = "ce-kibana-app" +} + +variable "existing_code_engine_project_id" { + type = string + description = "Existing code engine project ID to deploy Kibana. If no value is passed, a new code engine project will be created." + default = null +} + +variable "enable_kibana_dashboard" { + type = bool + description = "Set to true to deploy Kibana in Code Engine. NOTE: By default, the Kibana image will be pulled from the official Elastic registry (docker.elastic.co) and is not certified by IBM, however this can be overridden using the `kibana_registry_namespace_image` and `kibana_image_digest` inputs." + default = false +} + +variable "kibana_registry_namespace_image" { + type = string + description = "The Kibana image reference in the format of `[registry-url]/[namespace]/[image]`. This value is used only when `enable_kibana_dashboard` is set to true." + default = "docker.elastic.co/kibana/kibana" +} + +variable "kibana_image_digest" { + type = string + description = "When `enable_kibana_dashboard` is set to true, Kibana is deployed using an image tag compatible with the Elasticsearch version. Alternatively, an image digest in the format `sha256:xxxxx...` can also be specified but it must correspond to a version compatible with the Elasticsearch instance." + default = null + validation { + condition = var.kibana_image_digest == null || can(regex("^sha256:", var.kibana_image_digest)) + error_message = "If provided, the value of kibana_image_digest must start with 'sha256:'." + } + + +} +variable "kibana_image_port" { + description = "Specify the port number used to connect to the Kibana service exposed by the container image. Default port is 5601 and it is only applicable if `enable_kibana_dashboard` is true" + type = number + default = 5601 +} + +############################################################## +# Context-based restriction (CBR) +############################################################## + +variable "cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "(Optional, list) List of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-cbr_rules.md)" + default = [] +} diff --git a/solutions/security-enforced/version.tf b/solutions/security-enforced/version.tf new file mode 100644 index 00000000..ffce2a6e --- /dev/null +++ b/solutions/security-enforced/version.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.3.0" + required_providers { + # The below tflint-ignore is required because although the below provider is not directly required by this submodule, + # it is required by consuming modules, and if not set here, the top level module calling this module will not be + # able to set alternative alias for the provider. + # tflint-ignore: terraform_unused_required_providers + ibm = { + source = "IBM-Cloud/ibm" + # Use "greater than or equal to" range in modules + version = ">= 1.70.0, <2.0.0" + } + } +} diff --git a/solutions/standard/catalogValidationValues.json.template b/solutions/standard/catalogValidationValues.json.template deleted file mode 100644 index e69e502f..00000000 --- a/solutions/standard/catalogValidationValues.json.template +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ibmcloud_api_key": $VALIDATION_APIKEY, - "region": "us-south", - "tags": $TAGS, - "name": $PREFIX, - "resource_group_name": $PREFIX, - "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN -} diff --git a/tests/pr_test.go b/tests/pr_test.go index 9925204a..137996da 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -25,7 +25,8 @@ import ( const completeExampleTerraformDir = "examples/complete" const fscloudExampleTerraformDir = "examples/fscloud" -const standardSolutionTerraformDir = "solutions/standard" +const fullyConfigurableSolutionTerraformDir = "solutions/fully-configurable" +const securityEnforcedSolutionTerraformDir = "solutions/security-enforced" const latestVersion = "8.15" // Use existing resource group @@ -58,19 +59,17 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } -func TestRunStandardSolutionSchematics(t *testing.T) { +func TestRunFullyConfigurableSolutionSchematics(t *testing.T) { t.Parallel() options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ Testing: t, TarIncludePatterns: []string{ "*.tf", - fmt.Sprintf("%s/*.tf", standardSolutionTerraformDir), - fmt.Sprintf("%s/*.tf", fscloudExampleTerraformDir), - fmt.Sprintf("%s/*.tf", "modules/fscloud"), + fmt.Sprintf("%s/*.tf", fullyConfigurableSolutionTerraformDir), fmt.Sprintf("%s/*.sh", "scripts"), }, - TemplateFolder: standardSolutionTerraformDir, + TemplateFolder: fullyConfigurableSolutionTerraformDir, BestRegionYAMLPath: regionSelectionPath, Prefix: "els-sr-da", ResourceGroup: resourceGroup, @@ -78,7 +77,7 @@ func TestRunStandardSolutionSchematics(t *testing.T) { WaitJobCompleteMinutes: 60, }) - serviceCredentialSecrets := []map[string]any{ + serviceCredentialSecrets := []map[string]interface{}{ { "secret_group_name": fmt.Sprintf("%s-secret-group", options.Prefix), "service_credentials": []map[string]string{ @@ -96,17 +95,16 @@ func TestRunStandardSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, - {Name: "access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, + {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, - {Name: "existing_backup_kms_key_crn", Value: permanentResources["hpcs_south_root_key_crn"], DataType: "string"}, {Name: "kms_endpoint_type", Value: "private", DataType: "string"}, - {Name: "resource_group_name", Value: options.Prefix, DataType: "string"}, + {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, {Name: "plan", Value: "platinum", DataType: "string"}, {Name: "enable_elser_model", Value: true, DataType: "bool"}, {Name: "service_credential_names", Value: "{\"admin_test\": \"Administrator\", \"editor_test\": \"Editor\"}", DataType: "map(string)"}, {Name: "existing_secrets_manager_instance_crn", Value: permanentResources["secretsManagerCRN"], DataType: "string"}, {Name: "service_credential_secrets", Value: serviceCredentialSecrets, DataType: "list(object)"}, - {Name: "admin_pass", Value: GetRandomAdminPassword(t), DataType: "string"}, + {Name: "service_endpoints", Value: "private", DataType: "string"}, {Name: "admin_pass_secrets_manager_secret_group", Value: options.Prefix, DataType: "string"}, {Name: "admin_pass_secrets_manager_secret_name", Value: options.Prefix, DataType: "string"}, {Name: "enable_kibana_dashboard", Value: true, DataType: "bool"}, @@ -118,24 +116,25 @@ func TestRunStandardSolutionSchematics(t *testing.T) { assert.Nil(t, err, "This should not have errored") } -func TestRunStandardUpgradeSolution(t *testing.T) { +func TestRunFullyConfigurableUpgradeSolution(t *testing.T) { t.Parallel() options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ Testing: t, - TerraformDir: standardSolutionTerraformDir, + TerraformDir: fullyConfigurableSolutionTerraformDir, BestRegionYAMLPath: regionSelectionPath, Prefix: "els-st-da-upg", ResourceGroup: resourceGroup, CheckApplyResultForUpgrade: true, }) - options.TerraformVars = map[string]any{ - "access_tags": permanentResources["accessTags"], - "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], - "kms_endpoint_type": "public", - "resource_group_name": options.Prefix, - "provider_visibility": "public", + options.TerraformVars = map[string]interface{}{ + "prefix": options.Prefix, + "access_tags": permanentResources["accessTags"], + "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], + "kms_endpoint_type": "public", + "existing_resource_group_name": resourceGroup, + "provider_visibility": "public", // Currently, we can not have upgrade test for elser model, because test provision private endpoint for ES (fscloud profile), and script can not connect to private ES API without schematics // "plan": "platinum", // "enable_elser_model": true, @@ -149,6 +148,60 @@ func TestRunStandardUpgradeSolution(t *testing.T) { } } +func TestRunSecurityEnforcedSolutionSchematics(t *testing.T) { + t.Parallel() + + options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ + Testing: t, + TarIncludePatterns: []string{ + "*.tf", + fmt.Sprintf("%s/*.tf", securityEnforcedSolutionTerraformDir), + fmt.Sprintf("%s/*.tf", fullyConfigurableSolutionTerraformDir), + fmt.Sprintf("%s/*.sh", "scripts"), + }, + TemplateFolder: securityEnforcedSolutionTerraformDir, + BestRegionYAMLPath: regionSelectionPath, + Prefix: "els-sr-da", + ResourceGroup: resourceGroup, + DeleteWorkspaceOnFail: false, + WaitJobCompleteMinutes: 60, + }) + + serviceCredentialSecrets := []map[string]interface{}{ + { + "secret_group_name": fmt.Sprintf("%s-secret-group", options.Prefix), + "service_credentials": []map[string]string{ + { + "secret_name": fmt.Sprintf("%s-cred-reader", options.Prefix), + "service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::role:Viewer", + }, + { + "secret_name": fmt.Sprintf("%s-cred-writer", options.Prefix), + "service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::role:Editor", + }, + }, + }, + } + + options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, + {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, + {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, + {Name: "plan", Value: "platinum", DataType: "string"}, + {Name: "enable_elser_model", Value: true, DataType: "bool"}, + {Name: "service_credential_names", Value: "{\"admin_test\": \"Administrator\", \"editor_test\": \"Editor\"}", DataType: "map(string)"}, + {Name: "existing_secrets_manager_instance_crn", Value: permanentResources["secretsManagerCRN"], DataType: "string"}, + {Name: "service_credential_secrets", Value: serviceCredentialSecrets, DataType: "list(object)"}, + {Name: "admin_pass_secrets_manager_secret_group", Value: options.Prefix, DataType: "string"}, + {Name: "admin_pass_secrets_manager_secret_name", Value: options.Prefix, DataType: "string"}, + {Name: "enable_kibana_dashboard", Value: true, DataType: "bool"}, + {Name: "prefix", Value: options.Prefix, DataType: "string"}, + } + err := options.RunSchematicTest() + assert.Nil(t, err, "This should not have errored") +} + func TestRunExistingInstance(t *testing.T) { t.Parallel() prefix := fmt.Sprintf("elastic-t-%s", strings.ToLower(random.UniqueId())) @@ -191,12 +244,12 @@ func TestRunExistingInstance(t *testing.T) { Testing: t, TarIncludePatterns: []string{ "*.tf", - fmt.Sprintf("%s/*.tf", standardSolutionTerraformDir), + fmt.Sprintf("%s/*.tf", fullyConfigurableSolutionTerraformDir), fmt.Sprintf("%s/*.tf", fscloudExampleTerraformDir), fmt.Sprintf("%s/*.tf", "modules/fscloud"), fmt.Sprintf("%s/*.sh", "scripts"), }, - TemplateFolder: standardSolutionTerraformDir, + TemplateFolder: fullyConfigurableSolutionTerraformDir, BestRegionYAMLPath: regionSelectionPath, Prefix: "els-sr-da", ResourceGroup: resourceGroup, @@ -205,11 +258,11 @@ func TestRunExistingInstance(t *testing.T) { }) options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "prefix", Value: options.Prefix, DataType: "string"}, {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "existing_elasticsearch_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "elasticsearch_crn"), DataType: "string"}, - {Name: "resource_group_name", Value: fmt.Sprintf("%s-resource-group", prefix), DataType: "string"}, + {Name: "existing_resource_group_name", Value: fmt.Sprintf("%s-resource-group", prefix), DataType: "string"}, {Name: "region", Value: region, DataType: "string"}, - {Name: "use_existing_resource_group", Value: true, DataType: "bool"}, {Name: "provider_visibility", Value: "public", DataType: "string"}, } err := options.RunSchematicTest() @@ -229,22 +282,23 @@ func TestRunExistingInstance(t *testing.T) { } // Test the DA when using IBM owned encryption keys -func TestRunStandardSolutionIBMKeys(t *testing.T) { +func TestFullyConfigurableSolutionIBMKeys(t *testing.T) { t.Parallel() options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ Testing: t, - TerraformDir: standardSolutionTerraformDir, + TerraformDir: fullyConfigurableSolutionTerraformDir, Region: "us-south", - Prefix: "es-icd-key", + Prefix: "esicdkey", ResourceGroup: resourceGroup, }) options.TerraformVars = map[string]any{ "elasticsearch_version": "8.12", "provider_visibility": "public", - "resource_group_name": options.Prefix, + "existing_resource_group_name": resourceGroup, "use_ibm_owned_encryption_key": true, + "prefix": options.Prefix, } output, err := options.RunTestConsistency() @@ -255,7 +309,7 @@ func TestRunStandardSolutionIBMKeys(t *testing.T) { func TestPlanValidation(t *testing.T) { options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ Testing: t, - TerraformDir: standardSolutionTerraformDir, + TerraformDir: fullyConfigurableSolutionTerraformDir, Prefix: "validate-plan", ResourceGroup: resourceGroup, Region: "us-south", // skip VPC region picker From 506f89cbed99f94ab829877bff17882e79959183 Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 2 May 2025 08:32:04 +0100 Subject: [PATCH 02/22] SKIP UPGRADE TEST --- cra-config.yaml | 1 + tests/pr_test.go | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cra-config.yaml b/cra-config.yaml index cc4289fa..fffb037d 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -5,6 +5,7 @@ CRA_TARGETS: CRA_IGNORE_RULES_FILE: "cra-tf-validate-ignore-rules.json" # CRA Ignore file to use. If not provided, it checks the repo root directory for `cra-tf-validate-ignore-rules.json` PROFILE_ID: "fe96bd4d-9b37-40f2-b39f-a62760e326a3" # SCC profile ID (currently set to 'IBM Cloud Framework for Financial Services' '1.7.0' profile). CRA_ENVIRONMENT_VARIABLES: + TF_VAR_prefix: "test" TF_VAR_existing_kms_instance_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" TF_VAR_existing_kms_key_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9:key:76170fae-4e0c-48c3-8ebe-326059ebb533" TF_VAR_provider_visibility: "public" diff --git a/tests/pr_test.go b/tests/pr_test.go index 137996da..ee072449 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -130,7 +130,7 @@ func TestRunFullyConfigurableUpgradeSolution(t *testing.T) { options.TerraformVars = map[string]interface{}{ "prefix": options.Prefix, - "access_tags": permanentResources["accessTags"], + "elasticsearch_access_tags": permanentResources["accessTags"], "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], "kms_endpoint_type": "public", "existing_resource_group_name": resourceGroup, @@ -318,11 +318,11 @@ func TestPlanValidation(t *testing.T) { options.TerraformOptions.NoColor = true options.TerraformOptions.Logger = logger.Discard options.TerraformOptions.Vars = map[string]interface{}{ - "prefix": options.Prefix, - "region": "us-south", - "elasticsearch_version": "8.10", - "provider_visibility": "public", - "resource_group_name": options.Prefix, + "prefix": options.Prefix, + "region": "us-south", + "elasticsearch_version": "8.10", + "provider_visibility": "public", + "existing_resource_group_name": options.Prefix, } // Test the DA when using Elser model From 2b106d235366e6ef301d7ff5dfd646ebf0fed16d Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 2 May 2025 11:36:45 +0100 Subject: [PATCH 03/22] SKIP UPGRADE TEST --- .secrets.baseline | 12 ++++++++- cra-config.yaml | 2 +- ibm_catalog.json | 1 + solutions/fully-configurable/variables.tf | 16 +++++++++-- tests/pr_test.go | 33 +++++++++++++---------- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 8f9a8e14..9103cb96 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-03-24T11:10:21Z", + "generated_at": "2025-05-02T09:58:59Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -104,6 +104,16 @@ "type": "Secret Keyword", "verified_result": null } + ], + "tests/pr_test.go": [ + { + "hashed_secret": "8c7c51db5075ebd0369c51e9f14737d9b4c1c21d", + "is_secret": false, + "is_verified": false, + "line_number": 356, + "type": "Base64 High Entropy String", + "verified_result": null + } ] }, "version": "0.13.1+ibm.62.dss", diff --git a/cra-config.yaml b/cra-config.yaml index fffb037d..73e90082 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -6,7 +6,7 @@ CRA_TARGETS: PROFILE_ID: "fe96bd4d-9b37-40f2-b39f-a62760e326a3" # SCC profile ID (currently set to 'IBM Cloud Framework for Financial Services' '1.7.0' profile). CRA_ENVIRONMENT_VARIABLES: TF_VAR_prefix: "test" + TF_VAR_use_ibm_owned_encryption_key: false TF_VAR_existing_kms_instance_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" - TF_VAR_existing_kms_key_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9:key:76170fae-4e0c-48c3-8ebe-326059ebb533" TF_VAR_provider_visibility: "public" TF_VAR_existing_resource_group_name: "geretain-test-elasticsearch" diff --git a/ibm_catalog.json b/ibm_catalog.json index d651221a..7ed4be4e 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -96,6 +96,7 @@ }, { "key": "provider_visibility", + "hidden": true, "options": [ { "displayname": "private", diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 9a4daccd..f9abee72 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -65,8 +65,8 @@ variable "elasticsearch_backup_crn" { validation { condition = anytrue([ - var.backup_crn == null, - can(regex("^crn:.*:backup:", var.backup_crn)) + var.elasticsearch_backup_crn == null, + can(regex("^crn:.*:backup:", var.elasticsearch_backup_crn)) ]) error_message = "backup_crn must be null OR starts with 'crn:' and contains ':backup:'" } @@ -266,6 +266,18 @@ variable "use_ibm_owned_encryption_key" { ) error_message = "When 'use_ibm_owned_encryption_key' is false, you must provide either 'existing_kms_instance_crn' (to create a new key) or 'existing_kms_key_crn' (to use an existing key)." } + + validation { + condition = !var.use_ibm_owned_encryption_key && var.existing_kms_instance_crn == null ? (var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null) : true + error_message = "When not using ibm owned encryption, you must provide either an existing KMS instance with variable `existing_kms_instance_crn` or an existing KMS key using variable `existing_kms_key_crn` or `existing_backup_kms_key_crn`" + } + + validation { + condition = ( + var.use_ibm_owned_encryption_key ? length(compact([var.existing_kms_instance_crn, var.existing_kms_key_crn, var.existing_backup_kms_key_crn])) == 0 : true + ) + error_message = "When using ibm owned encryption keys by setting variable 'use_ibm_owned_encryption_key' to true, 'existing_kms_instance_crn', 'existing_kms_key_crn' and 'existing_backup_kms_key_crn' must not be set." + } } variable "existing_kms_instance_crn" { diff --git a/tests/pr_test.go b/tests/pr_test.go index ee072449..1b56a82c 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -96,6 +96,7 @@ func TestRunFullyConfigurableSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, + {Name: "use_ibm_owned_encryption_key", Value: false, DataType: "bool"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "kms_endpoint_type", Value: "private", DataType: "string"}, {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, @@ -131,6 +132,7 @@ func TestRunFullyConfigurableUpgradeSolution(t *testing.T) { options.TerraformVars = map[string]interface{}{ "prefix": options.Prefix, "elasticsearch_access_tags": permanentResources["accessTags"], + "use_ibm_owned_encryption_key": false, "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], "kms_endpoint_type": "public", "existing_resource_group_name": resourceGroup, @@ -185,6 +187,7 @@ func TestRunSecurityEnforcedSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "use_ibm_owned_encryption_key", Value: false, DataType: "bool"}, {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, @@ -310,7 +313,7 @@ func TestPlanValidation(t *testing.T) { options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ Testing: t, TerraformDir: fullyConfigurableSolutionTerraformDir, - Prefix: "validate-plan", + Prefix: "val-plan", ResourceGroup: resourceGroup, Region: "us-south", // skip VPC region picker }) @@ -319,36 +322,38 @@ func TestPlanValidation(t *testing.T) { options.TerraformOptions.Logger = logger.Discard options.TerraformOptions.Vars = map[string]interface{}{ "prefix": options.Prefix, + "existing_resource_group_name": resourceGroup, "region": "us-south", "elasticsearch_version": "8.10", "provider_visibility": "public", - "existing_resource_group_name": options.Prefix, } // Test the DA when using Elser model - var standardSolutionWithElserModelVars = map[string]interface{}{ - "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], - "enable_elser_model": true, - "plan": "platinum", + var fullyConfigurableSolutionWithElserModelVars = map[string]interface{}{ + "use_ibm_owned_encryption_key": false, + "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], + "enable_elser_model": true, + "plan": "platinum", } // Test the DA when using Kibana dashboard and existing KMS instance - var standardSolutionWithKibanaDashboardVars = map[string]interface{}{ - "enable_kibana_dashboard": true, - "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], - "plan": "enterprise", + var fullyConfigurableSolutionWithKibanaDashboardVars = map[string]interface{}{ + "enable_kibana_dashboard": true, + "use_ibm_owned_encryption_key": false, + "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], + "plan": "enterprise", } // Test the DA when using IBM owned encryption key - var standardSolutionWithUseIbmOwnedEncKey = map[string]interface{}{ + var fullyConfigurableSolutionWithUseIbmOwnedEncKey = map[string]interface{}{ "use_ibm_owned_encryption_key": true, } // Create a map of the variables tfVarsMap := map[string]map[string]interface{}{ - "standardSolutionWithElserModelVars": standardSolutionWithElserModelVars, - "standardSolutionWithKibanaDashboardVars": standardSolutionWithKibanaDashboardVars, - "standardSolutionWithUseIbmOwnedEncKey": standardSolutionWithUseIbmOwnedEncKey, + "fullyConfigurableSolutionWithElserModelVars": fullyConfigurableSolutionWithElserModelVars, + "fullyConfigurableSolutionWithKibanaDashboardVars": fullyConfigurableSolutionWithKibanaDashboardVars, + "fullyConfigurableSolutionWithUseIbmOwnedEncKey": fullyConfigurableSolutionWithUseIbmOwnedEncKey, } _, initErr := terraform.InitE(t, options.TerraformOptions) From 919868d77f4c63332b298cf63a47ea70cb47a8aa Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 2 May 2025 12:16:33 +0100 Subject: [PATCH 04/22] SKIP UPGRADE TEST --- solutions/fully-configurable/outputs.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solutions/fully-configurable/outputs.tf b/solutions/fully-configurable/outputs.tf index a42defc6..d99d07b4 100644 --- a/solutions/fully-configurable/outputs.tf +++ b/solutions/fully-configurable/outputs.tf @@ -62,16 +62,16 @@ output "kibana_app_endpoint" { output "cbr_rule_ids" { description = "CBR rule ids created to restrict Elasticsearch" - value = module.elasticsearch[0].cbr_rule_ids != null ? module.elasticsearch[0].cbr_rule_ids : null + value = var.existing_elasticsearch_instance_crn != null ? null : module.elasticsearch[0].cbr_rule_ids } output "adminuser" { description = "Database admin user name" - value = module.elasticsearch[0].adminuser != null ? module.elasticsearch[0].adminuser : null + value = var.existing_elasticsearch_instance_crn != null ? null : module.elasticsearch[0].adminuser } output "certificate_base64" { description = "Database connection certificate" - value = module.elasticsearch[0].certificate_base64 != null ? module.elasticsearch[0].certificate_base64 : null + value = var.existing_elasticsearch_instance_crn != null ? null : module.elasticsearch[0].certificate_base64 sensitive = true } From 668cff5315432a7eb6798be414b2e321905986a6 Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 2 May 2025 14:21:01 +0100 Subject: [PATCH 05/22] SKIP UPGRADE TEST, add kms_encryption_enabled variable --- .secrets.baseline | 4 ++-- cra-config.yaml | 1 + ibm_catalog.json | 3 +++ solutions/fully-configurable/variables.tf | 13 ++++++++++++- solutions/security-enforced/main.tf | 1 + tests/pr_test.go | 5 +++++ 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 9103cb96..8d2e3a02 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-05-02T09:58:59Z", + "generated_at": "2025-05-02T13:16:14Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -110,7 +110,7 @@ "hashed_secret": "8c7c51db5075ebd0369c51e9f14737d9b4c1c21d", "is_secret": false, "is_verified": false, - "line_number": 356, + "line_number": 361, "type": "Base64 High Entropy String", "verified_result": null } diff --git a/cra-config.yaml b/cra-config.yaml index 73e90082..7116c372 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -6,6 +6,7 @@ CRA_TARGETS: PROFILE_ID: "fe96bd4d-9b37-40f2-b39f-a62760e326a3" # SCC profile ID (currently set to 'IBM Cloud Framework for Financial Services' '1.7.0' profile). CRA_ENVIRONMENT_VARIABLES: TF_VAR_prefix: "test" + TF_VAR_kms_encryption_enabled: true TF_VAR_use_ibm_owned_encryption_key: false TF_VAR_existing_kms_instance_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" TF_VAR_provider_visibility: "public" diff --git a/ibm_catalog.json b/ibm_catalog.json index 7ed4be4e..3c33165b 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -317,6 +317,9 @@ } ] }, + { + "key": "kms_encryption_enabled" + }, { "key": "use_ibm_owned_encryption_key" }, diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index f9abee72..81ebfcc0 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -238,6 +238,17 @@ variable "auto_scaling" { # Encryption ############################################################## +variable "kms_encryption_enabled" { + type = bool + description = "Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." + default = false + + validation { + condition = var.kms_encryption_enabled ? var.existing_kms_instance_crn != null || var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null : true + error_message = "When variable `kms_encryption_enabled` is true and KMS encryption is enabled, you must provide either an existing KMS instance with variable `existing_kms_instance_crn` or an existing KMS key using variable `existing_kms_key_crn` or `existing_backup_kms_key_crn`" + } +} + variable "use_ibm_owned_encryption_key" { type = bool description = "IBM Cloud Databases will secure your deployment's data at rest automatically with an encryption key that IBM hold. Alternatively, you may select your own Key Management System instance and encryption key (Key Protect or Hyper Protect Crypto Services) by setting this to false. If setting to false, a value must be passed for `existing_kms_instance_crn` to create a new key, or `existing_kms_key_crn` and/or `existing_backup_kms_key_crn` to use an existing key." @@ -276,7 +287,7 @@ variable "use_ibm_owned_encryption_key" { condition = ( var.use_ibm_owned_encryption_key ? length(compact([var.existing_kms_instance_crn, var.existing_kms_key_crn, var.existing_backup_kms_key_crn])) == 0 : true ) - error_message = "When using ibm owned encryption keys by setting variable 'use_ibm_owned_encryption_key' to true, 'existing_kms_instance_crn', 'existing_kms_key_crn' and 'existing_backup_kms_key_crn' must not be set." + error_message = "When using ibm owned encryption keys by setting variable 'use_ibm_owned_encryption_key' to true, 'existing_kms_instance_crn', 'existing_kms_key_crn' and 'existing_backup_kms_key_crn' should not be set." } } diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf index fc289d59..2011484c 100644 --- a/solutions/security-enforced/main.tf +++ b/solutions/security-enforced/main.tf @@ -26,6 +26,7 @@ module "elasticsearch" { # Auto Scaling auto_scaling = var.auto_scaling # Encryption + kms_encryption_enabled = true use_ibm_owned_encryption_key = false existing_kms_instance_crn = var.existing_kms_instance_crn existing_kms_key_crn = var.existing_kms_key_crn diff --git a/tests/pr_test.go b/tests/pr_test.go index 1b56a82c..91bf56b8 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -96,6 +96,7 @@ func TestRunFullyConfigurableSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, + {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, {Name: "use_ibm_owned_encryption_key", Value: false, DataType: "bool"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "kms_endpoint_type", Value: "private", DataType: "string"}, @@ -132,6 +133,7 @@ func TestRunFullyConfigurableUpgradeSolution(t *testing.T) { options.TerraformVars = map[string]interface{}{ "prefix": options.Prefix, "elasticsearch_access_tags": permanentResources["accessTags"], + "kms_encryption_enabled": true, "use_ibm_owned_encryption_key": false, "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], "kms_endpoint_type": "public", @@ -187,6 +189,7 @@ func TestRunSecurityEnforcedSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, {Name: "use_ibm_owned_encryption_key", Value: false, DataType: "bool"}, {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, @@ -330,6 +333,7 @@ func TestPlanValidation(t *testing.T) { // Test the DA when using Elser model var fullyConfigurableSolutionWithElserModelVars = map[string]interface{}{ + "kms_encryption_enabled": true, "use_ibm_owned_encryption_key": false, "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], "enable_elser_model": true, @@ -339,6 +343,7 @@ func TestPlanValidation(t *testing.T) { // Test the DA when using Kibana dashboard and existing KMS instance var fullyConfigurableSolutionWithKibanaDashboardVars = map[string]interface{}{ "enable_kibana_dashboard": true, + "kms_encryption_enabled": true, "use_ibm_owned_encryption_key": false, "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], "plan": "enterprise", From f2100980229d2ab2191f51969b2f9b15fbd2c561 Mon Sep 17 00:00:00 2001 From: whoffler Date: Thu, 8 May 2025 08:38:42 +0100 Subject: [PATCH 06/22] update required variables in ibmcatalog --- ibm_catalog.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index 3c33165b..06883f2b 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -324,8 +324,7 @@ "key": "use_ibm_owned_encryption_key" }, { - "key": "existing_kms_instance_crn", - "required": true + "key": "existing_kms_instance_crn" }, { "key": "existing_kms_key_crn" @@ -624,8 +623,7 @@ "key": "ibmcloud_kms_api_key" }, { - "key": "existing_kms_instance_crn", - "required": true + "key": "existing_kms_instance_crn" }, { "key": "existing_kms_key_crn" From f4bf8fdbf441795e6705f7fb2ff060347e730b7e Mon Sep 17 00:00:00 2001 From: whoffler Date: Thu, 8 May 2025 11:08:35 +0100 Subject: [PATCH 07/22] updated prefix, added empty provider.tf --- solutions/fully-configurable/main.tf | 15 ++++++++------- solutions/security-enforced/provider.tf | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 solutions/security-enforced/provider.tf diff --git a/solutions/fully-configurable/main.tf b/solutions/fully-configurable/main.tf index 4ff37f22..3a1bba63 100644 --- a/solutions/fully-configurable/main.tf +++ b/solutions/fully-configurable/main.tf @@ -13,9 +13,10 @@ module "resource_group" { ####################################################################################################################### locals { + prefix = (var.prefix != null && trimspace(var.prefix) != "" ? "${var.prefix}-" : "") create_new_kms_key = var.existing_elasticsearch_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? 1 : 0 # no need to create any KMS resources if encryption not enabled, using existing Elasticsearch, passing an existing key, or using IBM owned keys - elasticsearch_key_name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.elasticsearch_key_name}" : var.elasticsearch_key_name - elasticsearch_key_ring_name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.elasticsearch_key_ring_name}" : var.elasticsearch_key_ring_name + elasticsearch_key_name = "${local.prefix}${var.elasticsearch_key_name}" + elasticsearch_key_ring_name = "${local.prefix}${var.elasticsearch_key_ring_name}" } @@ -271,7 +272,7 @@ module "elasticsearch" { source = "../.." depends_on = [time_sleep.wait_for_authorization_policy, time_sleep.wait_for_backup_kms_authorization_policy] resource_group_id = module.resource_group.resource_group_id - name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.elasticsearch_name}" : var.elasticsearch_name + name = "${local.prefix}${var.elasticsearch_name}" region = var.region plan = var.plan skip_iam_authorization_policy = var.skip_es_kms_auth_policy @@ -371,10 +372,10 @@ locals { # Build the structure of the arbitrary credential type secret for admin password admin_pass_secret = [{ - secret_group_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secrets_manager_secret_group != null ? "${var.prefix}-${var.admin_pass_secrets_manager_secret_group}" : var.admin_pass_secrets_manager_secret_group + secret_group_name = "${local.prefix}${var.admin_pass_secrets_manager_secret_group}" existing_secret_group = var.use_existing_admin_pass_secrets_manager_secret_group secrets = [{ - secret_name = (var.prefix != null && var.prefix != "") && var.admin_pass_secrets_manager_secret_name != null ? "${var.prefix}-${var.admin_pass_secrets_manager_secret_name}" : var.admin_pass_secrets_manager_secret_name + secret_name = "${local.prefix}${var.admin_pass_secrets_manager_secret_name}" secret_type = "arbitrary" secret_payload_password = local.admin_pass } @@ -406,8 +407,8 @@ module "secrets_manager_service_credentials" { locals { code_engine_project_id = var.existing_code_engine_project_id != null ? var.existing_code_engine_project_id : null - code_engine_project_name = local.code_engine_project_id != null ? null : (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.kibana_code_engine_new_project_name}" : var.kibana_code_engine_new_project_name - code_engine_app_name = (var.prefix != null && var.prefix != "") ? "${var.prefix}-${var.kibana_code_engine_new_app_name}" : var.kibana_code_engine_new_app_name + code_engine_project_name = local.code_engine_project_id != null ? null : "${local.prefix}${var.kibana_code_engine_new_project_name}" + code_engine_app_name = "${local.prefix}${var.kibana_code_engine_new_app_name}" kibana_version = var.enable_kibana_dashboard ? jsondecode(data.http.es_metadata[0].response_body).version.number : null } diff --git a/solutions/security-enforced/provider.tf b/solutions/security-enforced/provider.tf new file mode 100644 index 00000000..4c6add22 --- /dev/null +++ b/solutions/security-enforced/provider.tf @@ -0,0 +1 @@ +# Explicit provider config not required here as provider config in fully-configurable is used From d3510e1d4b54f6d0de0dc717bb55a7545afa1cca Mon Sep 17 00:00:00 2001 From: whoffler Date: Thu, 8 May 2025 13:02:07 +0100 Subject: [PATCH 08/22] remove 'use_default_backup_encryption_key' from sec-enf, update validation --- ibm_catalog.json | 3 --- solutions/fully-configurable/variables.tf | 11 +++++++++-- solutions/security-enforced/main.tf | 2 +- solutions/security-enforced/variables.tf | 6 ------ 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index 06883f2b..3480ebe0 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -631,9 +631,6 @@ { "key": "existing_backup_kms_key_crn" }, - { - "key": "use_default_backup_encryption_key" - }, { "key": "elasticsearch_key_ring_name" }, diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 81ebfcc0..18690590 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -244,8 +244,15 @@ variable "kms_encryption_enabled" { default = false validation { - condition = var.kms_encryption_enabled ? var.existing_kms_instance_crn != null || var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null : true - error_message = "When variable `kms_encryption_enabled` is true and KMS encryption is enabled, you must provide either an existing KMS instance with variable `existing_kms_instance_crn` or an existing KMS key using variable `existing_kms_key_crn` or `existing_backup_kms_key_crn`" + condition = ( + var.existing_elasticsearch_instance_crn != null || + (var.kms_encryption_enabled && ( + var.existing_kms_instance_crn != null || + var.existing_kms_key_crn != null || + var.existing_backup_kms_key_crn != null + )) + ) + error_message = "When setting values for 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn', the 'kms_encryption_enabled' input must be set to true." } } diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf index 2011484c..cfd608f1 100644 --- a/solutions/security-enforced/main.tf +++ b/solutions/security-enforced/main.tf @@ -31,7 +31,7 @@ module "elasticsearch" { existing_kms_instance_crn = var.existing_kms_instance_crn existing_kms_key_crn = var.existing_kms_key_crn existing_backup_kms_key_crn = var.existing_backup_kms_key_crn - use_default_backup_encryption_key = var.use_default_backup_encryption_key + use_default_backup_encryption_key = false kms_endpoint_type = "private" skip_es_kms_auth_policy = var.skip_es_kms_auth_policy elasticsearch_key_ring_name = var.elasticsearch_key_ring_name diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index b82ea807..3125ba0a 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -250,12 +250,6 @@ variable "existing_backup_kms_key_crn" { } } -variable "use_default_backup_encryption_key" { - type = bool - description = "When `use_ibm_owned_encryption_key` is set to false, backups will be encrypted with either the key specified in `existing_kms_key_crn`, in `existing_backup_kms_key_crn`, or with a new key that will be created in the instance specified in the `existing_kms_instance_crn` input. If you do not want to use your own key for backups encryption, you can set this to `true` to use the IBM Cloud Databases default encryption for backups. Alternatively set `use_ibm_owned_encryption_key` to true to use the default encryption for both backups and deployment data." - default = false -} - variable "skip_es_kms_auth_policy" { type = bool description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true." From 29b07dfb7bdd6fdb1a283debd3d1185465c7cfa5 Mon Sep 17 00:00:00 2001 From: whoffler Date: Mon, 12 May 2025 09:03:23 +0100 Subject: [PATCH 09/22] SKIP UPGRADE TEST update catalog validation values --- .../fully-configurable/catalogValidationValues.json.template | 2 ++ solutions/security-enforced/variables.tf | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template index b6b32f18..77c7aedb 100644 --- a/solutions/fully-configurable/catalogValidationValues.json.template +++ b/solutions/fully-configurable/catalogValidationValues.json.template @@ -4,5 +4,7 @@ "elasticsearch_tags": $TAGS, "elasticsearch_name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", + "kms_encryption_enabled": true, + "use_ibm_owned_encryption_key": false, "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN } diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index 3125ba0a..e1d595ae 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -221,11 +221,6 @@ variable "existing_kms_instance_crn" { ) error_message = "To enable KMS encryption one of 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn' must be set." } - - validation { - condition = var.existing_kms_instance_crn == null ? var.existing_kms_key_crn != null : true - error_message = "When using an existing elasticsearch instance 'existing_kms_instance_crn' should not be set" - } } variable "existing_kms_key_crn" { From 31c356eb50680f22e6a4277ae3497ec978bcfbb3 Mon Sep 17 00:00:00 2001 From: whoffler Date: Mon, 12 May 2025 11:48:48 +0100 Subject: [PATCH 10/22] SKIP UPGRADE TEST fix validation --- solutions/fully-configurable/variables.tf | 21 ++++++++++++--------- tests/pr_test.go | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 18690590..9ff8ac73 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -244,15 +244,18 @@ variable "kms_encryption_enabled" { default = false validation { - condition = ( - var.existing_elasticsearch_instance_crn != null || - (var.kms_encryption_enabled && ( - var.existing_kms_instance_crn != null || - var.existing_kms_key_crn != null || - var.existing_backup_kms_key_crn != null - )) - ) - error_message = "When setting values for 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn', the 'kms_encryption_enabled' input must be set to true." + condition = var.existing_elasticsearch_instance_crn != null ? var.kms_encryption_enabled == false : true + error_message = "When using an existing elasticsearch instance 'kms_encryption_enabled' should not be enabled" + } + + validation { + condition = var.kms_encryption_enabled == true ? (var.existing_kms_instance_crn != null || var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null) : true + error_message = "You must provide at least one of 'existing_kms_instance_crn', 'existing_kms_root_key_crn' or 'existing_backup_kms_key_crn' inputs if 'kms_encryption_enabled' is set to true." + } + + validation { + condition = var.kms_encryption_enabled == false ? (var.existing_kms_key_crn == null && var.existing_kms_instance_crn == null && var.existing_backup_kms_key_crn == null) : true + error_message = "If 'kms_encryption_enabled' is set to false, you should not pass values for 'existing_kms_instance_crn', 'existing_kms_root_key_crn' or 'existing_backup_kms_key_crn'. inputs" } } diff --git a/tests/pr_test.go b/tests/pr_test.go index 91bf56b8..6e194b09 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -71,7 +71,7 @@ func TestRunFullyConfigurableSolutionSchematics(t *testing.T) { }, TemplateFolder: fullyConfigurableSolutionTerraformDir, BestRegionYAMLPath: regionSelectionPath, - Prefix: "els-sr-da", + Prefix: "els-fc-da", ResourceGroup: resourceGroup, DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 60, @@ -165,7 +165,7 @@ func TestRunSecurityEnforcedSolutionSchematics(t *testing.T) { }, TemplateFolder: securityEnforcedSolutionTerraformDir, BestRegionYAMLPath: regionSelectionPath, - Prefix: "els-sr-da", + Prefix: "els-se-da", ResourceGroup: resourceGroup, DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 60, From ebf08eade52b6129786988204933dfa196473cdb Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 20 Jun 2025 11:25:27 +0100 Subject: [PATCH 11/22] SKIP UPGRADE TEST updated to use redis as template --- .catalog-onboard-pipeline.yaml | 2 + .secrets.baseline | 4 +- README.md | 1 + common-dev-assets | 2 +- examples/backup-restore/version.tf | 2 +- examples/basic/variables.tf | 1 + examples/basic/version.tf | 2 +- examples/complete/version.tf | 2 +- examples/fscloud/version.tf | 2 +- ibm_catalog.json | 50 ++-- main.tf | 21 +- solutions/fully-configurable/README.md | 19 +- .../catalogValidationValues.json.template | 2 +- solutions/fully-configurable/main.tf | 42 ++-- solutions/fully-configurable/provider.tf | 16 +- solutions/fully-configurable/variables.tf | 238 ++++++++---------- solutions/security-enforced/README.md | 15 -- .../catalogValidationValues.json.template | 2 +- solutions/security-enforced/main.tf | 52 ++-- solutions/security-enforced/outputs.tf | 10 +- solutions/security-enforced/variables.tf | 201 +++++++-------- solutions/security-enforced/version.tf | 4 +- tests/pr_test.go | 8 +- variables.tf | 6 + 24 files changed, 331 insertions(+), 373 deletions(-) diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml index fc5dd94b..7cb4fa35 100644 --- a/.catalog-onboard-pipeline.yaml +++ b/.catalog-onboard-pipeline.yaml @@ -12,9 +12,11 @@ offerings: scc: instance_id: 1c7d5f78-9262-44c3-b779-b28fe4d88c37 region: us-south + scope_resource_group_var_name: existing_resource_group_name - name: security-enforced mark_ready: true install_type: fullstack scc: instance_id: 1c7d5f78-9262-44c3-b779-b28fe4d88c37 region: us-south + scope_resource_group_var_name: existing_resource_group_name diff --git a/.secrets.baseline b/.secrets.baseline index 8d2e3a02..80904806 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-05-02T13:16:14Z", + "generated_at": "2025-06-20T10:01:18Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -110,7 +110,7 @@ "hashed_secret": "8c7c51db5075ebd0369c51e9f14737d9b4c1c21d", "is_secret": false, "is_verified": false, - "line_number": 361, + "line_number": 357, "type": "Base64 High Entropy String", "verified_result": null } diff --git a/README.md b/README.md index bb2b53cc..40ffbfee 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ You need the following permissions to run this module. | [elasticsearch\_version](#input\_elasticsearch\_version) | The version of Databases for Elasticsearch to deploy. Possible values: `8.7`, `8.10`, `8.12`, `8.15` which requires an Enterprise Platinum pricing plan. If no value is specified, the current preferred version for IBM Cloud Databases is used. | `string` | `null` | no | | [elser\_model\_type](#input\_elser\_model\_type) | Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. Applies only if also 'plan' is set to 'platinum'. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html) | `string` | `".elser_model_2_linux-x86_64"` | no | | [enable\_elser\_model](#input\_enable\_elser\_model) | Set it to true to install and start the Elastic's Natural Language Processing model. Applies only if also 'plan' is set to 'platinum'. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch) | `bool` | `false` | no | +| [kms\_encryption\_enabled](#input\_kms\_encryption\_enabled) | Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing\_kms\_instance\_crn', 'existing\_kms\_key\_crn' or 'existing\_backup\_kms\_key\_crn'. | `bool` | `false` | no | | [kms\_key\_crn](#input\_kms\_key\_crn) | The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the `use_same_kms_key_for_backups` and `backup_encryption_key_crn` inputs. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no | | [member\_cpu\_count](#input\_member\_cpu\_count) | The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling). | `number` | `0` | no | | [member\_disk\_mb](#input\_member\_disk\_mb) | The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling). | `number` | `5120` | no | diff --git a/common-dev-assets b/common-dev-assets index d0c2b2a1..b76eee7e 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit d0c2b2a1d3cdf41f6a844bc17816199fe3f8b20f +Subproject commit b76eee7ec33d5b81b30828e37a02d2df595e0909 diff --git a/examples/backup-restore/version.tf b/examples/backup-restore/version.tf index 6f39952e..170ae1a4 100644 --- a/examples/backup-restore/version.tf +++ b/examples/backup-restore/version.tf @@ -5,7 +5,7 @@ terraform { # module's version.tf (basic example), and 1 example that will always use the latest provider version (complete example). ibm = { source = "IBM-Cloud/ibm" - version = ">=1.70.0, <2.0.0" + version = ">=1.70.2, <2.0.0" } } } diff --git a/examples/basic/variables.tf b/examples/basic/variables.tf index 18b25c7e..3f0e4007 100644 --- a/examples/basic/variables.tf +++ b/examples/basic/variables.tf @@ -50,6 +50,7 @@ variable "service_endpoints" { error_message = "Valid values for service_endpoints are 'public', 'public-and-private', and 'private'" } } + variable "member_host_flavor" { type = string description = "The host flavor per member. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor)." diff --git a/examples/basic/version.tf b/examples/basic/version.tf index 509f9700..5677e7b1 100644 --- a/examples/basic/version.tf +++ b/examples/basic/version.tf @@ -4,7 +4,7 @@ terraform { # Pin to the lowest provider version of the range defined in the main module's version.tf to ensure lowest version still works ibm = { source = "IBM-Cloud/ibm" - version = "1.70.0" + version = "1.79.2" } # The elasticsearch provider is not actually required by the module itself, just this example, so OK to use ">=" here instead of locking into a version elasticsearch = { diff --git a/examples/complete/version.tf b/examples/complete/version.tf index c07b9389..3f0c1bab 100644 --- a/examples/complete/version.tf +++ b/examples/complete/version.tf @@ -4,7 +4,7 @@ terraform { required_providers { ibm = { source = "IBM-Cloud/ibm" - version = ">=1.70.0, <2.0.0" + version = ">=1.79.2, <2.0.0" } } } diff --git a/examples/fscloud/version.tf b/examples/fscloud/version.tf index cdc76d38..03d8bdf3 100644 --- a/examples/fscloud/version.tf +++ b/examples/fscloud/version.tf @@ -4,7 +4,7 @@ terraform { # Use latest version of provider in non-basic examples to verify latest version works with module ibm = { source = "IBM-Cloud/ibm" - version = ">= 1.70.0" + version = ">= 1.79.2" } } } diff --git a/ibm_catalog.json b/ibm_catalog.json index 3480ebe0..8f307aa0 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -33,20 +33,20 @@ "description": "Creates and configures an IBM Cloud Databases for Elasticsearch instance." }, { - "title": "Supports KMS encryption", - "description": "Provides KMS encryption for the data that you store in the database." + "title": "KMS encryption", + "description": "Provides [KMS encryption](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-key-protect&interface=ui) for the data that you store in the database, enhancing data security." }, { - "title": "Supports autoscaling", - "description": "Provides the autoscaling to allow the database to increase resources in response to usage." + "title": "Autoscaling", + "description": "Provides the [autoscaling](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-autoscaling&interface=ui) to allow the database to increase resources in response to usage." }, { - "title": "Attaches access tags", + "title": "Access tags", "description": "Attaches access tags to the Elasticsearch instance." }, { - "title": "Supports backup restoration", - "description": "Provides database restoration using a backup created by a deployment with the same service ID." + "title": "Backup restoration", + "description": "Provides [database restoration](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-dashboard-backups&interface=ui) using a backup created by a deployment with the same service ID." } ], "flavors": [ @@ -65,11 +65,31 @@ ] }, "iam_permissions": [ + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Administrator" + ], + "service_name": "all-account-management-services" + }, { "role_crns": [ "crn:v1:bluemix:public:iam::::role:Editor" ], "service_name": "databases-for-elasticsearch" + }, + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "service_name": "kms", + "notes": "[Optional] Editor access is required to create keys. It is required only if KMS encryption is enabled." + }, + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "service_name": "hs-crypto", + "notes": "[Optional] Editor access is required to create keys in HPCS. It is required only if KMS encryption is enabled." } ], "architecture": { @@ -238,7 +258,7 @@ ] }, { - "key": "elasticsearch_tags" + "key": "elasticsearch_resource_tags" }, { "key": "elasticsearch_access_tags" @@ -336,13 +356,13 @@ "key": "use_default_backup_encryption_key" }, { - "key": "elasticsearch_key_ring_name" + "key": "key_ring_name" }, { - "key": "elasticsearch_key_name" + "key": "key_name" }, { - "key": "skip_es_kms_auth_policy" + "key": "skip_elasticsearch_kms_auth_policy" }, { "key": "elasticsearch_backup_crn" @@ -569,7 +589,7 @@ ] }, { - "key": "elasticsearch_tags" + "key": "elasticsearch_resource_tags" }, { "key": "elasticsearch_access_tags" @@ -632,13 +652,13 @@ "key": "existing_backup_kms_key_crn" }, { - "key": "elasticsearch_key_ring_name" + "key": "key_ring_name" }, { - "key": "elasticsearch_key_name" + "key": "key_name" }, { - "key": "skip_es_kms_auth_policy" + "key": "skip_elasticsearch_kms_auth_policy" }, { "key": "elasticsearch_backup_crn" diff --git a/main.tf b/main.tf index 6a870a48..8d0e26ba 100644 --- a/main.tf +++ b/main.tf @@ -1,10 +1,3 @@ -######################################################################################################################## -# Input variable validation -# (approach based on https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400) -# -# TODO: Replace with terraform cross variable validation: https://github.ibm.com/GoldenEye/issues/issues/10836 -######################################################################################################################## - ######################################################################################################################## # Locals ######################################################################################################################## @@ -12,7 +5,7 @@ locals { # If 'use_ibm_owned_encryption_key' is true or 'use_default_backup_encryption_key' is true, default to null. # If no value is passed for 'backup_encryption_key_crn', then default to use 'kms_key_crn'. - backup_encryption_key_crn = var.use_ibm_owned_encryption_key || var.use_default_backup_encryption_key ? null : (var.backup_encryption_key_crn != null ? var.backup_encryption_key_crn : var.kms_key_crn) + backup_encryption_key_crn = !var.kms_encryption_enabled || var.use_ibm_owned_encryption_key || var.use_default_backup_encryption_key ? null : (var.backup_encryption_key_crn != null ? var.backup_encryption_key_crn : var.kms_key_crn) # Determine if auto scaling is enabled auto_scaling_enabled = var.auto_scaling == null ? [] : [1] @@ -27,8 +20,8 @@ locals { ######################################################################################################################## locals { - parse_kms_key = !var.use_ibm_owned_encryption_key - parse_backup_kms_key = !var.use_ibm_owned_encryption_key && !var.use_default_backup_encryption_key + parse_kms_key = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key + parse_backup_kms_key = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key && !var.use_default_backup_encryption_key } module "kms_key_crn_parser" { @@ -62,10 +55,10 @@ locals { ######################################################################################################################## locals { - # only create auth policy if 'use_ibm_owned_encryption_key' is false, and 'skip_iam_authorization_policy' is false - create_kms_auth_policy = !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy ? 1 : 0 - # only create backup auth policy if 'use_ibm_owned_encryption_key' is false, 'skip_iam_authorization_policy' is false and 'use_same_kms_key_for_backups' is false - create_backup_kms_auth_policy = !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy && !var.use_same_kms_key_for_backups ? 1 : 0 + # only create auth policy if kms_encryption_enabled' is enabled, 'use_ibm_owned_encryption_key' is false, and 'skip_iam_authorization_policy' is false + create_kms_auth_policy = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy ? 1 : 0 + # only create backup auth policy if kms_encryption_enabled' is enabled, 'use_ibm_owned_encryption_key' is false, 'skip_iam_authorization_policy' is false and 'use_same_kms_key_for_backups' is false + create_backup_kms_auth_policy = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy && !var.use_same_kms_key_for_backups ? 1 : 0 } resource "ibm_iam_authorization_policy" "policy" { diff --git a/solutions/fully-configurable/README.md b/solutions/fully-configurable/README.md index 90a35ed7..f099860c 100644 --- a/solutions/fully-configurable/README.md +++ b/solutions/fully-configurable/README.md @@ -1,20 +1,3 @@ -# IBM Cloud Databases for Elasticsearch (Fully Configurable) - -## Prerequisites -- An existing resource group - -This architecture creates an instance of IBM Cloud Databases for Elasticsearch and supports provisioning of the following resources: - -- A KMS root key, if one is not passed in. -- An IBM Cloud Databases for Elasticsearch instance with KMS encryption. -- Autoscaling rules for the database instance, if provided. -- Install and start the Elastic's Natural Language Processing model, if enabled. -- Kibana dashboard for Elasticsearch, if enabled. - -**Note on accessing Kibana:** If Kibana is enabled, you can access the Kibana application over a IBM private network using the method outlined [here](https://cloud.ibm.com/docs/codeengine?topic=codeengine-vpe). - -**Note on setting kibana_visibility:** When the Kibana application visibility is changed from private to public using kibana_visibility variable, it will become accessible from the public Internet. However, access via the IBM Cloud private network will no longer be available. This change takes effect immediately, potentially impacting active users or integrations. It is important to consider the associated security implications before proceeding. - -![fscloud-elastic-search](../../reference-architecture/deployable-architecture-elasticsearch.svg) +# Cloud automation for Elasticsearch (Fully Configurable) :exclamation: **Important:** This solution is not intended to be called by other modules because it contains a provider configuration and is not compatible with the `for_each`, `count`, and `depends_on` arguments. For more information, see [Providers Within Modules](https://developer.hashicorp.com/terraform/language/modules/develop/providers). diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template index 77c7aedb..a859fea0 100644 --- a/solutions/fully-configurable/catalogValidationValues.json.template +++ b/solutions/fully-configurable/catalogValidationValues.json.template @@ -1,7 +1,7 @@ { "ibmcloud_api_key": $VALIDATION_APIKEY, "region": "us-south", - "elasticsearch_tags": $TAGS, + "elasticsearch_resource_tags": $TAGS, "elasticsearch_name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", "kms_encryption_enabled": true, diff --git a/solutions/fully-configurable/main.tf b/solutions/fully-configurable/main.tf index 3a1bba63..5085f36f 100644 --- a/solutions/fully-configurable/main.tf +++ b/solutions/fully-configurable/main.tf @@ -13,10 +13,15 @@ module "resource_group" { ####################################################################################################################### locals { - prefix = (var.prefix != null && trimspace(var.prefix) != "" ? "${var.prefix}-" : "") - create_new_kms_key = var.existing_elasticsearch_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? 1 : 0 # no need to create any KMS resources if encryption not enabled, using existing Elasticsearch, passing an existing key, or using IBM owned keys - elasticsearch_key_name = "${local.prefix}${var.elasticsearch_key_name}" - elasticsearch_key_ring_name = "${local.prefix}${var.elasticsearch_key_ring_name}" + prefix = (var.prefix != null && trimspace(var.prefix) != "" ? "${var.prefix}-" : "") + create_new_kms_key = ( + var.kms_encryption_enabled && + var.existing_elasticsearch_instance_crn == null && + !var.use_ibm_owned_encryption_key && + var.existing_kms_key_crn == null + ) + elasticsearch_key_name = "${local.prefix}${var.key_name}" + elasticsearch_key_ring_name = "${local.prefix}${var.key_ring_name}" } @@ -24,7 +29,7 @@ module "kms" { providers = { ibm = ibm.kms } - count = local.create_new_kms_key + count = local.create_new_kms_key ? 1 : 0 source = "terraform-ibm-modules/kms-all-inclusive/ibm" version = "5.1.7" create_key_protect_instance = false @@ -42,7 +47,7 @@ module "kms" { standard_key = false rotation_interval_month = 3 dual_auth_delete_enabled = false - force_delete = true + force_delete = true # Force delete must be set to true, or the terraform destroy will fail since the service does not de-register itself from the key until the reclamation period has expired. } ] } @@ -86,16 +91,16 @@ data "ibm_iam_account_settings" "iam_account_settings" { locals { account_id = data.ibm_iam_account_settings.iam_account_settings.account_id - create_cross_account_kms_auth_policy = var.existing_elasticsearch_instance_crn == null && !var.skip_es_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key - create_cross_account_backup_kms_auth_policy = var.existing_elasticsearch_instance_crn == null && !var.skip_es_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key && var.existing_backup_kms_key_crn != null + create_cross_account_kms_auth_policy = var.kms_encryption_enabled && !var.skip_elasticsearch_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key + create_cross_account_backup_kms_auth_policy = var.kms_encryption_enabled && !var.skip_elasticsearch_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key && var.existing_backup_kms_key_crn != null # If KMS encryption enabled (and existing ES instance is not being passed), parse details from the existing key if being passed, otherwise get it from the key that the DA creates - kms_account_id = var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : module.kms_instance_crn_parser[0].account_id - kms_service = var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : module.kms_instance_crn_parser[0].service_name - kms_instance_guid = var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_instance : module.kms_instance_crn_parser[0].service_instance - kms_key_crn = var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? var.existing_kms_key_crn : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].crn - kms_key_id = var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].resource : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].key_id - kms_region = var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].region : module.kms_instance_crn_parser[0].region + kms_account_id = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : module.kms_instance_crn_parser[0].account_id + kms_service = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : module.kms_instance_crn_parser[0].service_name + kms_instance_guid = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_instance : module.kms_instance_crn_parser[0].service_instance + kms_key_crn = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? var.existing_kms_key_crn : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].crn + kms_key_id = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].resource : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].key_id + kms_region = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].region : module.kms_instance_crn_parser[0].region # If creating KMS cross account policy for backups, parse backup key details from passed in key CRN backup_kms_account_id = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].account_id : local.kms_account_id @@ -221,7 +226,9 @@ locals { # if - replace first char with J # elseif _ replace first char with K # else use asis - admin_pass = var.admin_pass == null ? (startswith(random_password.admin_password[0].result, "-") ? "J${substr(random_password.admin_password[0].result, 1, -1)}" : startswith(random_password.admin_password[0].result, "_") ? "K${substr(random_password.admin_password[0].result, 1, -1)}" : random_password.admin_password[0].result) : var.admin_pass + generated_admin_password = (length(random_password.admin_password) > 0 ? (startswith(random_password.admin_password[0].result, "-") ? "J${substr(random_password.admin_password[0].result, 1, -1)}" : startswith(random_password.admin_password[0].result, "_") ? "K${substr(random_password.admin_password[0].result, 1, -1)}" : random_password.admin_password[0].result) : null) + # admin password to use + admin_pass = var.admin_pass == null ? local.generated_admin_password : var.admin_pass } ####################################################################################################################### @@ -275,7 +282,7 @@ module "elasticsearch" { name = "${local.prefix}${var.elasticsearch_name}" region = var.region plan = var.plan - skip_iam_authorization_policy = var.skip_es_kms_auth_policy + skip_iam_authorization_policy = var.kms_encryption_enabled ? var.skip_elasticsearch_kms_auth_policy : true elasticsearch_version = var.elasticsearch_version service_endpoints = var.service_endpoints use_ibm_owned_encryption_key = var.use_ibm_owned_encryption_key @@ -284,8 +291,9 @@ module "elasticsearch" { use_same_kms_key_for_backups = local.use_same_kms_key_for_backups use_default_backup_encryption_key = var.use_default_backup_encryption_key backup_crn = var.elasticsearch_backup_crn + kms_encryption_enabled = var.kms_encryption_enabled access_tags = var.elasticsearch_access_tags - tags = var.elasticsearch_tags + tags = var.elasticsearch_resource_tags admin_pass = local.admin_pass users = var.users members = var.members diff --git a/solutions/fully-configurable/provider.tf b/solutions/fully-configurable/provider.tf index 515e60c2..e66dac2c 100644 --- a/solutions/fully-configurable/provider.tf +++ b/solutions/fully-configurable/provider.tf @@ -1,12 +1,14 @@ provider "ibm" { - ibmcloud_api_key = var.ibmcloud_api_key - region = var.region - visibility = var.provider_visibility + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region + visibility = var.provider_visibility + private_endpoint_type = (var.provider_visibility == "private" && var.region == "ca-mon") ? "vpe" : null } provider "ibm" { - alias = "kms" - ibmcloud_api_key = var.ibmcloud_kms_api_key != null ? var.ibmcloud_kms_api_key : var.ibmcloud_api_key - region = local.kms_region - visibility = var.provider_visibility + alias = "kms" + ibmcloud_api_key = var.ibmcloud_kms_api_key != null ? var.ibmcloud_kms_api_key : var.ibmcloud_api_key + region = local.kms_region + visibility = var.provider_visibility + private_endpoint_type = (var.provider_visibility == "private" && var.region == "ca-mon") ? "vpe" : null } diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 9ff8ac73..f64063b6 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -10,22 +10,11 @@ variable "ibmcloud_api_key" { variable "existing_resource_group_name" { type = string - description = "The name of an existing resource group to provision the Databases for Elasticsearch in." + description = "The name of an existing resource group to provision resources in." default = "Default" nullable = false } -variable "provider_visibility" { - description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints)." - type = string - default = "private" - nullable = false - validation { - condition = contains(["public", "private", "public-and-private"], var.provider_visibility) - error_message = "Invalid visibility option. Allowed values are 'public', 'private', or 'public-and-private'." - } -} - variable "prefix" { type = string description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To not use any prefix value, you can set this value to `null` or an empty string." @@ -41,6 +30,17 @@ variable "prefix" { } } +variable "provider_visibility" { + description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints)." + type = string + default = "private" + nullable = false + 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'." + } +} + ############################################################################## # Input Variables ############################################################################## @@ -52,6 +52,23 @@ variable "elasticsearch_name" { nullable = false } +variable "region" { + type = string + description = "The region where you want to deploy your instance, or the region in which your existing instance is in." + default = "us-south" + validation { + condition = var.existing_elasticsearch_instance_crn != null && var.region != local.existing_elasticsearch_region ? false : true + error_message = "The region detected in the 'existing_elasticsearch_instance_crn' value must match the value of the 'region' input variable when passing an existing instance." + } +} + +variable "existing_elasticsearch_instance_crn" { + type = string + default = null + description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." + nullable = true +} + variable "elasticsearch_version" { type = string description = "The version of the Databases for Elasticsearch instance. If no value is specified, the current preferred version of Databases for Elasticsearch is used." @@ -72,16 +89,6 @@ variable "elasticsearch_backup_crn" { } } -variable "region" { - type = string - description = "The region where you want to deploy your instance, or the region in which your existing instance is in." - default = "us-south" - validation { - condition = var.existing_elasticsearch_instance_crn != null && var.region != local.existing_elasticsearch_region ? false : true - error_message = "The region detected in the 'existing_elasticsearch_instance_crn' value must match the value of the 'region' input variable when passing an existing instance." - } -} - variable "plan" { type = string description = "The name of the service plan for your Databases for Elasticsearch instance. Possible values: `enterprise`, `platinum`." @@ -89,24 +96,6 @@ variable "plan" { nullable = false } -variable "service_endpoints" { - type = string - description = "Specify whether you want to enable public, or both public and private service endpoints. Possible values: `public`, `public-and-private`" - default = "private" - nullable = false - validation { - condition = contains(["public", "private"], var.service_endpoints) - error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`" - } -} - -variable "existing_elasticsearch_instance_crn" { - type = string - default = null - description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." - nullable = true -} - variable "enable_elser_model" { type = bool description = "Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch)" @@ -129,6 +118,16 @@ variable "elser_model_type" { # ICD hosting model properties ############################################################################## +variable "service_endpoints" { + type = string + description = "Specify whether you want to enable public, or both public and private service endpoints. Possible values: `public`, `public-and-private`" + default = "private" + nullable = false + validation { + condition = contains(["public", "private"], var.service_endpoints) + error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`" + } +} variable "members" { type = number @@ -136,6 +135,12 @@ variable "members" { default = 3 } +variable "member_memory_mb" { + type = number + description = "The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)" + default = 4096 +} + variable "member_cpu_count" { type = number description = "The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." @@ -160,10 +165,10 @@ variable "member_host_flavor" { } } -variable "member_memory_mb" { - type = number - description = "The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)" - default = 4096 +variable "service_credential_names" { + type = map(string) + description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + default = {} } variable "admin_pass" { @@ -185,15 +190,9 @@ variable "users" { sensitive = true } -variable "service_credential_names" { - type = map(string) - description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." - default = {} -} - -variable "elasticsearch_tags" { +variable "elasticsearch_resource_tags" { type = list(any) - description = "The list of tags to be added to the Databases for Elasticsearch instance." + description = "The list of resource tags to be added to the Databases for Elasticsearch instance." default = [] } @@ -203,37 +202,6 @@ variable "elasticsearch_access_tags" { default = [] } -############################################################## -# Auto Scaling -############################################################## - -variable "auto_scaling" { - type = object({ - disk = object({ - capacity_enabled = optional(bool, false) - free_space_less_than_percent = optional(number, 10) - io_above_percent = optional(number, 90) - io_enabled = optional(bool, false) - io_over_period = optional(string, "15m") - rate_increase_percent = optional(number, 10) - rate_limit_mb_per_member = optional(number, 3670016) - rate_period_seconds = optional(number, 900) - rate_units = optional(string, "mb") - }) - memory = object({ - io_above_percent = optional(number, 90) - io_enabled = optional(bool, false) - io_over_period = optional(string, "15m") - rate_increase_percent = optional(number, 10) - rate_limit_mb_per_member = optional(number, 114688) - rate_period_seconds = optional(number, 900) - rate_units = optional(string, "mb") - }) - }) - description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." - default = null -} - ############################################################## # Encryption ############################################################## @@ -242,21 +210,6 @@ variable "kms_encryption_enabled" { type = bool description = "Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." default = false - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.kms_encryption_enabled == false : true - error_message = "When using an existing elasticsearch instance 'kms_encryption_enabled' should not be enabled" - } - - validation { - condition = var.kms_encryption_enabled == true ? (var.existing_kms_instance_crn != null || var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null) : true - error_message = "You must provide at least one of 'existing_kms_instance_crn', 'existing_kms_root_key_crn' or 'existing_backup_kms_key_crn' inputs if 'kms_encryption_enabled' is set to true." - } - - validation { - condition = var.kms_encryption_enabled == false ? (var.existing_kms_key_crn == null && var.existing_kms_instance_crn == null && var.existing_backup_kms_key_crn == null) : true - error_message = "If 'kms_encryption_enabled' is set to false, you should not pass values for 'existing_kms_instance_crn', 'existing_kms_root_key_crn' or 'existing_backup_kms_key_crn'. inputs" - } } variable "use_ibm_owned_encryption_key" { @@ -323,23 +276,6 @@ variable "existing_kms_key_crn" { } } -variable "existing_backup_kms_key_crn" { - type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." - default = null - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" - } -} - -variable "use_default_backup_encryption_key" { - type = bool - description = "When `use_ibm_owned_encryption_key` is set to false, backups will be encrypted with either the key specified in `existing_kms_key_crn`, in `existing_backup_kms_key_crn`, or with a new key that will be created in the instance specified in the `existing_kms_instance_crn` input. If you do not want to use your own key for backups encryption, you can set this to `true` to use the IBM Cloud Databases default encryption for backups. Alternatively set `use_ibm_owned_encryption_key` to true to use the default encryption for both backups and deployment data." - default = false -} - variable "kms_endpoint_type" { type = string description = "The type of endpoint to use for communicating with the Key Protect or Hyper Protect Crypto Services instance. Possible values: `public`, `private`." @@ -350,24 +286,41 @@ variable "kms_endpoint_type" { } } -variable "skip_es_kms_auth_policy" { +variable "skip_elasticsearch_kms_auth_policy" { type = bool description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true." default = false } -variable "elasticsearch_key_ring_name" { +variable "key_ring_name" { type = string default = "elasticsearch-key-ring" description = "The name for the key ring created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } -variable "elasticsearch_key_name" { +variable "key_name" { type = string default = "elasticsearch-key" description = "The name for the key created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } +variable "existing_backup_kms_key_crn" { + type = string + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" + } +} + +variable "use_default_backup_encryption_key" { + type = bool + description = "When `use_ibm_owned_encryption_key` is set to false, backups will be encrypted with either the key specified in `existing_kms_key_crn`, in `existing_backup_kms_key_crn`, or with a new key that will be created in the instance specified in the `existing_kms_instance_crn` input. If you do not want to use your own key for backups encryption, you can set this to `true` to use the IBM Cloud Databases default encryption for backups. Alternatively set `use_ibm_owned_encryption_key` to true to use the default encryption for both backups and deployment data." + default = false +} + variable "ibmcloud_kms_api_key" { type = string description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Elastic Search instance. Leave this input empty if the same account owns both instances." @@ -375,24 +328,47 @@ variable "ibmcloud_kms_api_key" { default = null } -############################################################################## -## Secrets Manager Service Credentials -############################################################################## + +############################################################## +# Auto Scaling +############################################################## + +variable "auto_scaling" { + type = object({ + disk = object({ + capacity_enabled = optional(bool, false) + free_space_less_than_percent = optional(number, 10) + io_above_percent = optional(number, 90) + io_enabled = optional(bool, false) + io_over_period = optional(string, "15m") + rate_increase_percent = optional(number, 10) + rate_limit_mb_per_member = optional(number, 3670016) + rate_period_seconds = optional(number, 900) + rate_units = optional(string, "mb") + }) + memory = object({ + io_above_percent = optional(number, 90) + io_enabled = optional(bool, false) + io_over_period = optional(string, "15m") + rate_increase_percent = optional(number, 10) + rate_limit_mb_per_member = optional(number, 114688) + rate_period_seconds = optional(number, 900) + rate_units = optional(string, "mb") + }) + }) + description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + default = null +} + + +############################################################################# +# Secrets Manager Service Credentials +############################################################################# variable "existing_secrets_manager_instance_crn" { type = string default = null description = "The CRN of existing secrets manager to use to create service credential secrets for Databases for Elasticsearch instance." - - validation { - condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_group != null : true - error_message = "`admin_pass_secrets_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set." - } - - validation { - condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_name != null : true - error_message = "`admin_pass_secrets_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set." - } } variable "existing_secrets_manager_endpoint_type" { diff --git a/solutions/security-enforced/README.md b/solutions/security-enforced/README.md index 49071c03..ed731ec7 100644 --- a/solutions/security-enforced/README.md +++ b/solutions/security-enforced/README.md @@ -1,18 +1,3 @@ # IBM Cloud Databases for Elasticsearch (Security Enforced) -## Prerequisites -- An existing resource group - -This architecture creates an instance of IBM Cloud Databases for Elasticsearch and supports provisioning of the following resources: - -- A KMS root key, if one is not passed in. -- An IBM Cloud Databases for Elasticsearch instance with KMS encryption. -- Autoscaling rules for the database instance, if provided. -- Install and start the Elastic's Natural Language Processing model, if enabled. -- Kibana dashboard for Elasticsearch, if enabled. - -**Note on accessing Kibana:** If Kibana is enabled, you can access the Kibana application over a IBM private network using the method outlined [here](https://cloud.ibm.com/docs/codeengine?topic=codeengine-vpe). - -![fscloud-elastic-search](../../reference-architecture/deployable-architecture-elasticsearch.svg) - :exclamation: **Important:** This solution is not intended to be called by other modules because it contains a provider configuration and is not compatible with the `for_each`, `count`, and `depends_on` arguments. For more information, see [Providers Within Modules](https://developer.hashicorp.com/terraform/language/modules/develop/providers). diff --git a/solutions/security-enforced/catalogValidationValues.json.template b/solutions/security-enforced/catalogValidationValues.json.template index b6b32f18..c40cc403 100644 --- a/solutions/security-enforced/catalogValidationValues.json.template +++ b/solutions/security-enforced/catalogValidationValues.json.template @@ -1,7 +1,7 @@ { "ibmcloud_api_key": $VALIDATION_APIKEY, "region": "us-south", - "elasticsearch_tags": $TAGS, + "elasticsearch_resource_tags": $TAGS, "elasticsearch_name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf index cfd608f1..fe18eaa2 100644 --- a/solutions/security-enforced/main.tf +++ b/solutions/security-enforced/main.tf @@ -2,43 +2,42 @@ module "elasticsearch" { source = "../fully-configurable" ibmcloud_api_key = var.ibmcloud_api_key existing_resource_group_name = var.existing_resource_group_name - provider_visibility = "private" prefix = var.prefix elasticsearch_name = var.elasticsearch_name + provider_visibility = "private" + region = var.region + existing_elasticsearch_instance_crn = var.existing_elasticsearch_instance_crn elasticsearch_version = var.elasticsearch_version elasticsearch_backup_crn = var.elasticsearch_backup_crn - region = var.region plan = var.plan - existing_elasticsearch_instance_crn = var.existing_elasticsearch_instance_crn enable_elser_model = var.enable_elser_model elser_model_type = var.elser_model_type # ICD hosting model properties - members = var.members - member_cpu_count = var.member_cpu_count - member_disk_mb = var.member_disk_mb - member_host_flavor = var.member_host_flavor - member_memory_mb = var.member_memory_mb - admin_pass = var.admin_pass - users = var.users - service_credential_names = var.service_credential_names - elasticsearch_tags = var.elasticsearch_tags - elasticsearch_access_tags = var.elasticsearch_access_tags + members = var.members + member_memory_mb = var.member_memory_mb + member_cpu_count = var.member_cpu_count + member_disk_mb = var.member_disk_mb + member_host_flavor = var.member_host_flavor + service_credential_names = var.service_credential_names + admin_pass = var.admin_pass + users = var.users + elasticsearch_resource_tags = var.elasticsearch_resource_tags + elasticsearch_access_tags = var.elasticsearch_access_tags + # Encryption + kms_encryption_enabled = true + use_ibm_owned_encryption_key = false + existing_kms_instance_crn = var.existing_kms_instance_crn + existing_kms_key_crn = var.existing_kms_key_crn + kms_endpoint_type = "private" + skip_elasticsearch_kms_auth_policy = var.skip_elasticsearch_kms_auth_policy + ibmcloud_kms_api_key = var.ibmcloud_kms_api_key + key_ring_name = var.key_ring_name + key_name = var.key_name + existing_backup_kms_key_crn = var.existing_backup_kms_key_crn + use_default_backup_encryption_key = false # Auto Scaling auto_scaling = var.auto_scaling - # Encryption - kms_encryption_enabled = true - use_ibm_owned_encryption_key = false - existing_kms_instance_crn = var.existing_kms_instance_crn - existing_kms_key_crn = var.existing_kms_key_crn - existing_backup_kms_key_crn = var.existing_backup_kms_key_crn - use_default_backup_encryption_key = false - kms_endpoint_type = "private" - skip_es_kms_auth_policy = var.skip_es_kms_auth_policy - elasticsearch_key_ring_name = var.elasticsearch_key_ring_name - elasticsearch_key_name = var.elasticsearch_key_name - ibmcloud_kms_api_key = var.ibmcloud_kms_api_key # Secrets Manager Service Credentials - service_endpoints = "private" existing_secrets_manager_instance_crn = var.existing_secrets_manager_instance_crn existing_secrets_manager_endpoint_type = "private" service_credential_secrets = var.service_credential_secrets @@ -46,6 +45,7 @@ module "elasticsearch" { admin_pass_secrets_manager_secret_group = var.admin_pass_secrets_manager_secret_group use_existing_admin_pass_secrets_manager_secret_group = var.use_existing_admin_pass_secrets_manager_secret_group admin_pass_secrets_manager_secret_name = var.admin_pass_secrets_manager_secret_name + service_endpoints = "private" # Kibana Configuration kibana_code_engine_new_project_name = var.kibana_code_engine_new_project_name kibana_code_engine_new_app_name = var.kibana_code_engine_new_app_name diff --git a/solutions/security-enforced/outputs.tf b/solutions/security-enforced/outputs.tf index 7c64dc70..81cbfeb2 100644 --- a/solutions/security-enforced/outputs.tf +++ b/solutions/security-enforced/outputs.tf @@ -7,16 +7,16 @@ output "id" { value = module.elasticsearch.id } -output "guid" { - description = "Elasticsearch instance guid" - value = module.elasticsearch.guid -} - output "version" { description = "Elasticsearch instance version" value = module.elasticsearch.version } +output "guid" { + description = "Elasticsearch instance guid" + value = module.elasticsearch.guid +} + output "crn" { description = "Elasticsearch instance crn" value = module.elasticsearch.crn diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index e1d595ae..deed7328 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -10,7 +10,7 @@ variable "ibmcloud_api_key" { variable "existing_resource_group_name" { type = string - description = "The name of an existing resource group to provision the Databases for Elasticsearch in." + description = "The name of an existing resource group to provision resources in." default = "Default" nullable = false } @@ -30,10 +30,6 @@ variable "prefix" { } } -############################################################################## -# Input Variables -############################################################################## - variable "elasticsearch_name" { type = string description = "The name of the Databases for Elasticsearch instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format." @@ -41,6 +37,20 @@ variable "elasticsearch_name" { nullable = false } +variable "region" { + type = string + description = "The region where you want to deploy your instance, or the region in which your existing instance is in." + default = "us-south" + nullable = false +} + +variable "existing_elasticsearch_instance_crn" { + type = string + default = null + description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." + nullable = true +} + variable "elasticsearch_version" { type = string description = "The version of the Databases for Elasticsearch instance. If no value is specified, the current preferred version of Databases for Elasticsearch is used." @@ -53,13 +63,6 @@ variable "elasticsearch_backup_crn" { default = null } -variable "region" { - type = string - description = "The region where you want to deploy your instance, or the region in which your existing instance is in." - default = "us-south" - nullable = false -} - variable "plan" { type = string description = "The name of the service plan for your Databases for Elasticsearch instance. Possible values: `enterprise`, `platinum`." @@ -67,13 +70,6 @@ variable "plan" { nullable = false } -variable "existing_elasticsearch_instance_crn" { - type = string - default = null - description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." - nullable = true -} - variable "enable_elser_model" { type = bool description = "Set it to true to install and start the Elastic's Natural Language Processing model. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch)" @@ -96,13 +92,18 @@ variable "elser_model_type" { # ICD hosting model properties ############################################################################## - variable "members" { type = number description = "The number of members that are allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." default = 3 } +variable "member_memory_mb" { + type = number + description = "The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)" + default = 4096 +} + variable "member_cpu_count" { type = number description = "The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." @@ -127,10 +128,10 @@ variable "member_host_flavor" { } } -variable "member_memory_mb" { - type = number - description = "The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)" - default = 4096 +variable "service_credential_names" { + type = map(string) + description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + default = {} } variable "admin_pass" { @@ -152,13 +153,7 @@ variable "users" { sensitive = true } -variable "service_credential_names" { - type = map(string) - description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." - default = {} -} - -variable "elasticsearch_tags" { +variable "elasticsearch_resource_tags" { type = list(any) description = "The list of tags to be added to the Databases for Elasticsearch instance." default = [] @@ -170,37 +165,6 @@ variable "elasticsearch_access_tags" { default = [] } -############################################################## -# Auto Scaling -############################################################## - -variable "auto_scaling" { - type = object({ - disk = object({ - capacity_enabled = optional(bool, false) - free_space_less_than_percent = optional(number, 10) - io_above_percent = optional(number, 90) - io_enabled = optional(bool, false) - io_over_period = optional(string, "15m") - rate_increase_percent = optional(number, 10) - rate_limit_mb_per_member = optional(number, 3670016) - rate_period_seconds = optional(number, 900) - rate_units = optional(string, "mb") - }) - memory = object({ - io_above_percent = optional(number, 90) - io_enabled = optional(bool, false) - io_over_period = optional(string, "15m") - rate_increase_percent = optional(number, 10) - rate_limit_mb_per_member = optional(number, 114688) - rate_period_seconds = optional(number, 900) - rate_units = optional(string, "mb") - }) - }) - description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." - default = null -} - ############################################################## # Encryption ############################################################## @@ -209,85 +173,90 @@ variable "existing_kms_instance_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. Applies only if `use_ibm_owned_encryption_key` is false. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_instance_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_kms_instance_crn' should not be set" - } - - validation { - condition = ( - length(compact([var.existing_kms_instance_crn, var.existing_kms_key_crn, var.existing_backup_kms_key_crn])) == 1 ? true : false - ) - error_message = "To enable KMS encryption one of 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn' must be set." - } } variable "existing_kms_key_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null +} - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_key_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_kms_key_crn' should not be set" - } +variable "skip_elasticsearch_kms_auth_policy" { + type = bool + description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true." + default = false } -variable "existing_backup_kms_key_crn" { +variable "ibmcloud_kms_api_key" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Elastic Search instance. Leave this input empty if the same account owns both instances." + sensitive = true default = null - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" - } } -variable "skip_es_kms_auth_policy" { - type = bool - description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true." - default = false -} -variable "elasticsearch_key_ring_name" { +variable "key_ring_name" { type = string default = "elasticsearch-key-ring" description = "The name for the key ring created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } -variable "elasticsearch_key_name" { +variable "key_name" { type = string default = "elasticsearch-key" description = "The name for the key created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } -variable "ibmcloud_kms_api_key" { +variable "existing_backup_kms_key_crn" { type = string - description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Elastic Search instance. Leave this input empty if the same account owns both instances." - sensitive = true + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null + + validation { + condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true + error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" + } } -############################################################################## -## Secrets Manager Service Credentials -############################################################################## +############################################################## +# Auto Scaling +############################################################## + +variable "auto_scaling" { + type = object({ + disk = object({ + capacity_enabled = optional(bool, false) + free_space_less_than_percent = optional(number, 10) + io_above_percent = optional(number, 90) + io_enabled = optional(bool, false) + io_over_period = optional(string, "15m") + rate_increase_percent = optional(number, 10) + rate_limit_mb_per_member = optional(number, 3670016) + rate_period_seconds = optional(number, 900) + rate_units = optional(string, "mb") + }) + memory = object({ + io_above_percent = optional(number, 90) + io_enabled = optional(bool, false) + io_over_period = optional(string, "15m") + rate_increase_percent = optional(number, 10) + rate_limit_mb_per_member = optional(number, 114688) + rate_period_seconds = optional(number, 900) + rate_units = optional(string, "mb") + }) + }) + description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + default = null +} + +############################################################################# +# Secrets Manager Service Credentials +############################################################################# variable "existing_secrets_manager_instance_crn" { type = string default = null description = "The CRN of existing secrets manager to use to create service credential secrets for Databases for Elasticsearch instance." - - validation { - condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_group != null : true - error_message = "`admin_pass_secrets_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set." - } - - validation { - condition = var.existing_secrets_manager_instance_crn != null ? var.admin_pass_secrets_manager_secret_name != null : true - error_message = "`admin_pass_secrets_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set." - } } variable "service_credential_secrets" { @@ -337,6 +306,14 @@ variable "admin_pass_secrets_manager_secret_group" { type = string description = "The name of a new or existing secrets manager secret group for admin password. To use existing secret group, `use_existing_admin_pass_secrets_manager_secret_group` must be set to `true`. If a prefix input variable is specified, the prefix is added to the name in the `-` format." default = "elasticsearch-secrets" + + validation { + condition = ( + var.existing_secrets_manager_instance_crn == null || + var.admin_pass_secrets_manager_secret_group != null + ) + error_message = "`admin_pass_secrets_manager_secret_group` is required when `existing_secrets_manager_instance_crn` is set." + } } variable "use_existing_admin_pass_secrets_manager_secret_group" { @@ -349,6 +326,14 @@ variable "admin_pass_secrets_manager_secret_name" { type = string description = "The name of a new elasticsearch administrator secret. If a prefix input variable is specified, the prefix is added to the name in the `-` format." default = "elasticsearch-admin-password" + + validation { + condition = ( + var.existing_secrets_manager_instance_crn == null || + var.admin_pass_secrets_manager_secret_name != null + ) + error_message = "`admin_pass_secrets_manager_secret_name` is required when `existing_secrets_manager_instance_crn` is set." + } } ############################################################## diff --git a/solutions/security-enforced/version.tf b/solutions/security-enforced/version.tf index ffce2a6e..19061593 100644 --- a/solutions/security-enforced/version.tf +++ b/solutions/security-enforced/version.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0" + required_version = ">= 1.9.0" required_providers { # The below tflint-ignore is required because although the below provider is not directly required by this submodule, # it is required by consuming modules, and if not set here, the top level module calling this module will not be @@ -8,7 +8,7 @@ terraform { ibm = { source = "IBM-Cloud/ibm" # Use "greater than or equal to" range in modules - version = ">= 1.70.0, <2.0.0" + version = ">= 1.78.3, <2.0.0" } } } diff --git a/tests/pr_test.go b/tests/pr_test.go index 6e194b09..90b93930 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -118,12 +118,12 @@ func TestRunFullyConfigurableSolutionSchematics(t *testing.T) { assert.Nil(t, err, "This should not have errored") } -func TestRunFullyConfigurableUpgradeSolution(t *testing.T) { +func TestRunSecurityEnforcedUpgradeSolution(t *testing.T) { t.Parallel() options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ Testing: t, - TerraformDir: fullyConfigurableSolutionTerraformDir, + TerraformDir: securityEnforcedSolutionTerraformDir, BestRegionYAMLPath: regionSelectionPath, Prefix: "els-st-da-upg", ResourceGroup: resourceGroup, @@ -133,12 +133,8 @@ func TestRunFullyConfigurableUpgradeSolution(t *testing.T) { options.TerraformVars = map[string]interface{}{ "prefix": options.Prefix, "elasticsearch_access_tags": permanentResources["accessTags"], - "kms_encryption_enabled": true, - "use_ibm_owned_encryption_key": false, "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], - "kms_endpoint_type": "public", "existing_resource_group_name": resourceGroup, - "provider_visibility": "public", // Currently, we can not have upgrade test for elser model, because test provision private endpoint for ES (fscloud profile), and script can not connect to private ES API without schematics // "plan": "platinum", // "enable_elser_model": true, diff --git a/variables.tf b/variables.tf index 5762f1ec..4501accf 100644 --- a/variables.tf +++ b/variables.tf @@ -183,6 +183,12 @@ variable "auto_scaling" { # Encryption ############################################################## +variable "kms_encryption_enabled" { + type = bool + description = "Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." + default = false +} + variable "use_ibm_owned_encryption_key" { type = bool description = "IBM Cloud Databases will secure your deployment's data at rest automatically with an encryption key that IBM hold. Alternatively, you may select your own Key Management System instance and encryption key (Key Protect or Hyper Protect Crypto Services) by setting this to false. If setting to false, a value must be passed for the `kms_key_crn` input." From 7ffd58b14a8f5bdfd6866d84ae89757ec0f23dd0 Mon Sep 17 00:00:00 2001 From: whoffler Date: Mon, 23 Jun 2025 09:25:12 +0100 Subject: [PATCH 12/22] SKIP UPGRADE TEST small update --- ibm_catalog.json | 4 ---- solutions/fully-configurable/variables.tf | 2 +- solutions/security-enforced/variables.tf | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index 8f307aa0..353c1bf6 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -28,10 +28,6 @@ "provider_name": "IBM", "support_details": "This product is in the community registry, as such support is handled through the originated repo. If you experience issues please open an issue in the repository [https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/issues](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/issues). Please note this product is not supported via the IBM Cloud Support Center.", "features": [ - { - "title": "Creates an instance of Databases for Elasticsearch", - "description": "Creates and configures an IBM Cloud Databases for Elasticsearch instance." - }, { "title": "KMS encryption", "description": "Provides [KMS encryption](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-key-protect&interface=ui) for the data that you store in the database, enhancing data security." diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index f64063b6..36058306 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -54,7 +54,7 @@ variable "elasticsearch_name" { variable "region" { type = string - description = "The region where you want to deploy your instance, or the region in which your existing instance is in." + description = "The region to provision all resources in. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/region) about how to select different regions for different services." default = "us-south" validation { condition = var.existing_elasticsearch_instance_crn != null && var.region != local.existing_elasticsearch_region ? false : true diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index deed7328..4b23e329 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -39,7 +39,7 @@ variable "elasticsearch_name" { variable "region" { type = string - description = "The region where you want to deploy your instance, or the region in which your existing instance is in." + description = "The region to provision all resources in. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/region) about how to select different regions for different services." default = "us-south" nullable = false } From 639061df823e8ec2ece50435b7e54da71d94ec0a Mon Sep 17 00:00:00 2001 From: whoffler Date: Mon, 23 Jun 2025 09:32:00 +0100 Subject: [PATCH 13/22] SKIP UPGRADE TEST update digram --- .../deployable-architecture-elasticsearch.svg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference-architecture/deployable-architecture-elasticsearch.svg b/reference-architecture/deployable-architecture-elasticsearch.svg index 5ca6ee89..71aad084 100644 --- a/reference-architecture/deployable-architecture-elasticsearch.svg +++ b/reference-architecture/deployable-architecture-elasticsearch.svg @@ -1,4 +1,4 @@ - + -
IBM Cloud
IBM Cloud
KMS Encryption
KMS Encryption
Region
Region
Resource Group
Resource Group
IBM Cloud Elastic Search Instance
IBM Cloud El...
Kibana Code Engine App
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Text is not SVG - cannot display
\ No newline at end of file +
IBM Cloud
IBM Cloud
KMS Encryption
KMS Encryption
Region
Region
Resource Group
Resource Group
IBM Cloud Elastic Search Instance
IBM Cloud El...
Kibana Code Engine App
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Text is not SVG - cannot display
\ No newline at end of file From 19a4b7577086e4d89b42f75a5177fd5854a45c72 Mon Sep 17 00:00:00 2001 From: whoffler Date: Tue, 24 Jun 2025 14:06:28 +0100 Subject: [PATCH 14/22] enhance da, remove use_ibmcloud_encryption, update upgrade test --- .secrets.baseline | 4 +- cra-config.yaml | 1 - ibm_catalog.json | 93 ++++++++++++++++--- .../deployable-architecture-elasticsearch.svg | 2 +- .../catalogValidationValues.json.template | 1 - solutions/fully-configurable/main.tf | 21 ++--- solutions/fully-configurable/variables.tf | 44 +++------ solutions/security-enforced/main.tf | 1 - tests/pr_test.go | 24 ++--- 9 files changed, 114 insertions(+), 77 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 80904806..88ee2d53 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-06-20T10:01:18Z", + "generated_at": "2025-06-24T13:00:25Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -110,7 +110,7 @@ "hashed_secret": "8c7c51db5075ebd0369c51e9f14737d9b4c1c21d", "is_secret": false, "is_verified": false, - "line_number": 357, + "line_number": 353, "type": "Base64 High Entropy String", "verified_result": null } diff --git a/cra-config.yaml b/cra-config.yaml index 7116c372..df65a5bd 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -7,7 +7,6 @@ CRA_TARGETS: CRA_ENVIRONMENT_VARIABLES: TF_VAR_prefix: "test" TF_VAR_kms_encryption_enabled: true - TF_VAR_use_ibm_owned_encryption_key: false TF_VAR_existing_kms_instance_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" TF_VAR_provider_visibility: "public" TF_VAR_existing_resource_group_name: "geretain-test-elasticsearch" diff --git a/ibm_catalog.json b/ibm_catalog.json index 353c1bf6..31db473c 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -49,6 +49,7 @@ { "label": "Fully configurable", "name": "fully-configurable", + "index": 1, "install_type": "fullstack", "working_directory": "solutions/fully-configurable", "compliance": { @@ -91,8 +92,20 @@ "architecture": { "features": [ { - "title": " Creates an instance of Databases for Elasticsearch", - "description": "This architecture creates an instance of IBM Cloud Databases for Elasticsearch with KMS encryption. It accepts or creates a resource group, and provides autoscaling rules." + "title": "KMS encryption", + "description": "Provides [KMS encryption](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-key-protect&interface=ui) for the data that you store in the database, enhancing data security." + }, + { + "title": "Autoscaling", + "description": "Provides the [autoscaling](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-autoscaling&interface=ui) to allow the database to increase resources in response to usage." + }, + { + "title": "Access tags", + "description": "Attaches access tags to the Elasticsearch instance." + }, + { + "title": "Backup restoration", + "description": "Provides [database restoration](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-dashboard-backups&interface=ui) using a backup created by a deployment with the same service ID." } ], "diagrams": [ @@ -254,10 +267,26 @@ ] }, { - "key": "elasticsearch_resource_tags" + "key": "elasticsearch_resource_tags", + "type": "array", + "custom_config": { + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "type": "string" + } + } }, { - "key": "elasticsearch_access_tags" + "key": "elasticsearch_access_tags", + "type": "array", + "custom_config": { + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "type": "string" + } + } }, { "key": "auto_scaling" @@ -281,7 +310,13 @@ "key": "admin_pass" }, { - "key": "users" + "key": "users", + "type": "array", + "custom_config": { + "type": "textarea", + "grouping": "deployment", + "original_grouping": "deployment" + } }, { "key": "service_credential_names" @@ -303,7 +338,13 @@ ] }, { - "key": "service_credential_secrets" + "key": "service_credential_secrets", + "type": "array", + "custom_config": { + "type": "textarea", + "grouping": "deployment", + "original_grouping": "deployment" + } }, { "key": "use_existing_admin_pass_secrets_manager_secret_group" @@ -336,9 +377,6 @@ { "key": "kms_encryption_enabled" }, - { - "key": "use_ibm_owned_encryption_key" - }, { "key": "existing_kms_instance_crn" }, @@ -429,6 +467,7 @@ { "label": "Security Enforced", "name": "security-enforced", + "index": 2, "install_type": "fullstack", "working_directory": "solutions/security-enforced", "compliance": { @@ -585,10 +624,26 @@ ] }, { - "key": "elasticsearch_resource_tags" + "key": "elasticsearch_resource_tags", + "type": "array", + "custom_config": { + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "type": "string" + } + } }, { - "key": "elasticsearch_access_tags" + "key": "elasticsearch_access_tags", + "type": "array", + "custom_config": { + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "type": "string" + } + } }, { "key": "auto_scaling" @@ -612,7 +667,13 @@ "key": "admin_pass" }, { - "key": "users" + "key": "users", + "type": "array", + "custom_config": { + "type": "textarea", + "grouping": "deployment", + "original_grouping": "deployment" + } }, { "key": "service_credential_names" @@ -621,7 +682,13 @@ "key": "existing_secrets_manager_instance_crn" }, { - "key": "service_credential_secrets" + "key": "service_credential_secrets", + "type": "array", + "custom_config": { + "type": "textarea", + "grouping": "deployment", + "original_grouping": "deployment" + } }, { "key": "use_existing_admin_pass_secrets_manager_secret_group" diff --git a/reference-architecture/deployable-architecture-elasticsearch.svg b/reference-architecture/deployable-architecture-elasticsearch.svg index 71aad084..b9642103 100644 --- a/reference-architecture/deployable-architecture-elasticsearch.svg +++ b/reference-architecture/deployable-architecture-elasticsearch.svg @@ -1,4 +1,4 @@ -
IBM Cloud
IBM Cloud
KMS Encryption
KMS Encryption
Region
Region
Resource Group
Resource Group
IBM Cloud Elastic Search Instance
IBM Cloud El...
Kibana Code Engine App
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Text is not SVG - cannot display
\ No newline at end of file +
IBM Cloud
IBM Cloud
KMS Encryption
KMS Encryption
Region
Region
Resource Group
Resource Group
IBM Cloud Elastic Search Instance
IBM Cloud El...
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Kibana Code Engine App
Text is not SVG - cannot display
\ No newline at end of file diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template index a859fea0..55ad2a72 100644 --- a/solutions/fully-configurable/catalogValidationValues.json.template +++ b/solutions/fully-configurable/catalogValidationValues.json.template @@ -5,6 +5,5 @@ "elasticsearch_name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", "kms_encryption_enabled": true, - "use_ibm_owned_encryption_key": false, "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN } diff --git a/solutions/fully-configurable/main.tf b/solutions/fully-configurable/main.tf index 5085f36f..4c2a0efc 100644 --- a/solutions/fully-configurable/main.tf +++ b/solutions/fully-configurable/main.tf @@ -17,7 +17,6 @@ locals { create_new_kms_key = ( var.kms_encryption_enabled && var.existing_elasticsearch_instance_crn == null && - !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ) elasticsearch_key_name = "${local.prefix}${var.key_name}" @@ -91,16 +90,16 @@ data "ibm_iam_account_settings" "iam_account_settings" { locals { account_id = data.ibm_iam_account_settings.iam_account_settings.account_id - create_cross_account_kms_auth_policy = var.kms_encryption_enabled && !var.skip_elasticsearch_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key - create_cross_account_backup_kms_auth_policy = var.kms_encryption_enabled && !var.skip_elasticsearch_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key && var.existing_backup_kms_key_crn != null + create_cross_account_kms_auth_policy = var.kms_encryption_enabled && !var.skip_elasticsearch_kms_auth_policy && var.ibmcloud_kms_api_key != null + create_cross_account_backup_kms_auth_policy = var.kms_encryption_enabled && !var.skip_elasticsearch_kms_auth_policy && var.ibmcloud_kms_api_key != null && var.existing_backup_kms_key_crn != null # If KMS encryption enabled (and existing ES instance is not being passed), parse details from the existing key if being passed, otherwise get it from the key that the DA creates - kms_account_id = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : module.kms_instance_crn_parser[0].account_id - kms_service = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : module.kms_instance_crn_parser[0].service_name - kms_instance_guid = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_instance : module.kms_instance_crn_parser[0].service_instance - kms_key_crn = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? var.existing_kms_key_crn : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].crn - kms_key_id = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].resource : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].key_id - kms_region = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].region : module.kms_instance_crn_parser[0].region + kms_account_id = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : module.kms_instance_crn_parser[0].account_id + kms_service = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : module.kms_instance_crn_parser[0].service_name + kms_instance_guid = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].service_instance : module.kms_instance_crn_parser[0].service_instance + kms_key_crn = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null ? null : var.existing_kms_key_crn != null ? var.existing_kms_key_crn : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].crn + kms_key_id = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].resource : module.kms[0].keys[format("%s.%s", local.elasticsearch_key_ring_name, local.elasticsearch_key_name)].key_id + kms_region = !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null ? null : var.existing_kms_key_crn != null ? module.kms_key_crn_parser[0].region : module.kms_instance_crn_parser[0].region # If creating KMS cross account policy for backups, parse backup key details from passed in key CRN backup_kms_account_id = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].account_id : local.kms_account_id @@ -108,7 +107,7 @@ locals { backup_kms_instance_guid = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].service_instance : local.kms_instance_guid backup_kms_key_id = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].resource : local.kms_key_id - backup_kms_key_crn = var.existing_elasticsearch_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_backup_kms_key_crn + backup_kms_key_crn = var.existing_elasticsearch_instance_crn != null || !var.kms_encryption_enabled ? null : var.existing_backup_kms_key_crn # Always use same key for backups unless user explicially passed a value for 'existing_backup_kms_key_crn' use_same_kms_key_for_backups = var.existing_backup_kms_key_crn == null ? true : false } @@ -285,7 +284,7 @@ module "elasticsearch" { skip_iam_authorization_policy = var.kms_encryption_enabled ? var.skip_elasticsearch_kms_auth_policy : true elasticsearch_version = var.elasticsearch_version service_endpoints = var.service_endpoints - use_ibm_owned_encryption_key = var.use_ibm_owned_encryption_key + use_ibm_owned_encryption_key = !var.kms_encryption_enabled kms_key_crn = local.kms_key_crn backup_encryption_key_crn = local.backup_kms_key_crn use_same_kms_key_for_backups = local.use_same_kms_key_for_backups diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 36058306..057a0415 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -210,53 +210,31 @@ variable "kms_encryption_enabled" { type = bool description = "Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." default = false -} - -variable "use_ibm_owned_encryption_key" { - type = bool - description = "IBM Cloud Databases will secure your deployment's data at rest automatically with an encryption key that IBM hold. Alternatively, you may select your own Key Management System instance and encryption key (Key Protect or Hyper Protect Crypto Services) by setting this to false. If setting to false, a value must be passed for `existing_kms_instance_crn` to create a new key, or `existing_kms_key_crn` and/or `existing_backup_kms_key_crn` to use an existing key." - default = false - # this validation ensures IBM-owned key is not used when KMS details are provided validation { condition = ( + !var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || - !(var.use_ibm_owned_encryption_key && ( + ( var.existing_kms_instance_crn != null || var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null - )) + ) ) - error_message = "When setting values for 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn', the 'use_ibm_owned_encryption_key' input must be set to false." - } - - # this validation ensures key info is provided when IBM-owned key is disabled and no Elasticsearch instance is given - validation { - condition = !( - var.existing_elasticsearch_instance_crn == null && - var.use_ibm_owned_encryption_key == false && - var.existing_kms_instance_crn == null && - var.existing_kms_key_crn == null - ) - error_message = "When 'use_ibm_owned_encryption_key' is false, you must provide either 'existing_kms_instance_crn' (to create a new key) or 'existing_kms_key_crn' (to use an existing key)." - } - - validation { - condition = !var.use_ibm_owned_encryption_key && var.existing_kms_instance_crn == null ? (var.existing_kms_key_crn != null || var.existing_backup_kms_key_crn != null) : true - error_message = "When not using ibm owned encryption, you must provide either an existing KMS instance with variable `existing_kms_instance_crn` or an existing KMS key using variable `existing_kms_key_crn` or `existing_backup_kms_key_crn`" + error_message = "When 'kms_encryption_enabled' is true and setting values for 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." } validation { condition = ( - var.use_ibm_owned_encryption_key ? length(compact([var.existing_kms_instance_crn, var.existing_kms_key_crn, var.existing_backup_kms_key_crn])) == 0 : true + !var.kms_encryption_enabled ? length(compact([var.existing_kms_instance_crn, var.existing_kms_key_crn, var.existing_backup_kms_key_crn])) == 0 : true ) - error_message = "When using ibm owned encryption keys by setting variable 'use_ibm_owned_encryption_key' to true, 'existing_kms_instance_crn', 'existing_kms_key_crn' and 'existing_backup_kms_key_crn' should not be set." + error_message = "When using ibm owned encryption keys by setting input 'kms_encryption_enabled' to false, 'existing_kms_instance_crn', 'existing_kms_key_crn' and 'existing_backup_kms_key_crn' should not be set." } } variable "existing_kms_instance_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. Applies only if `use_ibm_owned_encryption_key` is false. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. Applies only if `kms_encryption` is true. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null validation { @@ -267,7 +245,7 @@ variable "existing_kms_instance_crn" { variable "existing_kms_key_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `kms_encryption_enabled` is true. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null validation { @@ -288,7 +266,7 @@ variable "kms_endpoint_type" { variable "skip_elasticsearch_kms_auth_policy" { type = bool - description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true." + description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `kms_encryption_enabled` is false." default = false } @@ -306,7 +284,7 @@ variable "key_name" { variable "existing_backup_kms_key_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `kms_encryption_enabled` is true. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `kms_encryption_enabled` to false to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null validation { @@ -317,7 +295,7 @@ variable "existing_backup_kms_key_crn" { variable "use_default_backup_encryption_key" { type = bool - description = "When `use_ibm_owned_encryption_key` is set to false, backups will be encrypted with either the key specified in `existing_kms_key_crn`, in `existing_backup_kms_key_crn`, or with a new key that will be created in the instance specified in the `existing_kms_instance_crn` input. If you do not want to use your own key for backups encryption, you can set this to `true` to use the IBM Cloud Databases default encryption for backups. Alternatively set `use_ibm_owned_encryption_key` to true to use the default encryption for both backups and deployment data." + description = "When `kms_encryption_enabled` is set to true, backups will be encrypted with either the key specified in `existing_kms_key_crn`, in `existing_backup_kms_key_crn`, or with a new key that will be created in the instance specified in the `existing_kms_instance_crn` input. If you do not want to use your own key for backups encryption, you can set this to `true` to use the IBM Cloud Databases default encryption for backups. Alternatively set `kms_encryption_enabled` to false to use the default encryption for both backups and deployment data." default = false } diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf index fe18eaa2..226bb03f 100644 --- a/solutions/security-enforced/main.tf +++ b/solutions/security-enforced/main.tf @@ -25,7 +25,6 @@ module "elasticsearch" { elasticsearch_access_tags = var.elasticsearch_access_tags # Encryption kms_encryption_enabled = true - use_ibm_owned_encryption_key = false existing_kms_instance_crn = var.existing_kms_instance_crn existing_kms_key_crn = var.existing_kms_key_crn kms_endpoint_type = "private" diff --git a/tests/pr_test.go b/tests/pr_test.go index 90b93930..7a4fbf54 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -97,7 +97,6 @@ func TestRunFullyConfigurableSolutionSchematics(t *testing.T) { {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, - {Name: "use_ibm_owned_encryption_key", Value: false, DataType: "bool"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "kms_endpoint_type", Value: "private", DataType: "string"}, {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, @@ -186,7 +185,6 @@ func TestRunSecurityEnforcedSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, - {Name: "use_ibm_owned_encryption_key", Value: false, DataType: "bool"}, {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, @@ -299,7 +297,7 @@ func TestFullyConfigurableSolutionIBMKeys(t *testing.T) { "elasticsearch_version": "8.12", "provider_visibility": "public", "existing_resource_group_name": resourceGroup, - "use_ibm_owned_encryption_key": true, + "kms_encryption_enabled": false, "prefix": options.Prefix, } @@ -329,25 +327,23 @@ func TestPlanValidation(t *testing.T) { // Test the DA when using Elser model var fullyConfigurableSolutionWithElserModelVars = map[string]interface{}{ - "kms_encryption_enabled": true, - "use_ibm_owned_encryption_key": false, - "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], - "enable_elser_model": true, - "plan": "platinum", + "kms_encryption_enabled": true, + "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], + "enable_elser_model": true, + "plan": "platinum", } // Test the DA when using Kibana dashboard and existing KMS instance var fullyConfigurableSolutionWithKibanaDashboardVars = map[string]interface{}{ - "enable_kibana_dashboard": true, - "kms_encryption_enabled": true, - "use_ibm_owned_encryption_key": false, - "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], - "plan": "enterprise", + "enable_kibana_dashboard": true, + "kms_encryption_enabled": true, + "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], + "plan": "enterprise", } // Test the DA when using IBM owned encryption key var fullyConfigurableSolutionWithUseIbmOwnedEncKey = map[string]interface{}{ - "use_ibm_owned_encryption_key": true, + "kms_encryption_enabled": false, } // Create a map of the variables From bc8a7013eb4cba3d9efadb78c3338f7d9e68ad99 Mon Sep 17 00:00:00 2001 From: whoffler Date: Tue, 24 Jun 2025 14:57:21 +0100 Subject: [PATCH 15/22] align with redis --- ibm_catalog.json | 206 +++++++++--------- .../catalogValidationValues.json.template | 2 +- solutions/fully-configurable/main.tf | 2 +- solutions/fully-configurable/variables.tf | 100 ++++----- solutions/security-enforced/README.md | 2 +- .../catalogValidationValues.json.template | 2 +- solutions/security-enforced/main.tf | 2 +- solutions/security-enforced/variables.tf | 21 +- solutions/security-enforced/version.tf | 10 +- 9 files changed, 164 insertions(+), 183 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index 31db473c..7555f788 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -9,6 +9,7 @@ "target_terraform", "terraform", "data_management", + "database", "solution" ], "keywords": [ @@ -92,20 +93,8 @@ "architecture": { "features": [ { - "title": "KMS encryption", - "description": "Provides [KMS encryption](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-key-protect&interface=ui) for the data that you store in the database, enhancing data security." - }, - { - "title": "Autoscaling", - "description": "Provides the [autoscaling](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-autoscaling&interface=ui) to allow the database to increase resources in response to usage." - }, - { - "title": "Access tags", - "description": "Attaches access tags to the Elasticsearch instance." - }, - { - "title": "Backup restoration", - "description": "Provides [database restoration](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-dashboard-backups&interface=ui) using a backup created by a deployment with the same service ID." + "title": " ", + "description": "Configured to use IBM secure by default standards, but can be edited to fit your use case." } ], "diagrams": [ @@ -211,38 +200,6 @@ } ] }, - { - "key": "elasticsearch_name" - }, - { - "key": "existing_elasticsearch_instance_crn" - }, - { - "key": "plan", - "options": [ - { - "displayname": "enterprise", - "value": "enterprise" - }, - { - "displayname": "platinum", - "value": "platinum" - } - ] - }, - { - "key": "service_endpoints", - "options": [ - { - "displayname": "private", - "value": "private" - }, - { - "displayname": "public", - "value": "public" - } - ] - }, { "key": "elasticsearch_version", "required": false, @@ -266,6 +223,22 @@ } ] }, + { + "key": "name" + }, + { + "key": "plan", + "options": [ + { + "displayname": "enterprise", + "value": "enterprise" + }, + { + "displayname": "platinum", + "value": "platinum" + } + ] + }, { "key": "elasticsearch_resource_tags", "type": "array", @@ -288,9 +261,6 @@ } } }, - { - "key": "auto_scaling" - }, { "key": "members" }, @@ -307,10 +277,26 @@ "key": "member_host_flavor" }, { - "key": "admin_pass" + "key": "auto_scaling" }, { - "key": "users", + "key": "service_endpoints", + "options": [ + { + "displayname": "private", + "value": "private" + }, + { + "displayname": "public", + "value": "public" + } + ] + }, + { + "key": "service_credential_names" + }, + { + "key": "service_credential_secrets", "type": "array", "custom_config": { "type": "textarea", @@ -319,13 +305,14 @@ } }, { - "key": "service_credential_names" + "key": "admin_pass" }, { "key": "existing_secrets_manager_instance_crn" }, { "key": "existing_secrets_manager_endpoint_type", + "hidden": true, "options": [ { "displayname": "public", @@ -338,7 +325,19 @@ ] }, { - "key": "service_credential_secrets", + "key": "skip_elasticsearch_to_secrets_manager_auth_policy" + }, + { + "key": "admin_pass_secrets_manager_secret_group" + }, + { + "key": "admin_pass_secrets_manager_secret_name" + }, + { + "key": "use_existing_admin_pass_secrets_manager_secret_group" + }, + { + "key": "users", "type": "array", "custom_config": { "type": "textarea", @@ -347,22 +346,20 @@ } }, { - "key": "use_existing_admin_pass_secrets_manager_secret_group" - }, - { - "key": "admin_pass_secrets_manager_secret_name" + "key": "ibmcloud_kms_api_key" }, { - "key": "admin_pass_secrets_manager_secret_group" + "key": "kms_encryption_enabled" }, { - "key": "skip_elasticsearch_to_secrets_manager_auth_policy" + "key": "existing_kms_instance_crn" }, { - "key": "ibmcloud_kms_api_key" + "key": "existing_kms_key_crn" }, { "key": "kms_endpoint_type", + "hidden": true, "options": [ { "displayname": "public", @@ -375,13 +372,13 @@ ] }, { - "key": "kms_encryption_enabled" + "key": "key_ring_name" }, { - "key": "existing_kms_instance_crn" + "key": "key_name" }, { - "key": "existing_kms_key_crn" + "key": "elasticsearch_backup_crn" }, { "key": "existing_backup_kms_key_crn" @@ -389,17 +386,11 @@ { "key": "use_default_backup_encryption_key" }, - { - "key": "key_ring_name" - }, - { - "key": "key_name" - }, { "key": "skip_elasticsearch_kms_auth_policy" }, { - "key": "elasticsearch_backup_crn" + "key": "existing_elasticsearch_instance_crn" }, { "key": "enable_elser_model" @@ -484,15 +475,28 @@ "role_crns": [ "crn:v1:bluemix:public:iam::::role:Editor" ], - "service_name": "databases-for-elasticsearch" + "service_name": "databases-for-redis" + }, + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "service_name": "kms", + "notes": "[Optional] Editor access is required to create keys. It is required only if KMS encryption is enabled." + }, + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "service_name": "hs-crypto", + "notes": "[Optional] Editor access is required to create keys in HPCS. It is required only if KMS encryption is enabled." } ], "architecture": { - "descriptions": "This architecture creates an instance of IBM Cloud Databases for Elasticsearch instance with KMS encryption. Supports autoscaling.", "features": [ { - "title": " Creates an instance of Databases for Elasticsearch", - "description": "This architecture creates an instance of IBM Cloud Databases for Elasticsearch with KMS encryption. It accepts or creates a resource group, and provides autoscaling rules." + "title": " ", + "description": "Configured to use IBM secure by default standards that can't be changed." } ], "diagrams": [ @@ -581,13 +585,7 @@ } ] }, - { - "key": "elasticsearch_name" - }, - { - "key": "existing_elasticsearch_instance_crn" - }, - { +{ "key": "plan", "options": [ { @@ -623,6 +621,9 @@ } ] }, + { + "key": "name" + }, { "key": "elasticsearch_resource_tags", "type": "array", @@ -645,9 +646,6 @@ } } }, - { - "key": "auto_scaling" - }, { "key": "members" }, @@ -664,10 +662,13 @@ "key": "member_host_flavor" }, { - "key": "admin_pass" + "key": "auto_scaling" }, { - "key": "users", + "key": "service_credential_names" + }, + { + "key": "service_credential_secrets", "type": "array", "custom_config": { "type": "textarea", @@ -676,31 +677,31 @@ } }, { - "key": "service_credential_names" + "key": "admin_pass" }, { "key": "existing_secrets_manager_instance_crn" }, { - "key": "service_credential_secrets", - "type": "array", - "custom_config": { - "type": "textarea", - "grouping": "deployment", - "original_grouping": "deployment" - } + "key": "skip_elasticsearch_to_secrets_manager_auth_policy" }, { - "key": "use_existing_admin_pass_secrets_manager_secret_group" + "key": "admin_pass_secrets_manager_secret_group" }, { "key": "admin_pass_secrets_manager_secret_name" }, { - "key": "admin_pass_secrets_manager_secret_group" + "key": "use_existing_admin_pass_secrets_manager_secret_group" }, { - "key": "skip_elasticsearch_to_secrets_manager_auth_policy" + "key": "users", + "type": "array", + "custom_config": { + "type": "textarea", + "grouping": "deployment", + "original_grouping": "deployment" + } }, { "key": "ibmcloud_kms_api_key" @@ -711,20 +712,23 @@ { "key": "existing_kms_key_crn" }, - { - "key": "existing_backup_kms_key_crn" - }, { "key": "key_ring_name" }, { "key": "key_name" }, + { + "key": "elasticsearch_backup_crn" + }, + { + "key": "existing_backup_kms_key_crn" + }, { "key": "skip_elasticsearch_kms_auth_policy" }, { - "key": "elasticsearch_backup_crn" + "key": "existing_elasticsearch_instance_crn" }, { "key": "enable_elser_model" diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template index 55ad2a72..c8be7749 100644 --- a/solutions/fully-configurable/catalogValidationValues.json.template +++ b/solutions/fully-configurable/catalogValidationValues.json.template @@ -2,7 +2,7 @@ "ibmcloud_api_key": $VALIDATION_APIKEY, "region": "us-south", "elasticsearch_resource_tags": $TAGS, - "elasticsearch_name": $PREFIX, + "name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", "kms_encryption_enabled": true, "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN diff --git a/solutions/fully-configurable/main.tf b/solutions/fully-configurable/main.tf index 4c2a0efc..6acf2c6f 100644 --- a/solutions/fully-configurable/main.tf +++ b/solutions/fully-configurable/main.tf @@ -278,7 +278,7 @@ module "elasticsearch" { source = "../.." depends_on = [time_sleep.wait_for_authorization_policy, time_sleep.wait_for_backup_kms_authorization_policy] resource_group_id = module.resource_group.resource_group_id - name = "${local.prefix}${var.elasticsearch_name}" + name = "${local.prefix}${var.name}" region = var.region plan = var.plan skip_iam_authorization_policy = var.kms_encryption_enabled ? var.skip_elasticsearch_kms_auth_policy : true diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 057a0415..3bb687d3 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -1,5 +1,5 @@ ############################################################################## -# DA extra +# Input Variables ############################################################################## variable "ibmcloud_api_key" { @@ -17,8 +17,9 @@ variable "existing_resource_group_name" { variable "prefix" { type = string - description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To not use any prefix value, you can set this value to `null` or an empty string." nullable = true + description = "The prefix to be added to all resources created by this solution. To skip using a prefix, set this value to null or an empty string. The prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It should not exceed 16 characters, must not end with a hyphen('-'), and can not contain consecutive hyphens ('--'). Example: prod-0205-cos. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/prefix.md)." + validation { condition = (var.prefix == null ? true : alltrue([ @@ -30,22 +31,7 @@ variable "prefix" { } } -variable "provider_visibility" { - description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints)." - type = string - default = "private" - nullable = false - 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'." - } -} - -############################################################################## -# Input Variables -############################################################################## - -variable "elasticsearch_name" { +variable "name" { type = string description = "The name of the Databases for Elasticsearch instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format." default = "elasticsearch" @@ -53,9 +39,10 @@ variable "elasticsearch_name" { } variable "region" { - type = string description = "The region to provision all resources in. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/region) about how to select different regions for different services." + type = string default = "us-south" + validation { condition = var.existing_elasticsearch_instance_crn != null && var.region != local.existing_elasticsearch_region ? false : true error_message = "The region detected in the 'existing_elasticsearch_instance_crn' value must match the value of the 'region' input variable when passing an existing instance." @@ -75,20 +62,6 @@ variable "elasticsearch_version" { default = null } -variable "elasticsearch_backup_crn" { - type = string - description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." - default = null - - validation { - condition = anytrue([ - var.elasticsearch_backup_crn == null, - can(regex("^crn:.*:backup:", var.elasticsearch_backup_crn)) - ]) - error_message = "backup_crn must be null OR starts with 'crn:' and contains ':backup:'" - } -} - variable "plan" { type = string description = "The name of the service plan for your Databases for Elasticsearch instance. Possible values: `enterprise`, `platinum`." @@ -166,8 +139,8 @@ variable "member_host_flavor" { } variable "service_credential_names" { - type = map(string) description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + type = map(string) default = {} } @@ -185,9 +158,9 @@ variable "users" { type = optional(string) role = optional(string) })) - description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." default = [] sensitive = true + description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." } variable "elasticsearch_resource_tags" { @@ -208,27 +181,22 @@ variable "elasticsearch_access_tags" { variable "kms_encryption_enabled" { type = bool - description = "Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." + description = "Set to true to enable KMS encryption using customer-managed keys. When enabled, you must provide a value for at least one of the following: existing_kms_instance_crn, existing_kms_key_crn, or existing_backup_kms_key_crn. If set to false, IBM-owned encryption is used (i.e., encryption keys managed and held by IBM)." default = false validation { - condition = ( - !var.kms_encryption_enabled || + condition = (!var.kms_encryption_enabled || var.existing_elasticsearch_instance_crn != null || - ( - var.existing_kms_instance_crn != null || - var.existing_kms_key_crn != null || - var.existing_backup_kms_key_crn != null - ) + var.existing_kms_instance_crn != null || + var.existing_kms_key_crn != null || + var.existing_backup_kms_key_crn != null ) - error_message = "When 'kms_encryption_enabled' is true and setting values for 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." + error_message = "When 'kms_encryption_enabled' is true, you must provide either 'existing_backup_kms_key_crn', 'existing_kms_instance_crn' (to create a new key) or 'existing_kms_key_crn' (to use an existing key)." } validation { - condition = ( - !var.kms_encryption_enabled ? length(compact([var.existing_kms_instance_crn, var.existing_kms_key_crn, var.existing_backup_kms_key_crn])) == 0 : true - ) - error_message = "When using ibm owned encryption keys by setting input 'kms_encryption_enabled' to false, 'existing_kms_instance_crn', 'existing_kms_key_crn' and 'existing_backup_kms_key_crn' should not be set." + condition = (var.existing_kms_instance_crn == null && var.existing_kms_key_crn == null && var.existing_backup_kms_key_crn == null) || var.kms_encryption_enabled + error_message = "When either 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn' is set then 'kms_encryption_enabled' must be set to true." } } @@ -270,6 +238,13 @@ variable "skip_elasticsearch_kms_auth_policy" { default = false } +variable "ibmcloud_kms_api_key" { + type = string + description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Elastic Search instance. Leave this input empty if the same account owns both instances." + sensitive = true + default = null +} + variable "key_ring_name" { type = string default = "elasticsearch-key-ring" @@ -286,11 +261,6 @@ variable "existing_backup_kms_key_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `kms_encryption_enabled` is true. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `kms_encryption_enabled` to false to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" - } } variable "use_default_backup_encryption_key" { @@ -299,13 +269,30 @@ variable "use_default_backup_encryption_key" { default = false } -variable "ibmcloud_kms_api_key" { +variable "elasticsearch_backup_crn" { type = string - description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Elastic Search instance. Leave this input empty if the same account owns both instances." - sensitive = true + description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." default = null + + validation { + condition = anytrue([ + var.elasticsearch_backup_crn == null, + can(regex("^crn:.*:backup:", var.elasticsearch_backup_crn)) + ]) + error_message = "backup_crn must be null OR starts with 'crn:' and contains ':backup:'" + } } +variable "provider_visibility" { + description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints)." + type = string + default = "private" + nullable = false + 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'." + } +} ############################################################## # Auto Scaling @@ -338,7 +325,6 @@ variable "auto_scaling" { default = null } - ############################################################################# # Secrets Manager Service Credentials ############################################################################# diff --git a/solutions/security-enforced/README.md b/solutions/security-enforced/README.md index ed731ec7..da8cc16f 100644 --- a/solutions/security-enforced/README.md +++ b/solutions/security-enforced/README.md @@ -1,3 +1,3 @@ -# IBM Cloud Databases for Elasticsearch (Security Enforced) +# Cloud automation for Elasticsearch (Security-enforced) :exclamation: **Important:** This solution is not intended to be called by other modules because it contains a provider configuration and is not compatible with the `for_each`, `count`, and `depends_on` arguments. For more information, see [Providers Within Modules](https://developer.hashicorp.com/terraform/language/modules/develop/providers). diff --git a/solutions/security-enforced/catalogValidationValues.json.template b/solutions/security-enforced/catalogValidationValues.json.template index c40cc403..4e7e4a15 100644 --- a/solutions/security-enforced/catalogValidationValues.json.template +++ b/solutions/security-enforced/catalogValidationValues.json.template @@ -2,7 +2,7 @@ "ibmcloud_api_key": $VALIDATION_APIKEY, "region": "us-south", "elasticsearch_resource_tags": $TAGS, - "elasticsearch_name": $PREFIX, + "name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN } diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf index 226bb03f..ce7507a5 100644 --- a/solutions/security-enforced/main.tf +++ b/solutions/security-enforced/main.tf @@ -3,7 +3,7 @@ module "elasticsearch" { ibmcloud_api_key = var.ibmcloud_api_key existing_resource_group_name = var.existing_resource_group_name prefix = var.prefix - elasticsearch_name = var.elasticsearch_name + name = var.name provider_visibility = "private" region = var.region existing_elasticsearch_instance_crn = var.existing_elasticsearch_instance_crn diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index 4b23e329..9bfdd306 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -17,8 +17,8 @@ variable "existing_resource_group_name" { variable "prefix" { type = string - description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To not use any prefix value, you can set this value to `null` or an empty string." nullable = true + description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To not use any prefix value, you can set this value to `null` or an empty string." validation { condition = (var.prefix == null ? true : alltrue([ @@ -30,7 +30,7 @@ variable "prefix" { } } -variable "elasticsearch_name" { +variable "name" { type = string description = "The name of the Databases for Elasticsearch instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format." default = "elasticsearch" @@ -38,8 +38,8 @@ variable "elasticsearch_name" { } variable "region" { - type = string description = "The region to provision all resources in. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/region) about how to select different regions for different services." + type = string default = "us-south" nullable = false } @@ -57,12 +57,6 @@ variable "elasticsearch_version" { default = null } -variable "elasticsearch_backup_crn" { - type = string - description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." - default = null -} - variable "plan" { type = string description = "The name of the service plan for your Databases for Elasticsearch instance. Possible values: `enterprise`, `platinum`." @@ -148,9 +142,9 @@ variable "users" { type = optional(string) role = optional(string) })) - description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." default = [] sensitive = true + description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." } variable "elasticsearch_resource_tags" { @@ -194,7 +188,6 @@ variable "ibmcloud_kms_api_key" { default = null } - variable "key_ring_name" { type = string default = "elasticsearch-key-ring" @@ -218,6 +211,12 @@ variable "existing_backup_kms_key_crn" { } } +variable "elasticsearch_backup_crn" { + type = string + description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." + default = null +} + ############################################################## # Auto Scaling ############################################################## diff --git a/solutions/security-enforced/version.tf b/solutions/security-enforced/version.tf index 19061593..70b38b5b 100644 --- a/solutions/security-enforced/version.tf +++ b/solutions/security-enforced/version.tf @@ -1,14 +1,6 @@ terraform { required_version = ">= 1.9.0" + # Lock DA into an exact provider version - renovate automation will keep it updated required_providers { - # The below tflint-ignore is required because although the below provider is not directly required by this submodule, - # it is required by consuming modules, and if not set here, the top level module calling this module will not be - # able to set alternative alias for the provider. - # tflint-ignore: terraform_unused_required_providers - ibm = { - source = "IBM-Cloud/ibm" - # Use "greater than or equal to" range in modules - version = ">= 1.78.3, <2.0.0" - } } } From 882a1ea656fa97d9c43bfbe13d7347a8bf39e16c Mon Sep 17 00:00:00 2001 From: whoffler Date: Wed, 25 Jun 2025 15:13:47 +0100 Subject: [PATCH 16/22] rebase on redis --- ibm_catalog.json | 28 ++++++++++++++--------- solutions/fully-configurable/variables.tf | 10 ++++---- solutions/security-enforced/variables.tf | 8 +++---- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index 7555f788..d1c2c98d 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -65,9 +65,10 @@ "iam_permissions": [ { "role_crns": [ - "crn:v1:bluemix:public:iam::::role:Administrator" + "crn:v1:bluemix:public:iam::::role:Viewer" ], - "service_name": "all-account-management-services" + "service_name": "Resource group only", + "notes": "Viewer access is required in the resource group you want to provision in." }, { "role_crns": [ @@ -132,7 +133,7 @@ }, { "key": "existing_resource_group_name", - "required": true, + "display_name": "resource_group", "custom_config": { "type": "resource_group", "grouping": "deployment", @@ -143,8 +144,7 @@ } }, { - "key": "prefix", - "required": true + "key": "prefix" }, { "key": "region", @@ -471,6 +471,13 @@ ] }, "iam_permissions": [ + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Viewer" + ], + "service_name": "Resource group only", + "notes": "Viewer access is required in the resource group you want to provision in." + }, { "role_crns": [ "crn:v1:bluemix:public:iam::::role:Editor" @@ -489,7 +496,7 @@ "crn:v1:bluemix:public:iam::::role:Editor" ], "service_name": "hs-crypto", - "notes": "[Optional] Editor access is required to create keys in HPCS. It is required only if KMS encryption is enabled." + "notes": "[Optional] Editor access is required to create keys in HPCS. It is only required when using HPCS for encryption." } ], "architecture": { @@ -516,7 +523,7 @@ }, { "key": "existing_resource_group_name", - "required": true, + "display_name": "resource_group", "custom_config": { "type": "resource_group", "grouping": "deployment", @@ -527,9 +534,7 @@ } }, { - "key": "prefix", - "required": true, - "description": "Prefix to add to all resources created by this solution. To not use any prefix value, you can enter the string `__NULL__`." + "key": "prefix" }, { "key": "region", @@ -707,7 +712,8 @@ "key": "ibmcloud_kms_api_key" }, { - "key": "existing_kms_instance_crn" + "key": "existing_kms_instance_crn", + "required": true }, { "key": "existing_kms_key_crn" diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 3bb687d3..df9021f0 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -57,8 +57,8 @@ variable "existing_elasticsearch_instance_crn" { } variable "elasticsearch_version" { - type = string description = "The version of the Databases for Elasticsearch instance. If no value is specified, the current preferred version of Databases for Elasticsearch is used." + type = string default = null } @@ -202,7 +202,7 @@ variable "kms_encryption_enabled" { variable "existing_kms_instance_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. Applies only if `kms_encryption` is true. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null validation { @@ -213,7 +213,7 @@ variable "existing_kms_instance_crn" { variable "existing_kms_key_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `kms_encryption_enabled` is true. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null validation { @@ -224,7 +224,7 @@ variable "existing_kms_key_crn" { variable "kms_endpoint_type" { type = string - description = "The type of endpoint to use for communicating with the Key Protect or Hyper Protect Crypto Services instance. Possible values: `public`, `private`." + description = "The type of endpoint to use for communicating with the Key Protect or Hyper Protect Crypto Services instance. Possible values: `public`, `private`. Applies only if `existing_kms_key_crn` is not specified." default = "private" validation { condition = can(regex("public|private", var.kms_endpoint_type)) @@ -287,7 +287,7 @@ variable "provider_visibility" { description = "Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints)." type = string default = "private" - nullable = false + 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'." diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index 9bfdd306..b665d62f 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -165,25 +165,25 @@ variable "elasticsearch_access_tags" { variable "existing_kms_instance_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. Applies only if `use_ibm_owned_encryption_key` is false. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null } variable "existing_kms_key_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null } variable "skip_elasticsearch_kms_auth_policy" { type = bool - description = "Set to true to skip the creation of IAM authorization policies that permits all Databases for Elasticsearch instances in the given resource group 'Reader' access to the Key Protect or Hyper Protect Crypto Services key. This policy is required in order to enable KMS encryption, so only skip creation if there is one already present in your account. No policy is created if `use_ibm_owned_encryption_key` is true." + description = "Whether to create an IAM authorization policy that permits all Databases for Elasticsearch instances in the resource group to read the encryption key from the Hyper Protect Crypto Services instance specified in the `existing_kms_instance_crn` variable." default = false } variable "ibmcloud_kms_api_key" { type = string - description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Elastic Search instance. Leave this input empty if the same account owns both instances." + description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the ElasticSearch instance. Leave this input empty if the same account owns both instances." sensitive = true default = null } From 1e6e2550f84f25d8298e3ae3efc0a91ed59f5d10 Mon Sep 17 00:00:00 2001 From: whoffler Date: Thu, 26 Jun 2025 12:50:25 +0100 Subject: [PATCH 17/22] address feedback --- README.md | 23 +++-- cra-config.yaml | 6 +- examples/backup-restore/version.tf | 2 +- examples/complete/main.tf | 2 +- ibm_catalog.json | 28 +++--- main.tf | 51 ++++++----- modules/fscloud/main.tf | 6 +- .../deployable-architecture-elasticsearch.svg | 2 +- .../catalogValidationValues.json.template | 2 +- solutions/fully-configurable/main.tf | 49 +++++----- solutions/fully-configurable/moved.tf | 4 - solutions/fully-configurable/outputs.tf | 10 +-- solutions/fully-configurable/variables.tf | 69 +++++++------- .../catalogValidationValues.json.template | 2 +- solutions/security-enforced/main.tf | 22 ++--- solutions/security-enforced/outputs.tf | 20 ++--- solutions/security-enforced/variables.tf | 90 ++++++++++++------- tests/pr_test.go | 6 +- variables.tf | 12 +-- version.tf | 8 +- 20 files changed, 215 insertions(+), 199 deletions(-) delete mode 100644 solutions/fully-configurable/moved.tf diff --git a/README.md b/README.md index 40ffbfee..7bf50d57 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,9 @@ You need the following permissions to run this module. | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.9.0 | -| [ibm](#requirement\_ibm) | >= 1.70.0, <2.0.0 | +| [ibm](#requirement\_ibm) | >= 1.79.2, <2.0.0 | | [null](#requirement\_null) | >= 3.2.1, < 4.0.0 | -| [time](#requirement\_time) | >= 0.9.1 | +| [time](#requirement\_time) | >= 0.9.1, < 1.0.0 | ### Modules @@ -76,16 +76,16 @@ You need the following permissions to run this module. | Name | Type | |------|------| -| [ibm_database.elasticsearch](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/database) | resource | -| [ibm_iam_authorization_policy.backup_kms_policy](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | -| [ibm_iam_authorization_policy.policy](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | -| [ibm_resource_key.service_credentials](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/resource_key) | resource | -| [ibm_resource_tag.elasticsearch_tag](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/resources/resource_tag) | resource | +| [ibm_database.elasticsearch](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database) | resource | +| [ibm_iam_authorization_policy.backup_kms_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [ibm_iam_authorization_policy.kms_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource | +| [ibm_resource_key.service_credentials](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/resource_key) | resource | +| [ibm_resource_tag.elasticsearch_tag](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/resource_tag) | resource | | [null_resource.put_vectordb_model](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [null_resource.start_vectordb_model](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [time_sleep.wait_for_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | | [time_sleep.wait_for_backup_kms_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | -| [ibm_database_connection.database_connection](https://registry.terraform.io/providers/ibm-cloud/ibm/latest/docs/data-sources/database_connection) | data source | +| [ibm_database_connection.database_connection](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/database_connection) | data source | ### Inputs @@ -97,16 +97,15 @@ You need the following permissions to run this module. | [backup\_crn](#input\_backup\_crn) | The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after both provisioning is complete and the new deployment that uses that data starts. Specify a backup CRN is in the format `crn:v1:<...>:backup:`. If not specified, the database is provisioned empty. | `string` | `null` | no | | [backup\_encryption\_key\_crn](#input\_backup\_encryption\_key\_crn) | The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false and `use_same_kms_key_for_backups` is false. If no value is passed, and `use_same_kms_key_for_backups` is true, the value of `kms_key_crn` is used. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no | | [cbr\_rules](#input\_cbr\_rules) | (Optional, list) List of context-based restrictions rules to create. |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [cpu\_count](#input\_cpu\_count) | The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling). | `number` | `0` | no | +| [disk\_mb](#input\_disk\_mb) | The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling). | `number` | `5120` | no | | [elasticsearch\_version](#input\_elasticsearch\_version) | The version of Databases for Elasticsearch to deploy. Possible values: `8.7`, `8.10`, `8.12`, `8.15` which requires an Enterprise Platinum pricing plan. If no value is specified, the current preferred version for IBM Cloud Databases is used. | `string` | `null` | no | | [elser\_model\_type](#input\_elser\_model\_type) | Trained ELSER model to be used for Elastic's Natural Language Processing. Possible values: `.elser_model_1`, `.elser_model_2` and `.elser_model_2_linux-x86_64`. Applies only if also 'plan' is set to 'platinum'. [Learn more](https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html) | `string` | `".elser_model_2_linux-x86_64"` | no | | [enable\_elser\_model](#input\_enable\_elser\_model) | Set it to true to install and start the Elastic's Natural Language Processing model. Applies only if also 'plan' is set to 'platinum'. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-elser-embeddings-elasticsearch) | `bool` | `false` | no | -| [kms\_encryption\_enabled](#input\_kms\_encryption\_enabled) | Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing\_kms\_instance\_crn', 'existing\_kms\_key\_crn' or 'existing\_backup\_kms\_key\_crn'. | `bool` | `false` | no | | [kms\_key\_crn](#input\_kms\_key\_crn) | The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. Applies only if `use_ibm_owned_encryption_key` is false. By default this key is used for both deployment data and backups, but this behaviour can be altered using the `use_same_kms_key_for_backups` and `backup_encryption_key_crn` inputs. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups). | `string` | `null` | no | -| [member\_cpu\_count](#input\_member\_cpu\_count) | The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling). | `number` | `0` | no | -| [member\_disk\_mb](#input\_member\_disk\_mb) | The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling). | `number` | `5120` | no | | [member\_host\_flavor](#input\_member\_host\_flavor) | The host flavor per member. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/database#host_flavor). | `string` | `null` | no | -| [member\_memory\_mb](#input\_member\_memory\_mb) | The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling) | `number` | `4096` | no | | [members](#input\_members) | The number of members that are allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling). | `number` | `3` | no | +| [memory\_mb](#input\_memory\_mb) | The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling) | `number` | `4096` | no | | [name](#input\_name) | The name of the Databases for Elasticsearch instance. | `string` | n/a | yes | | [plan](#input\_plan) | The pricing plan for the Databases for Elasticsearch instance. Must be `enterprise` or `platinum` if the `elasticsearch_version` variable is set to `8.10` or later. | `string` | `"enterprise"` | no | | [region](#input\_region) | The region where you want to deploy your instance. | `string` | `"us-south"` | no | diff --git a/cra-config.yaml b/cra-config.yaml index df65a5bd..b87cc8be 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -5,8 +5,8 @@ CRA_TARGETS: CRA_IGNORE_RULES_FILE: "cra-tf-validate-ignore-rules.json" # CRA Ignore file to use. If not provided, it checks the repo root directory for `cra-tf-validate-ignore-rules.json` PROFILE_ID: "fe96bd4d-9b37-40f2-b39f-a62760e326a3" # SCC profile ID (currently set to 'IBM Cloud Framework for Financial Services' '1.7.0' profile). CRA_ENVIRONMENT_VARIABLES: - TF_VAR_prefix: "test" - TF_VAR_kms_encryption_enabled: true TF_VAR_existing_kms_instance_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" - TF_VAR_provider_visibility: "public" TF_VAR_existing_resource_group_name: "geretain-test-elasticsearch" + TF_VAR_kms_encryption_enabled: true + TF_VAR_provider_visibility: "public" + TF_VAR_prefix: "test" diff --git a/examples/backup-restore/version.tf b/examples/backup-restore/version.tf index 170ae1a4..b211acf0 100644 --- a/examples/backup-restore/version.tf +++ b/examples/backup-restore/version.tf @@ -5,7 +5,7 @@ terraform { # module's version.tf (basic example), and 1 example that will always use the latest provider version (complete example). ibm = { source = "IBM-Cloud/ibm" - version = ">=1.70.2, <2.0.0" + version = ">=1.79.2, <2.0.0" } } } diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 60b6b53d..22d70de8 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -80,7 +80,7 @@ module "icd_elasticsearch" { tags = var.resource_tags auto_scaling = var.auto_scaling member_host_flavor = "multitenant" - member_memory_mb = 4096 + memory_mb = 4096 # Example of how to use different KMS keys for data and backups use_ibm_owned_encryption_key = false diff --git a/ibm_catalog.json b/ibm_catalog.json index d1c2c98d..b13f8a77 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -23,7 +23,7 @@ "nosql" ], "short_description": "Creates and configures an instance of IBM Cloud Databases for Elasticsearch.", - "long_description": "This architecture supports creating and configuring an instance of [Databases for Elasticsearch](https://www.ibm.com/products/databases-for-elasticsearch), with optional KMS encryption. This Terraform-based automation is part of a broader suite of IBM-maintained Infrastructure as Code (IaC) asset collection, each following the naming pattern \"Cloud automation for *servicename*\" and focusing on single IBM Cloud service. These single-service deployable architectures can be used on their own to streamline and automate service deployments through an [IaC approach](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-understanding-projects), or assembled together into a broader [automated IaC stack](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-config-stack) to automate the deployment of an end-to-end solution architecture.", + "long_description": "This architecture supports creating and configuring an instance of [Databases for Elasticsearch](https://www.ibm.com/products/databases-for-elasticsearch), with optional KMS encryption.\n\nℹ️ This Terraform-based automation is part of a broader suite of IBM-maintained Infrastructure as Code (IaC) assets, each following the naming pattern \"Cloud automation for *servicename*\" and focusing on single IBM Cloud service. These single-service deployable architectures can be used on their own to streamline and automate service deployments through an [IaC approach](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-understanding-projects), or assembled together into a broader [automated IaC stack](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-config-stack) to automate the deployment of an end-to-end solution architecture.", "offering_docs_url": "https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/README.md", "offering_icon_url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/main/images/elasticsearch_icon.svg", "provider_name": "IBM", @@ -58,7 +58,7 @@ "profiles": [ { "profile_name": "IBM Cloud Framework for Financial Services", - "profile_version": "1.6.0" + "profile_version": "1.7.0" } ] }, @@ -81,14 +81,14 @@ "crn:v1:bluemix:public:iam::::role:Editor" ], "service_name": "kms", - "notes": "[Optional] Editor access is required to create keys. It is required only if KMS encryption is enabled." + "notes": "[Optional] Editor access is required to create keys. It is only required when using Key Protect for encryption." }, { "role_crns": [ "crn:v1:bluemix:public:iam::::role:Editor" ], "service_name": "hs-crypto", - "notes": "[Optional] Editor access is required to create keys in HPCS. It is required only if KMS encryption is enabled." + "notes": "[Optional] Editor access is required to create keys in HPCS. It is only required when using HPCS for encryption." } ], "architecture": { @@ -240,7 +240,7 @@ ] }, { - "key": "elasticsearch_resource_tags", + "key": "resource_tags", "type": "array", "custom_config": { "grouping": "deployment", @@ -251,7 +251,7 @@ } }, { - "key": "elasticsearch_access_tags", + "key": "access_tags", "type": "array", "custom_config": { "grouping": "deployment", @@ -289,6 +289,10 @@ { "displayname": "public", "value": "public" + }, + { + "displayname": "public-and-private", + "value": "public-and-private" } ] }, @@ -378,7 +382,7 @@ "key": "key_name" }, { - "key": "elasticsearch_backup_crn" + "key": "backup_crn" }, { "key": "existing_backup_kms_key_crn" @@ -456,7 +460,7 @@ ] }, { - "label": "Security Enforced", + "label": "Security-enforced", "name": "security-enforced", "index": 2, "install_type": "fullstack", @@ -466,7 +470,7 @@ "profiles": [ { "profile_name": "IBM Cloud Framework for Financial Services", - "profile_version": "1.6.0" + "profile_version": "1.7.0" } ] }, @@ -630,7 +634,7 @@ "key": "name" }, { - "key": "elasticsearch_resource_tags", + "key": "resource_tags", "type": "array", "custom_config": { "grouping": "deployment", @@ -641,7 +645,7 @@ } }, { - "key": "elasticsearch_access_tags", + "key": "access_tags", "type": "array", "custom_config": { "grouping": "deployment", @@ -725,7 +729,7 @@ "key": "key_name" }, { - "key": "elasticsearch_backup_crn" + "key": "backup_crn" }, { "key": "existing_backup_kms_key_crn" diff --git a/main.tf b/main.tf index 8d0e26ba..a22ebec4 100644 --- a/main.tf +++ b/main.tf @@ -3,9 +3,11 @@ ######################################################################################################################## locals { + # If no value passed for 'backup_encryption_key_crn' use the value of 'kms_key_crn' and perform validation of 'kms_key_crn' to check if region is supported by backup encryption key. + # If 'use_ibm_owned_encryption_key' is true or 'use_default_backup_encryption_key' is true, default to null. # If no value is passed for 'backup_encryption_key_crn', then default to use 'kms_key_crn'. - backup_encryption_key_crn = !var.kms_encryption_enabled || var.use_ibm_owned_encryption_key || var.use_default_backup_encryption_key ? null : (var.backup_encryption_key_crn != null ? var.backup_encryption_key_crn : var.kms_key_crn) + backup_encryption_key_crn = var.use_ibm_owned_encryption_key || var.use_default_backup_encryption_key ? null : (var.backup_encryption_key_crn != null ? var.backup_encryption_key_crn : var.kms_key_crn) # Determine if auto scaling is enabled auto_scaling_enabled = var.auto_scaling == null ? [] : [1] @@ -20,8 +22,8 @@ locals { ######################################################################################################################## locals { - parse_kms_key = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key - parse_backup_kms_key = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key && !var.use_default_backup_encryption_key + parse_kms_key = !var.use_ibm_owned_encryption_key + parse_backup_kms_key = !var.use_ibm_owned_encryption_key && !var.use_default_backup_encryption_key } module "kms_key_crn_parser" { @@ -55,18 +57,19 @@ locals { ######################################################################################################################## locals { - # only create auth policy if kms_encryption_enabled' is enabled, 'use_ibm_owned_encryption_key' is false, and 'skip_iam_authorization_policy' is false - create_kms_auth_policy = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy ? 1 : 0 - # only create backup auth policy if kms_encryption_enabled' is enabled, 'use_ibm_owned_encryption_key' is false, 'skip_iam_authorization_policy' is false and 'use_same_kms_key_for_backups' is false - create_backup_kms_auth_policy = var.kms_encryption_enabled && !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy && !var.use_same_kms_key_for_backups ? 1 : 0 + # only create auth policy if 'use_ibm_owned_encryption_key' is false, and 'skip_iam_authorization_policy' is false + create_kms_auth_policy = !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy ? 1 : 0 + # only create backup auth policy if 'use_ibm_owned_encryption_key' is false, 'skip_iam_authorization_policy' is false and 'use_same_kms_key_for_backups' is false + create_backup_kms_auth_policy = !var.use_ibm_owned_encryption_key && !var.skip_iam_authorization_policy && !var.use_same_kms_key_for_backups ? 1 : 0 } -resource "ibm_iam_authorization_policy" "policy" { +# Create IAM Authorization Policies to allow Elasticsearch to access KMS for the encryption key +resource "ibm_iam_authorization_policy" "kms_policy" { count = local.create_kms_auth_policy source_service_name = "databases-for-elasticsearch" source_resource_group_id = var.resource_group_id roles = ["Reader"] - description = "Allow all Elastic Search instances in the resource group ${var.resource_group_id} to read the ${local.kms_service} key ${local.kms_key_id} from the instance GUID ${local.kms_key_instance_guid}" + description = "Allow all Elasticsearch instances in the resource group ${var.resource_group_id} to read the ${local.kms_service} key ${local.kms_key_id} from the instance GUID ${local.kms_key_instance_guid}" resource_attributes { name = "serviceName" operator = "stringEquals" @@ -101,8 +104,9 @@ resource "ibm_iam_authorization_policy" "policy" { # workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 resource "time_sleep" "wait_for_authorization_policy" { - count = local.create_kms_auth_policy - depends_on = [ibm_iam_authorization_policy.policy] + count = local.create_kms_auth_policy + depends_on = [ibm_iam_authorization_policy.kms_policy] + create_duration = "30s" } @@ -111,7 +115,7 @@ resource "ibm_iam_authorization_policy" "backup_kms_policy" { source_service_name = "databases-for-elasticsearch" source_resource_group_id = var.resource_group_id roles = ["Reader"] - description = "Allow all Elastic Search instances in the Resource Group ${var.resource_group_id} to read the ${local.backup_kms_service} key ${local.backup_kms_key_id} from the instance GUID ${local.backup_kms_key_instance_guid}" + description = "Allow all Elasticsearch instances in the Resource Group ${var.resource_group_id} to read the ${local.backup_kms_service} key ${local.backup_kms_key_id} from the instance GUID ${local.backup_kms_key_instance_guid}" resource_attributes { name = "serviceName" operator = "stringEquals" @@ -186,12 +190,12 @@ resource "ibm_database" "elasticsearch" { dynamic "group" { for_each = local.host_flavor_set && var.member_host_flavor != "multitenant" && var.backup_crn == null ? [1] : [] content { - group_id = "member" # Only member type is allowed for elasticsearch + group_id = "member" # Only member type is allowed for IBM Cloud Databases host_flavor { id = var.member_host_flavor } disk { - allocation_mb = var.member_disk_mb + allocation_mb = var.disk_mb } members { allocation_count = var.members @@ -203,18 +207,18 @@ resource "ibm_database" "elasticsearch" { dynamic "group" { for_each = local.host_flavor_set && var.member_host_flavor == "multitenant" && var.backup_crn == null ? [1] : [] content { - group_id = "member" # Only member type is allowed for elasticsearch + group_id = "member" # Only member type is allowed for IBM Cloud Databases host_flavor { id = var.member_host_flavor } disk { - allocation_mb = var.member_disk_mb + allocation_mb = var.disk_mb } memory { - allocation_mb = var.member_memory_mb + allocation_mb = var.memory_mb } cpu { - allocation_count = var.member_cpu_count + allocation_count = var.cpu_count } members { allocation_count = var.members @@ -224,17 +228,17 @@ resource "ibm_database" "elasticsearch" { ## This block is for if host_flavor IS NOT set dynamic "group" { - for_each = local.host_flavor_set == false && var.backup_crn == null ? [1] : [] + for_each = !local.host_flavor_set && var.backup_crn == null ? [1] : [] content { - group_id = "member" # Only member type is allowed for elasticsearch + group_id = "member" # Only member type is allowed for IBM Cloud Databases memory { - allocation_mb = var.member_memory_mb + allocation_mb = var.memory_mb } disk { - allocation_mb = var.member_disk_mb + allocation_mb = var.disk_mb } cpu { - allocation_count = var.member_cpu_count + allocation_count = var.cpu_count } members { allocation_count = var.members @@ -293,7 +297,6 @@ resource "ibm_resource_tag" "elasticsearch_tag" { tag_type = "access" } - ######################################################################################################################## # Context Based Restrictions ######################################################################################################################## diff --git a/modules/fscloud/main.tf b/modules/fscloud/main.tf index 9a52d8e6..c3d9c9a7 100644 --- a/modules/fscloud/main.tf +++ b/modules/fscloud/main.tf @@ -17,11 +17,11 @@ module "elasticsearch" { tags = var.tags plan = var.plan members = var.members - member_memory_mb = var.member_memory_mb + memory_mb = var.member_memory_mb admin_pass = var.admin_pass users = var.users - member_disk_mb = var.member_disk_mb - member_cpu_count = var.member_cpu_count + disk_mb = var.member_disk_mb + cpu_count = var.member_cpu_count member_host_flavor = var.member_host_flavor auto_scaling = var.auto_scaling service_credential_names = var.service_credential_names diff --git a/reference-architecture/deployable-architecture-elasticsearch.svg b/reference-architecture/deployable-architecture-elasticsearch.svg index b9642103..302b170b 100644 --- a/reference-architecture/deployable-architecture-elasticsearch.svg +++ b/reference-architecture/deployable-architecture-elasticsearch.svg @@ -1,4 +1,4 @@ -
IBM Cloud
IBM Cloud
KMS Encryption
KMS Encryption
Region
Region
Resource Group
Resource Group
IBM Cloud Elastic Search Instance
IBM Cloud El...
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Kibana Code Engine App
Text is not SVG - cannot display
\ No newline at end of file +
IBM Cloud
IBM Cloud
[Optional] KMS
[Optional] KMS
Key Ring
Key Ring
elasticseach-key
Region
Region
Resource Group
Resource Group
Databases for Elasticsearch
Databases fo...
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Kibana Code Engine App
Text is not SVG - cannot display
\ No newline at end of file diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template index c8be7749..fbb545af 100644 --- a/solutions/fully-configurable/catalogValidationValues.json.template +++ b/solutions/fully-configurable/catalogValidationValues.json.template @@ -1,7 +1,7 @@ { "ibmcloud_api_key": $VALIDATION_APIKEY, "region": "us-south", - "elasticsearch_resource_tags": $TAGS, + "resource_tags": $TAGS, "name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", "kms_encryption_enabled": true, diff --git a/solutions/fully-configurable/main.tf b/solutions/fully-configurable/main.tf index 6acf2c6f..4ce977f6 100644 --- a/solutions/fully-configurable/main.tf +++ b/solutions/fully-configurable/main.tf @@ -1,6 +1,9 @@ ####################################################################################################################### # Resource Group ####################################################################################################################### +locals { + prefix = var.prefix != null ? trimspace(var.prefix) != "" ? "${var.prefix}-" : "" : "" +} module "resource_group" { source = "terraform-ibm-modules/resource-group/ibm" @@ -13,7 +16,7 @@ module "resource_group" { ####################################################################################################################### locals { - prefix = (var.prefix != null && trimspace(var.prefix) != "" ? "${var.prefix}-" : "") + use_ibm_owned_encryption_key = !var.kms_encryption_enabled create_new_kms_key = ( var.kms_encryption_enabled && var.existing_elasticsearch_instance_crn == null && @@ -23,7 +26,6 @@ locals { elasticsearch_key_ring_name = "${local.prefix}${var.key_ring_name}" } - module "kms" { providers = { ibm = ibm.kms @@ -106,8 +108,7 @@ locals { backup_kms_service = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].service_name : local.kms_service backup_kms_instance_guid = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].service_instance : local.kms_instance_guid backup_kms_key_id = local.create_cross_account_backup_kms_auth_policy ? module.kms_backup_key_crn_parser[0].resource : local.kms_key_id - - backup_kms_key_crn = var.existing_elasticsearch_instance_crn != null || !var.kms_encryption_enabled ? null : var.existing_backup_kms_key_crn + backup_kms_key_crn = var.existing_elasticsearch_instance_crn != null || !var.kms_encryption_enabled ? null : var.existing_backup_kms_key_crn # Always use same key for backups unless user explicially passed a value for 'existing_backup_kms_key_crn' use_same_kms_key_for_backups = var.existing_backup_kms_key_crn == null ? true : false } @@ -120,7 +121,7 @@ resource "ibm_iam_authorization_policy" "kms_policy" { source_service_name = "databases-for-elasticsearch" source_resource_group_id = module.resource_group.resource_group_id roles = ["Reader"] - description = "Allow all Elastic Search instances in the resource group ${module.resource_group.resource_group_id} in the account ${local.account_id} to read the ${local.kms_service} key ${local.kms_key_id} from the instance GUID ${local.kms_instance_guid}" + description = "Allow all Elasticsearch instances in the resource group ${module.resource_group.resource_group_id} in the account ${local.account_id} to read the ${local.kms_service} key ${local.kms_key_id} from the instance GUID ${local.kms_instance_guid}" resource_attributes { name = "serviceName" operator = "stringEquals" @@ -168,7 +169,7 @@ resource "ibm_iam_authorization_policy" "backup_kms_policy" { source_service_name = "databases-for-elasticsearch" source_resource_group_id = module.resource_group.resource_group_id roles = ["Reader"] - description = "Allow all Elastic Search instances in the resource group ${module.resource_group.resource_group_id} in the account ${local.account_id} to read the ${local.backup_kms_service} key ${local.backup_kms_key_id} from the instance GUID ${local.backup_kms_instance_guid}" + description = "Allow all Elasticsearch instances in the resource group ${module.resource_group.resource_group_id} in the account ${local.account_id} to read the ${local.backup_kms_service} key ${local.backup_kms_key_id} from the instance GUID ${local.backup_kms_instance_guid}" resource_attributes { name = "serviceName" operator = "stringEquals" @@ -281,27 +282,26 @@ module "elasticsearch" { name = "${local.prefix}${var.name}" region = var.region plan = var.plan - skip_iam_authorization_policy = var.kms_encryption_enabled ? var.skip_elasticsearch_kms_auth_policy : true elasticsearch_version = var.elasticsearch_version - service_endpoints = var.service_endpoints - use_ibm_owned_encryption_key = !var.kms_encryption_enabled + skip_iam_authorization_policy = var.kms_encryption_enabled ? var.skip_elasticsearch_kms_auth_policy : true + use_ibm_owned_encryption_key = local.use_ibm_owned_encryption_key kms_key_crn = local.kms_key_crn backup_encryption_key_crn = local.backup_kms_key_crn use_same_kms_key_for_backups = local.use_same_kms_key_for_backups use_default_backup_encryption_key = var.use_default_backup_encryption_key - backup_crn = var.elasticsearch_backup_crn - kms_encryption_enabled = var.kms_encryption_enabled - access_tags = var.elasticsearch_access_tags - tags = var.elasticsearch_resource_tags + access_tags = var.access_tags + tags = var.resource_tags admin_pass = local.admin_pass users = var.users members = var.members member_host_flavor = var.member_host_flavor - member_memory_mb = var.member_memory_mb - member_disk_mb = var.member_disk_mb - member_cpu_count = var.member_cpu_count + memory_mb = var.member_memory_mb + disk_mb = var.member_disk_mb + cpu_count = var.member_cpu_count auto_scaling = var.auto_scaling service_credential_names = var.service_credential_names + backup_crn = var.backup_crn + service_endpoints = var.service_endpoints enable_elser_model = var.enable_elser_model elser_model_type = var.elser_model_type cbr_rules = var.cbr_rules @@ -323,7 +323,7 @@ locals { ####################################################################################################################### locals { - create_sm_auth_policy = var.skip_elasticsearch_to_secrets_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1 + create_secrets_manager_auth_policy = var.skip_elasticsearch_to_secrets_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1 } # Parse the Secrets Manager CRN @@ -334,10 +334,9 @@ module "sm_instance_crn_parser" { crn = var.existing_secrets_manager_instance_crn } -# create a service authorization between Secrets Manager and the target service (Elastic Search) +# create a service authorization between Secrets Manager and the target service (Elasticsearch) resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" { - count = local.create_sm_auth_policy - depends_on = [module.elasticsearch] + count = local.create_secrets_manager_auth_policy source_service_name = "secrets-manager" source_resource_instance_id = local.existing_secrets_manager_instance_guid target_service_name = "databases-for-elasticsearch" @@ -347,14 +346,13 @@ resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" { } # workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478 -resource "time_sleep" "wait_for_es_authorization_policy" { - count = local.create_sm_auth_policy +resource "time_sleep" "wait_for_elasticsearch_authorization_policy" { + count = local.create_secrets_manager_auth_policy depends_on = [ibm_iam_authorization_policy.secrets_manager_key_manager] create_duration = "30s" } locals { - # Build the structure of the service credential type secret service_credential_secrets = [ for service_credentials in var.service_credential_secrets : { secret_group_name = service_credentials.secret_group_name @@ -396,10 +394,9 @@ locals { existing_secrets_manager_instance_region = var.existing_secrets_manager_instance_crn != null ? module.sm_instance_crn_parser[0].region : null } -# Create secret(s) module "secrets_manager_service_credentials" { - count = var.existing_secrets_manager_instance_crn == null ? 0 : 1 - depends_on = [time_sleep.wait_for_es_authorization_policy] + count = length(local.service_credential_secrets) > 0 ? 1 : 0 + depends_on = [time_sleep.wait_for_elasticsearch_authorization_policy] source = "terraform-ibm-modules/secrets-manager/ibm//modules/secrets" version = "2.3.1" existing_sm_instance_guid = local.existing_secrets_manager_instance_guid diff --git a/solutions/fully-configurable/moved.tf b/solutions/fully-configurable/moved.tf deleted file mode 100644 index ddd70738..00000000 --- a/solutions/fully-configurable/moved.tf +++ /dev/null @@ -1,4 +0,0 @@ -moved { - from = module.elasticsearch - to = module.elasticsearch[0] -} diff --git a/solutions/fully-configurable/outputs.tf b/solutions/fully-configurable/outputs.tf index d99d07b4..1f52d179 100644 --- a/solutions/fully-configurable/outputs.tf +++ b/solutions/fully-configurable/outputs.tf @@ -7,16 +7,16 @@ output "id" { value = local.elasticsearch_id } -output "guid" { - description = "Elasticsearch instance guid" - value = local.elasticsearch_guid -} - output "version" { description = "Elasticsearch instance version" value = local.elasticsearch_version } +output "guid" { + description = "Elasticsearch instance guid" + value = local.elasticsearch_guid +} + output "crn" { description = "Elasticsearch instance crn" value = local.elasticsearch_crn diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index df9021f0..e64de9b6 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -10,7 +10,7 @@ variable "ibmcloud_api_key" { variable "existing_resource_group_name" { type = string - description = "The name of an existing resource group to provision resources in." + description = "The name of an existing resource group to provision resource in." default = "Default" nullable = false } @@ -21,13 +21,24 @@ variable "prefix" { description = "The prefix to be added to all resources created by this solution. To skip using a prefix, set this value to null or an empty string. The prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It should not exceed 16 characters, must not end with a hyphen('-'), and can not contain consecutive hyphens ('--'). Example: prod-0205-cos. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/prefix.md)." validation { - condition = (var.prefix == null ? true : + # - 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]{0,1}[-a-z0-9]{0,14}[a-z0-9]{0,1}$", var.prefix)), - length(regexall("^.*--.*", var.prefix)) == 0 + 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, contain only lowercase letters, numbers, and - characters. Prefixes must end with a lowercase letter or number and be 16 or fewer characters." + 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 = length(var.prefix) <= 16 + error_message = "Prefix must not exceed 16 characters." } } @@ -35,11 +46,10 @@ variable "name" { type = string description = "The name of the Databases for Elasticsearch instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format." default = "elasticsearch" - nullable = false } variable "region" { - description = "The region to provision all resources in. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/region) about how to select different regions for different services." + description = "The region where you want to deploy your instance." type = string default = "us-south" @@ -53,7 +63,6 @@ variable "existing_elasticsearch_instance_crn" { type = string default = null description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." - nullable = true } variable "elasticsearch_version" { @@ -93,12 +102,12 @@ variable "elser_model_type" { variable "service_endpoints" { type = string - description = "Specify whether you want to enable public, or both public and private service endpoints. Possible values: `public`, `public-and-private`" + description = "The type of endpoint of the database instance. Possible values: `public`, `private`, `public-and-private`." default = "private" - nullable = false + validation { - condition = contains(["public", "private"], var.service_endpoints) - error_message = "The specified service endpoint is not supported. The following endpoint options are supported: `public`, `private`" + condition = can(regex("public|public-and-private|private", var.service_endpoints)) + error_message = "Valid values for service_endpoints are 'public', 'public-and-private', and 'private'" } } @@ -139,14 +148,14 @@ variable "member_host_flavor" { } variable "service_credential_names" { - description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "Map of name, role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#svc-credential-name)" type = map(string) default = {} } variable "admin_pass" { type = string - description = "The password for the database administrator. If the admin password is null, then it is created automatically. You must set 'existing_secrets_manager_instance_crn' to store admin pass into secrets manager. You can specify more users in a user block." + description = "The password for the database administrator. If no admin password is provided (i.e., it is null), one will be generated automatically. Additional users can be added using a user block." default = null sensitive = true } @@ -155,21 +164,21 @@ variable "users" { type = list(object({ name = string password = string # pragma: allowlist secret - type = optional(string) + type = string # "type" is required to generate the connection string for the outputs. role = optional(string) })) default = [] sensitive = true - description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "A list of users that you want to create on the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." } -variable "elasticsearch_resource_tags" { - type = list(any) +variable "resource_tags" { + type = list(string) description = "The list of resource tags to be added to the Databases for Elasticsearch instance." default = [] } -variable "elasticsearch_access_tags" { +variable "access_tags" { type = list(string) description = "A list of access tags to apply to the Databases for Elasticsearch instance created by the solution. [Learn more](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." default = [] @@ -204,22 +213,12 @@ variable "existing_kms_instance_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services instance. Required to create a new encryption key and key ring which will be used to encrypt both deployment data and backups. To use an existing key, pass values for `existing_kms_key_crn` and/or `existing_backup_kms_key_crn`. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_instance_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_kms_instance_crn' should not be set" - } } variable "existing_kms_key_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_kms_key_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_kms_key_crn' should not be set" - } } variable "kms_endpoint_type" { @@ -248,13 +247,13 @@ variable "ibmcloud_kms_api_key" { variable "key_ring_name" { type = string default = "elasticsearch-key-ring" - description = "The name for the key ring created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + description = "The name for the key ring created for the ElasticSearch key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } variable "key_name" { type = string default = "elasticsearch-key" - description = "The name for the key created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + description = "The name for the key created for the ElasticSearch key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } variable "existing_backup_kms_key_crn" { @@ -269,15 +268,15 @@ variable "use_default_backup_encryption_key" { default = false } -variable "elasticsearch_backup_crn" { +variable "backup_crn" { type = string description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." default = null validation { condition = anytrue([ - var.elasticsearch_backup_crn == null, - can(regex("^crn:.*:backup:", var.elasticsearch_backup_crn)) + var.backup_crn == null, + can(regex("^crn:.*:backup:", var.backup_crn)) ]) error_message = "backup_crn must be null OR starts with 'crn:' and contains ':backup:'" } @@ -321,7 +320,7 @@ variable "auto_scaling" { rate_units = optional(string, "mb") }) }) - description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "Optional rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#autoscaling)" default = null } diff --git a/solutions/security-enforced/catalogValidationValues.json.template b/solutions/security-enforced/catalogValidationValues.json.template index 4e7e4a15..693f534a 100644 --- a/solutions/security-enforced/catalogValidationValues.json.template +++ b/solutions/security-enforced/catalogValidationValues.json.template @@ -1,7 +1,7 @@ { "ibmcloud_api_key": $VALIDATION_APIKEY, "region": "us-south", - "elasticsearch_resource_tags": $TAGS, + "resource_tags": $TAGS, "name": $PREFIX, "existing_resource_group_name": "geretain-test-permanent", "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf index ce7507a5..12f28ba8 100644 --- a/solutions/security-enforced/main.tf +++ b/solutions/security-enforced/main.tf @@ -8,21 +8,21 @@ module "elasticsearch" { region = var.region existing_elasticsearch_instance_crn = var.existing_elasticsearch_instance_crn elasticsearch_version = var.elasticsearch_version - elasticsearch_backup_crn = var.elasticsearch_backup_crn + backup_crn = var.backup_crn plan = var.plan enable_elser_model = var.enable_elser_model elser_model_type = var.elser_model_type # ICD hosting model properties - members = var.members - member_memory_mb = var.member_memory_mb - member_cpu_count = var.member_cpu_count - member_disk_mb = var.member_disk_mb - member_host_flavor = var.member_host_flavor - service_credential_names = var.service_credential_names - admin_pass = var.admin_pass - users = var.users - elasticsearch_resource_tags = var.elasticsearch_resource_tags - elasticsearch_access_tags = var.elasticsearch_access_tags + members = var.members + member_memory_mb = var.member_memory_mb + member_cpu_count = var.member_cpu_count + member_disk_mb = var.member_disk_mb + member_host_flavor = var.member_host_flavor + service_credential_names = var.service_credential_names + admin_pass = var.admin_pass + users = var.users + resource_tags = var.resource_tags + access_tags = var.access_tags # Encryption kms_encryption_enabled = true existing_kms_instance_crn = var.existing_kms_instance_crn diff --git a/solutions/security-enforced/outputs.tf b/solutions/security-enforced/outputs.tf index 81cbfeb2..34b0f96f 100644 --- a/solutions/security-enforced/outputs.tf +++ b/solutions/security-enforced/outputs.tf @@ -22,11 +22,6 @@ output "crn" { value = module.elasticsearch.crn } -output "cbr_rule_ids" { - description = "CBR rule ids created to restrict Elasticsearch" - value = module.elasticsearch.cbr_rule_ids -} - output "service_credentials_json" { description = "Service credentials json map" value = module.elasticsearch.service_credentials_json @@ -39,11 +34,6 @@ output "service_credentials_object" { sensitive = true } -output "adminuser" { - description = "Database admin user name" - value = module.elasticsearch.adminuser -} - output "hostname" { description = "Database connection hostname" value = module.elasticsearch.hostname @@ -54,6 +44,16 @@ output "port" { value = module.elasticsearch.port } +output "cbr_rule_ids" { + description = "CBR rule ids created to restrict Elasticsearch" + value = module.elasticsearch.cbr_rule_ids +} + +output "adminuser" { + description = "Database admin user name" + value = module.elasticsearch.adminuser +} + output "certificate_base64" { description = "Database connection certificate" value = module.elasticsearch.certificate_base64 diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index b665d62f..ff3d3409 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -1,5 +1,5 @@ ############################################################################## -# DA extra +# Input Variables ############################################################################## variable "ibmcloud_api_key" { @@ -10,7 +10,7 @@ variable "ibmcloud_api_key" { variable "existing_resource_group_name" { type = string - description = "The name of an existing resource group to provision resources in." + description = "The name of an existing resource group to provision resource in." default = "Default" nullable = false } @@ -18,15 +18,27 @@ variable "existing_resource_group_name" { variable "prefix" { type = string nullable = true - description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To not use any prefix value, you can set this value to `null` or an empty string." + description = "The prefix to be added to all resources created by this solution. To skip using a prefix, set this value to null or an empty string. The prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It should not exceed 16 characters, must not end with a hyphen('-'), and can not contain consecutive hyphens ('--'). Example: prod-0205-cos. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/prefix.md)." + validation { - condition = (var.prefix == null ? true : + # - 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]{0,1}[-a-z0-9]{0,14}[a-z0-9]{0,1}$", var.prefix)), - length(regexall("^.*--.*", var.prefix)) == 0 + 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, contain only lowercase letters, numbers, and - characters. Prefixes must end with a lowercase letter or number and be 16 or fewer characters." + 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 = length(var.prefix) <= 16 + error_message = "Prefix must not exceed 16 characters." } } @@ -34,26 +46,23 @@ variable "name" { type = string description = "The name of the Databases for Elasticsearch instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format." default = "elasticsearch" - nullable = false } variable "region" { - description = "The region to provision all resources in. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/region) about how to select different regions for different services." + description = "The region where you want to deploy your instance." type = string default = "us-south" - nullable = false } variable "existing_elasticsearch_instance_crn" { type = string default = null description = "The CRN of an existing Databases for Elasticsearch instance. If no value is specified, a new instance is created." - nullable = true } variable "elasticsearch_version" { - type = string description = "The version of the Databases for Elasticsearch instance. If no value is specified, the current preferred version of Databases for Elasticsearch is used." + type = string default = null } @@ -123,14 +132,14 @@ variable "member_host_flavor" { } variable "service_credential_names" { + description = "Map of name, role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#svc-credential-name)" type = map(string) - description = "The map of name and role for service credentials that you want to create for the database. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." default = {} } variable "admin_pass" { type = string - description = "The password for the database administrator. If the admin password is null, then it is created automatically. You must set 'existing_secrets_manager_instance_crn' to store admin pass into secrets manager. You can specify more users in a user block." + description = "The password for the database administrator. If no admin password is provided (i.e., it is null), one will be generated automatically. Additional users can be added using a user block." default = null sensitive = true } @@ -139,21 +148,21 @@ variable "users" { type = list(object({ name = string password = string # pragma: allowlist secret - type = optional(string) + type = string # "type" is required to generate the connection string for the outputs. role = optional(string) })) default = [] sensitive = true - description = "The list of users that have access to the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "A list of users that you want to create on the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." } -variable "elasticsearch_resource_tags" { - type = list(any) - description = "The list of tags to be added to the Databases for Elasticsearch instance." +variable "resource_tags" { + type = list(string) + description = "The list of resource tags to be added to the Databases for Elasticsearch instance." default = [] } -variable "elasticsearch_access_tags" { +variable "access_tags" { type = list(string) description = "A list of access tags to apply to the Databases for Elasticsearch instance created by the solution. [Learn more](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)." default = [] @@ -173,6 +182,15 @@ variable "existing_kms_key_crn" { type = string description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key to encrypt your data. By default this key is used for both deployment data and backups, but this behaviour can be altered using the optional `existing_backup_kms_key_crn` input. If no value is passed a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." default = null + + + validation { + condition = ( + (var.existing_kms_key_crn != null && var.existing_kms_instance_crn == null) || + (var.existing_kms_key_crn == null && var.existing_kms_instance_crn != null) + ) + error_message = "Either existing_kms_key_crn or existing_kms_instance_crn must be set, but not both." + } } variable "skip_elasticsearch_kms_auth_policy" { @@ -191,30 +209,33 @@ variable "ibmcloud_kms_api_key" { variable "key_ring_name" { type = string default = "elasticsearch-key-ring" - description = "The name for the key ring created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + description = "The name for the key ring created for the Databases for ElasticSearch key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } variable "key_name" { type = string default = "elasticsearch-key" - description = "The name for the key created for the ElasticSearch key. Applies only if not specifying an existing key or using IBM owned keys. If a prefix input variable is specified, the prefix is added to the name in the `-` format." + description = "The name for the key created for the Databases for ElasticSearch key. Applies only if not specifying an existing key. If a prefix input variable is specified, the prefix is added to the name in the `-` format." } variable "existing_backup_kms_key_crn" { type = string - description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. Applies only if `use_ibm_owned_encryption_key` is false. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input. Alternatively set `use_default_backup_encryption_key` to true to use the IBM Cloud Databases default encryption. Bare in mind that backups encryption is only available in certain regions. See [Bring your own key for backups](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-key-protect&interface=ui#key-byok) and [Using the HPCS Key for Backup encryption](https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-hpcs#use-hpcs-backups)." + description = "The CRN of a Key Protect or Hyper Protect Crypto Services encryption key that you want to use for encrypting the disk that holds deployment backups. If no value is passed, the value of `existing_kms_key_crn` is used. If no value is passed for `existing_kms_key_crn`, a new key will be created in the instance specified in the `existing_kms_instance_crn` input." default = null - - validation { - condition = var.existing_elasticsearch_instance_crn != null ? var.existing_backup_kms_key_crn == null : true - error_message = "When using an existing elasticsearch instance 'existing_backup_kms_key_crn' should not be set" - } } -variable "elasticsearch_backup_crn" { +variable "backup_crn" { type = string description = "The CRN of a backup resource to restore from. The backup is created by a database deployment with the same service ID. The backup is loaded after provisioning and the new deployment starts up that uses that data. A backup CRN is in the format crn:v1:<…>:backup:. If omitted, the database is provisioned empty." default = null + + validation { + condition = anytrue([ + var.backup_crn == null, + can(regex("^crn:.*:backup:", var.backup_crn)) + ]) + error_message = "backup_crn must be null OR starts with 'crn:' and contains ':backup:'" + } } ############################################################## @@ -244,7 +265,7 @@ variable "auto_scaling" { rate_units = optional(string, "mb") }) }) - description = "The rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "Optional rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." default = null } @@ -290,15 +311,18 @@ variable "service_credential_secrets" { } validation { - condition = length(var.service_credential_secrets) > 0 ? var.existing_secrets_manager_instance_crn != null : true - error_message = "existing_secrets_manager_instance_crn` is required when adding service credentials to a secrets manager secret." + condition = ( + length(var.service_credential_secrets) == 0 || + var.existing_secrets_manager_instance_crn != null + ) + error_message = "`existing_secrets_manager_instance_crn` is required when adding service credentials to a secrets manager secret." } } variable "skip_elasticsearch_to_secrets_manager_auth_policy" { type = bool default = false - description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for Elasticsearch. Set to `true` to use an existing policy." + description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for Elasticsearch. If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Elasticsearch 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_instance_crn' is not passed." } variable "admin_pass_secrets_manager_secret_group" { diff --git a/tests/pr_test.go b/tests/pr_test.go index 7a4fbf54..3dc4f0e9 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -95,7 +95,7 @@ func TestRunFullyConfigurableSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, - {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, + {Name: "access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "kms_endpoint_type", Value: "private", DataType: "string"}, @@ -131,7 +131,7 @@ func TestRunSecurityEnforcedUpgradeSolution(t *testing.T) { options.TerraformVars = map[string]interface{}{ "prefix": options.Prefix, - "elasticsearch_access_tags": permanentResources["accessTags"], + "access_tags": permanentResources["accessTags"], "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], "existing_resource_group_name": resourceGroup, // Currently, we can not have upgrade test for elser model, because test provision private endpoint for ES (fscloud profile), and script can not connect to private ES API without schematics @@ -185,7 +185,7 @@ func TestRunSecurityEnforcedSolutionSchematics(t *testing.T) { options.TerraformVars = []testschematic.TestSchematicTerraformVar{ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, - {Name: "elasticsearch_access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, + {Name: "access_tags", Value: permanentResources["accessTags"], DataType: "list(string)"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, {Name: "plan", Value: "platinum", DataType: "string"}, diff --git a/variables.tf b/variables.tf index 4501accf..4b72a8b8 100644 --- a/variables.tf +++ b/variables.tf @@ -60,14 +60,14 @@ variable "members" { # Validation is done in the Terraform plan phase by the IBM provider, so no need to add extra validation here. } -variable "member_cpu_count" { +variable "cpu_count" { type = number description = "The dedicated CPU per member that is allocated. For shared CPU, set to 0. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." default = 0 # Validation is done in the Terraform plan phase by the IBM provider, so no need to add extra validation here. } -variable "member_disk_mb" { +variable "disk_mb" { type = number description = "The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)." default = 5120 @@ -81,7 +81,7 @@ variable "member_host_flavor" { # Validation is done in the Terraform plan phase by the IBM provider, so no need to add extra validation here. } -variable "member_memory_mb" { +variable "memory_mb" { type = number description = "The memory per member that is allocated. [Learn more](https://cloud.ibm.com/docs/databases-for-elasticsearch?topic=databases-for-elasticsearch-resources-scaling)" default = 4096 @@ -183,12 +183,6 @@ variable "auto_scaling" { # Encryption ############################################################## -variable "kms_encryption_enabled" { - type = bool - description = "Set to true to enable KMS Encryption using customer managed keys. When set to true, a value must be passed for either 'existing_kms_instance_crn', 'existing_kms_key_crn' or 'existing_backup_kms_key_crn'." - default = false -} - variable "use_ibm_owned_encryption_key" { type = bool description = "IBM Cloud Databases will secure your deployment's data at rest automatically with an encryption key that IBM hold. Alternatively, you may select your own Key Management System instance and encryption key (Key Protect or Hyper Protect Crypto Services) by setting this to false. If setting to false, a value must be passed for the `kms_key_crn` input." diff --git a/version.tf b/version.tf index 0f6877bf..db383db5 100644 --- a/version.tf +++ b/version.tf @@ -1,10 +1,10 @@ terraform { required_version = ">= 1.9.0" - # Use "greater than or equal to" range in modules required_providers { ibm = { - source = "ibm-cloud/ibm" - version = ">= 1.70.0, <2.0.0" + source = "IBM-Cloud/ibm" + # Use "greater than or equal to" range in modules + version = ">= 1.79.2, <2.0.0" } null = { source = "hashicorp/null" @@ -12,7 +12,7 @@ terraform { } time = { source = "hashicorp/time" - version = ">= 0.9.1" + version = ">= 0.9.1, < 1.0.0" } } } From 13e235fa40fcd26191effb03bfb120bf8ff908ca Mon Sep 17 00:00:00 2001 From: whoffler Date: Thu, 26 Jun 2025 16:14:14 +0100 Subject: [PATCH 18/22] update --- .../deployable-architecture-elasticsearch.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference-architecture/deployable-architecture-elasticsearch.svg b/reference-architecture/deployable-architecture-elasticsearch.svg index 302b170b..21bcb9d8 100644 --- a/reference-architecture/deployable-architecture-elasticsearch.svg +++ b/reference-architecture/deployable-architecture-elasticsearch.svg @@ -1,4 +1,4 @@ -
IBM Cloud
IBM Cloud
[Optional] KMS
[Optional] KMS
Key Ring
Key Ring
elasticseach-key
Region
Region
Resource Group
Resource Group
Databases for Elasticsearch
Databases fo...
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Kibana Code Engine App
Text is not SVG - cannot display
\ No newline at end of file +IBM CloudRegionResource GroupDatabase for Elasticsearch
ES
ES
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Kibana Code Engine App
[Optional] KMS
[Optional] KMS
Key Ring
Key Ring
redis-key
Text is not SVG - cannot display
\ No newline at end of file From 8075a79e650a3749606165aec7a9ad22b127575a Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 27 Jun 2025 09:05:23 +0100 Subject: [PATCH 19/22] update diagram --- .../deployable-architecture-elasticsearch.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference-architecture/deployable-architecture-elasticsearch.svg b/reference-architecture/deployable-architecture-elasticsearch.svg index 21bcb9d8..367df641 100644 --- a/reference-architecture/deployable-architecture-elasticsearch.svg +++ b/reference-architecture/deployable-architecture-elasticsearch.svg @@ -1,4 +1,4 @@ -IBM CloudRegionResource GroupDatabase for Elasticsearch
ES
ES
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Kibana Code Engine App
[Optional] KMS
[Optional] KMS
Key Ring
Key Ring
redis-key
Text is not SVG - cannot display
\ No newline at end of file +IBM CloudRegionResource GroupDatabase for Elasticsearch
ES
ES
IBM Cloud Code Engine Project
IBM Cloud Code Engine Project
Kibana Code Engine App
[Optional] KMS
[Optional] KMS
Key Ring
Key Ring
elasticsearch-key
Text is not SVG - cannot display
\ No newline at end of file From 5df79da35ec8194f034b36909713d35f153b38d8 Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 27 Jun 2025 10:28:50 +0100 Subject: [PATCH 20/22] remove default version from ibmcatalog --- ibm_catalog.json | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index b13f8a77..d108f771 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -202,13 +202,8 @@ }, { "key": "elasticsearch_version", - "required": false, - "default_value": "__NULL__", + "required": true, "options": [ - { - "displayname": "preferred", - "value": "__NULL__" - }, { "displayname": "8.15", "value": "8.15" @@ -609,13 +604,8 @@ }, { "key": "elasticsearch_version", - "required": false, - "default_value": "__NULL__", + "required": true, "options": [ - { - "displayname": "preferred", - "value": "__NULL__" - }, { "displayname": "8.15", "value": "8.15" From 0d60484dcfe54701bd0ec87bf72d44a3724f19f0 Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 27 Jun 2025 11:02:28 +0100 Subject: [PATCH 21/22] update se and fc users input descriptions --- solutions/fully-configurable/variables.tf | 2 +- solutions/security-enforced/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index e64de9b6..b8fa53b9 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -169,7 +169,7 @@ variable "users" { })) default = [] sensitive = true - description = "A list of users that you want to create on the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "A list of users that you want to create on the database. Multiple blocks are allowed. The user password must be in the range of 10-32 characters. Be warned that in most case using IAM service credentials (via the var.service_credential_names) is sufficient to control access to the Elasticsearch instance. This blocks creates native Elasticsearch database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#users)" } variable "resource_tags" { diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index ff3d3409..2117401b 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -153,7 +153,7 @@ variable "users" { })) default = [] sensitive = true - description = "A list of users that you want to create on the database. Multiple blocks are allowed. The user password must be 10-32 characters. In most cases, you can use IAM service credentials (by specifying `service_credential_names`) to control access to the database instance. This block creates native database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "A list of users that you want to create on the database. Multiple blocks are allowed. The user password must be in the range of 10-32 characters. Be warned that in most case using IAM service credentials (via the var.service_credential_names) is sufficient to control access to the Elasticsearch instance. This blocks creates native Elasticsearch database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/blob/main/solutions/fully-configurable/DA-types.md#users)" } variable "resource_tags" { From 88c84b931a2f4397a3e74ce2710828b9fe481774 Mon Sep 17 00:00:00 2001 From: whoffler Date: Fri, 27 Jun 2025 11:46:48 +0100 Subject: [PATCH 22/22] update auto_scaling and skip_redis_kms_auth_policy descriptions --- solutions/fully-configurable/variables.tf | 2 +- solutions/security-enforced/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index b8fa53b9..f8963168 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -387,7 +387,7 @@ variable "service_credential_secrets" { variable "skip_elasticsearch_to_secrets_manager_auth_policy" { type = bool default = false - description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for Elasticsearch. Set to `true` to use an existing policy." + description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for Elasticsearch. If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Elasticsearch 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_instance_crn' is not passed." } variable "admin_pass_secrets_manager_secret_group" { diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index 2117401b..456d7d0b 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -265,7 +265,7 @@ variable "auto_scaling" { rate_units = optional(string, "mb") }) }) - description = "Optional rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md)." + description = "Optional rules to allow the database to increase resources in response to usage. Only a single autoscaling block is allowed. Make sure you understand the effects of autoscaling, especially for production environments. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-elasticsearch/tree/main/solutions/fully-configurable/DA-types.md#autoscaling)" default = null }