From 3e8ff010e7ca76aa1ab332c48b16b37f8474bda4 Mon Sep 17 00:00:00 2001 From: Arya Girish K Date: Fri, 24 Oct 2025 12:53:19 +0530 Subject: [PATCH 1/4] feat: Add Ui regex validation --- ibm_catalog.json | 143 +++++++++++++++++++--- solutions/fully-configurable/variables.tf | 2 +- solutions/security-enforced/variables.tf | 2 +- 3 files changed, 130 insertions(+), 17 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index f93614b2..7d3de7f7 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -147,7 +147,18 @@ "description": "The name of an existing resource group to provision the resources." }, { - "key": "prefix" + "key": "prefix", + "default_value": "dev", + "random_string": { + "length": 4 + }, + "value_constraints": [ + { + "type": "regex", + "description": "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 ('--'). It should not exceed 16 characters.", + "value": "^$|^__NULL__$|^[a-z](?!.*--)(?:[a-z0-9-]{0,14}[a-z0-9])?$" + } + ] }, { "key": "region", @@ -333,7 +344,14 @@ "key": "admin_pass" }, { - "key": "existing_secrets_manager_instance_crn" + "key": "existing_secrets_manager_instance_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_secrets_manager_instance_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}secrets-manager:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] }, { "key": "existing_secrets_manager_endpoint_type", @@ -377,10 +395,24 @@ "key": "kms_encryption_enabled" }, { - "key": "existing_kms_instance_crn" + "key": "existing_kms_instance_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_kms_instance_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] }, { - "key": "existing_kms_key_crn" + "key": "existing_kms_key_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_kms_key_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + } + ] }, { "key": "kms_endpoint_type", @@ -403,10 +435,24 @@ "key": "key_name" }, { - "key": "backup_crn" + "key": "backup_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'backup_crn' is not valid.", + "value": "^__NULL__$|^crn:.*:backup:" + } + ] }, { - "key": "existing_backup_kms_key_crn" + "key": "existing_backup_kms_key_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_backup_kms_key_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + } + ] }, { "key": "use_default_backup_encryption_key" @@ -415,7 +461,14 @@ "key": "skip_postgresql_kms_auth_policy" }, { - "key": "existing_postgresql_instance_crn" + "key": "existing_postgresql_instance_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_postgresql_instance_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}databases-for-postgresql:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] }, { "key": "remote_leader_crn" @@ -504,7 +557,18 @@ "description": "The name of an existing resource group to provision the resources." }, { - "key": "prefix" + "key": "prefix", + "default_value": "dev", + "random_string": { + "length": 4 + }, + "value_constraints": [ + { + "type": "regex", + "description": "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 ('--'). It should not exceed 16 characters.", + "value": "^$|^__NULL__$|^[a-z](?!.*--)(?:[a-z0-9-]{0,14}[a-z0-9])?$" + } + ] }, { "key": "region", @@ -670,7 +734,14 @@ "key": "admin_pass" }, { - "key": "existing_secrets_manager_instance_crn" + "key": "existing_secrets_manager_instance_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_secrets_manager_instance_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}secrets-manager:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] }, { "key": "skip_postgresql_secrets_manager_auth_policy" @@ -698,10 +769,24 @@ }, { "key": "existing_kms_instance_crn", - "required": true + "required": true, + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_kms_instance_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] }, { - "key": "existing_kms_key_crn" + "key": "existing_kms_key_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_kms_key_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + } + ] }, { "key": "key_ring_name" @@ -710,19 +795,47 @@ "key": "key_name" }, { - "key": "backup_crn" + "key": "backup_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'backup_crn' is not valid.", + "value": "^__NULL__$|^crn:.*:backup:" + } + ] }, { - "key": "existing_backup_kms_key_crn" + "key": "existing_backup_kms_key_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_backup_kms_key_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + } + ] }, { "key": "skip_postgresql_kms_auth_policy" }, { - "key": "existing_postgresql_instance_crn" + "key": "existing_postgresql_instance_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'existing_postgresql_instance_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}databases-for-postgresql:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] }, { - "key": "remote_leader_crn" + "key": "remote_leader_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'remote_leader_crn' is not valid.", + "value": "^__NULL__$|^crn:(.*:){3}databases-for-postgresql:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] } ], "terraform_version": "1.10.5" diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 746beb12..22b894b1 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -17,7 +17,7 @@ variable "existing_resource_group_name" { variable "prefix" { type = 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)." + description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/prefix.md)." validation { # - null and empty string is allowed diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index 53446680..d7a67e4e 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -17,7 +17,7 @@ variable "existing_resource_group_name" { variable "prefix" { type = 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)." + description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to null or an empty string. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/prefix.md)." validation { # - null and empty string is allowed From 74f5fecd9f01e7d436346d09f0bae87ce75d4930 Mon Sep 17 00:00:00 2001 From: Arya Girish K Date: Thu, 13 Nov 2025 20:42:52 +0530 Subject: [PATCH 2/4] fix: update CRN pattern --- ibm_catalog.json | 35 ++++++++++++++--------- solutions/fully-configurable/variables.tf | 34 +++++++++++++++++++++- solutions/security-enforced/variables.tf | 26 ++++++++++++++++- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index d425e3e1..890713dc 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -340,7 +340,7 @@ { "type": "regex", "description": "The value provided for 'existing_secrets_manager_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}secrets-manager:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}{3}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, @@ -391,7 +391,7 @@ { "type": "regex", "description": "The value provided for 'existing_kms_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, @@ -401,7 +401,7 @@ { "type": "regex", "description": "The value provided for 'existing_kms_key_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" } ] }, @@ -431,7 +431,7 @@ { "type": "regex", "description": "The value provided for 'backup_crn' is not valid.", - "value": "^__NULL__$|^crn:.*:backup:" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:backup:[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$" } ] }, @@ -441,7 +441,7 @@ { "type": "regex", "description": "The value provided for 'existing_backup_kms_key_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + "value": "^__NULL__$|^^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" } ] }, @@ -457,12 +457,19 @@ { "type": "regex", "description": "The value provided for 'existing_postgresql_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}databases-for-postgresql:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, { - "key": "remote_leader_crn" + "key": "remote_leader_crn", + "value_constraints": [ + { + "type": "regex", + "description": "The value provided for 'remote_leader_crn' is not valid.", + "value": "^__NULL__$|^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + } + ] } ], "terraform_version": "1.12.2", @@ -722,7 +729,7 @@ { "type": "regex", "description": "The value provided for 'existing_secrets_manager_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}secrets-manager:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}{3}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, @@ -757,7 +764,7 @@ { "type": "regex", "description": "The value provided for 'existing_kms_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, @@ -767,7 +774,7 @@ { "type": "regex", "description": "The value provided for 'existing_kms_key_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" } ] }, @@ -783,7 +790,7 @@ { "type": "regex", "description": "The value provided for 'backup_crn' is not valid.", - "value": "^__NULL__$|^crn:.*:backup:" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:backup:[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$" } ] }, @@ -793,7 +800,7 @@ { "type": "regex", "description": "The value provided for 'existing_backup_kms_key_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" } ] }, @@ -806,7 +813,7 @@ { "type": "regex", "description": "The value provided for 'existing_postgresql_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}databases-for-postgresql:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, @@ -816,7 +823,7 @@ { "type": "regex", "description": "The value provided for 'remote_leader_crn' is not valid.", - "value": "^__NULL__$|^crn:(.*:){3}databases-for-postgresql:(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] } diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 22b894b1..b6ca8828 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -249,12 +249,28 @@ 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 = anytrue([ + var.existing_kms_instance_crn == null, + can(regex("^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)) + ]) + error_message = "The value provided for 'existing_kms_instance_crn' is not valid." + } } 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 = anytrue([ + var.existing_kms_key_crn == null, + can(regex("^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_kms_key_crn)) + ]) + error_message = "The value provided for 'existing_kms_key_crn’ is not valid." + } } variable "kms_endpoint_type" { @@ -297,6 +313,14 @@ 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. 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 = anytrue([ + var.existing_backup_kms_key_crn == null, + can(regex("^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_backup_kms_key_crn)) + ]) + error_message = "The value provided for 'existing_backup_kms_key_crn' is not valid." + } } variable "use_default_backup_encryption_key" { @@ -313,7 +337,7 @@ variable "backup_crn" { validation { condition = anytrue([ var.backup_crn == null, - can(regex("^crn:.*:backup:", var.backup_crn)) + can(regex("^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:backup:[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$", var.backup_crn)) ]) error_message = "backup_crn must be null OR starts with 'crn:' and contains ':backup:'" } @@ -390,6 +414,14 @@ 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 PostgreSQL instance." + + validation { + condition = anytrue([ + var.existing_secrets_manager_instance_crn == null, + can(regex("^crn:v\\d:(.*:){2}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_secrets_manager_instance_crn)) + ]) + error_message = "The value provided for 'existing_secrets_manager_instance_crn' is not valid." + } } variable "existing_secrets_manager_endpoint_type" { diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index d7a67e4e..4c852163 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -206,6 +206,14 @@ 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 = anytrue([ + var.existing_kms_instance_crn == null, + can(regex("^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)) + ]) + error_message = "The value provided for 'existing_kms_instance_crn' is not valid." + } } variable "existing_kms_key_crn" { @@ -220,6 +228,14 @@ variable "existing_kms_key_crn" { ) error_message = "Either existing_kms_key_crn or existing_kms_instance_crn must be set, but not both." } + + validation { + condition = anytrue([ + var.existing_kms_key_crn == null, + can(regex("^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_kms_key_crn)) + ]) + error_message = "The value provided for 'existing_kms_key_crn’ is not valid." + } } variable "skip_postgresql_kms_auth_policy" { @@ -261,7 +277,7 @@ variable "backup_crn" { validation { condition = anytrue([ var.backup_crn == null, - can(regex("^crn:.*:backup:", var.backup_crn)) + can(regex("^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:backup:[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$", var.backup_crn)) ]) error_message = "backup_crn must be null OR starts with 'crn:' and contains ':backup:'" } @@ -327,6 +343,14 @@ 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 PostgreSQL instance." + + validation { + condition = anytrue([ + var.existing_secrets_manager_instance_crn == null, + can(regex("^crn:v\\d:(.*:){2}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_secrets_manager_instance_crn)) + ]) + error_message = "The value provided for 'existing_secrets_manager_instance_crn' is not valid." + } } variable "service_credential_secrets" { From 9d74a68ea6d11385be604d18127be75eade7b7aa Mon Sep 17 00:00:00 2001 From: Arya Girish K Date: Wed, 19 Nov 2025 20:48:18 +0530 Subject: [PATCH 3/4] Updated validation --- solutions/fully-configurable/variables.tf | 16 ++++++++++++++++ solutions/security-enforced/variables.tf | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/solutions/fully-configurable/variables.tf b/solutions/fully-configurable/variables.tf index 68a4a3c2..ea8696d4 100644 --- a/solutions/fully-configurable/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -62,6 +62,14 @@ variable "existing_postgresql_instance_crn" { type = string default = null description = "The CRN of an existing Databases for Postgresql instance. If no value is specified, a new instance is created." + + validation { + condition = anytrue([ + var.existing_postgresql_instance_crn == null, + can(regex("^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_postgresql_instance_crn)) + ]) + error_message = "The value provided for 'existing_postgresql_instance_crn' is not valid." + } } variable "postgresql_version" { @@ -74,6 +82,14 @@ variable "remote_leader_crn" { type = string description = "A CRN of the leader database to make the replica(read-only) deployment. The leader database is created by a database deployment with the same service ID. A read-only replica is set up to replicate all of your data from the leader deployment to the replica deployment by using asynchronous replication. [Learn more](https://cloud.ibm.com/docs/databases-for-postgresql?topic=databases-for-postgresql-read-only-replicas)." default = null + + validation { + condition = anytrue([ + var.remote_leader_crn == null, + can(regex("^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.remote_leader_crn)) + ]) + error_message = "The value provided for 'remote_leader_crn' is not valid." + } } ############################################################################## diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index a183187f..ebf38c76 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -57,6 +57,14 @@ variable "existing_postgresql_instance_crn" { type = string default = null description = "The CRN of an existing Databases for Postgresql instance. If no value is specified, a new instance is created." + + validation { + condition = anytrue([ + var.existing_postgresql_instance_crn == null, + can(regex("^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_postgresql_instance_crn)) + ]) + error_message = "The value provided for 'existing_postgresql_instance_crn' is not valid." + } } variable "postgresql_version" { @@ -69,6 +77,14 @@ variable "remote_leader_crn" { type = string description = "A CRN of the leader database to make the replica(read-only) deployment. The leader database is created by a database deployment with the same service ID. A read-only replica is set up to replicate all of your data from the leader deployment to the replica deployment by using asynchronous replication. [Learn more](https://cloud.ibm.com/docs/databases-for-postgresql?topic=databases-for-postgresql-read-only-replicas)." default = null + + validation { + condition = anytrue([ + var.remote_leader_crn == null, + can(regex("^crn:v\\d:(.*:){2}databases-for-postgresql:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.remote_leader_crn)) + ]) + error_message = "The value provided for 'remote_leader_crn' is not valid." + } } ############################################################################## From 30dae3b55ff8485a3d27d289c23ca6d772a5528f Mon Sep 17 00:00:00 2001 From: Arya Girish K Date: Wed, 19 Nov 2025 22:14:57 +0530 Subject: [PATCH 4/4] fix: Addressed comments --- ibm_catalog.json | 4 ++-- solutions/security-enforced/variables.tf | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ibm_catalog.json b/ibm_catalog.json index e240b14b..be4e6e9a 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -339,7 +339,7 @@ { "type": "regex", "description": "The value provided for 'existing_secrets_manager_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:v\\d:(.*:){2}{3}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, @@ -727,7 +727,7 @@ { "type": "regex", "description": "The value provided for 'existing_secrets_manager_instance_crn' is not valid.", - "value": "^__NULL__$|^crn:v\\d:(.*:){2}{3}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" + "value": "^__NULL__$|^crn:v\\d:(.*:){2}secrets-manager:(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$" } ] }, diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf index ebf38c76..dea21e98 100644 --- a/solutions/security-enforced/variables.tf +++ b/solutions/security-enforced/variables.tf @@ -283,6 +283,14 @@ 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. 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 = anytrue([ + var.existing_backup_kms_key_crn == null, + can(regex("^crn:v\\d:(.*:){2}(kms|hs-crypto):(.*:)([aos]\\/[\\w_\\-]+):[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_backup_kms_key_crn)) + ]) + error_message = "The value provided for 'existing_backup_kms_key_crn' is not valid." + } } variable "backup_crn" {