diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml
index 24b56c2d..f91d0c71 100644
--- a/.catalog-onboard-pipeline.yaml
+++ b/.catalog-onboard-pipeline.yaml
@@ -6,9 +6,17 @@ offerings:
catalog_id: 7df1e4ca-d54c-4fd0-82ce-3d13247308cd
offering_id: 01f5b01a-3650-4acf-aaf3-4790f7cbd422
variations:
- - name: standard
+ - name: fully-configurable
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
+ - 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/cra-config.yaml b/cra-config.yaml
index fbae9039..65c84b39 100644
--- a/cra-config.yaml
+++ b/cra-config.yaml
@@ -1,12 +1,13 @@
# 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"
+ - CRA_TARGET: "solutions/fully-configurable"
CRA_IGNORE_RULES_FILE: "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:1368d2eb-3ed0-4a8b-b09c-2155895f01ea"
- TF_VAR_use_existing_resource_group: true
- TF_VAR_resource_group_name: "geretain-test-redis"
+ TF_VAR_existing_resource_group_name: "geretain-test-rabbitmq"
+ TF_VAR_kms_encryption_enabled: true
TF_VAR_provider_visibility: "public"
+ TF_VAR_prefix: "test"
diff --git a/ibm_catalog.json b/ibm_catalog.json
index e75d17a2..2b462114 100644
--- a/ibm_catalog.json
+++ b/ibm_catalog.json
@@ -17,40 +17,40 @@
"infrastructure as code",
"terraform",
"solution",
- "rabbitmq standard",
"cache",
"in memory"
],
"short_description": "Creates and configures an instance of IBM Cloud Databases for RabbitMQ.",
- "long_description": "This architecture supports creating and configuring an instance of Databases for RabbitMQ with KMS encryption.",
+ "long_description": "This architecture supports creating and configuring an instance of Databases for RabbitMQ with KMS encryption. RabbitMQ routes messages between microservices for modern applications. [Messages for RabbitMQ](https://www.ibm.com/products/messages-for-rabbitmq) makes RabbitMQ even better by managing it for you. Features include high availability, automated backup orchestration, autoscaling, and de-coupled allocation of storage, RAM, and vCPUs. Messages for RabbitMQ pricing is based on underlying disk, RAM, and optional vCPU allocation, as well as backup storage usage. The service is HIPAA-Ready and compliant with PCI-DSS, SOC 1 Type 2, SOC 2 Type 2, ISO 27001, ISO 27017, ISO 27018, ISO 27701, and GDPR. You can also learn more by viewing docs, API docs, and terms.\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-rabbitmq/blob/main/README.md",
"offering_icon_url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-icd-rabbitmq/main/images/rabbitmq_icon.svg",
"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-rabbitmq/issues](https://github.com/terraform-ibm-modules/terraform-ibm-icd-rabbitmq/issues). Please note this product is not supported via the IBM Cloud Support Center.",
"features": [
{
- "title": "Creates an instance of Databases for RabbitMQ",
- "description": "Creates and configures an IBM Cloud Databases for RabbitMQ instance."
+ "title": "KMS encryption",
+ "description": "Provides [KMS encryption](https://cloud.ibm.com/docs/messages-for-rabbitmq?topic=messages-for-rabbitmq-key-protect&interface=ui) for the data that you store in the database, enhancing data security."
},
{
- "title": "Supports KMS encryption",
- "description": "Provides KMS encryption for the data that you store in the database."
+ "title": "Autoscaling",
+ "description": "Provides the [autoscaling](https://cloud.ibm.com/docs/messages-for-rabbitmq?topic=messages-for-rabbitmq-autoscaling&interface=ui) to allow the database to increase resources in response to usage."
},
{
- "title": "Supports autoscaling",
- "description": "Provides the autoscaling to allow the database to increase resources in response to usage."
+ "title": "Access tags",
+ "description": "Attaches access tags to the RabbitMQ 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/messages-for-rabbitmq?topic=messages-for-rabbitmq-backups-for-rabbitmq&interface=ui) using a backup created by a deployment with the same service ID."
}
],
"flavors": [
{
- "label": "Standard",
- "name": "standard",
+ "label": "Fully configurable",
+ "name": "fully-configurable",
+ "index": 1,
"install_type": "fullstack",
- "working_directory": "solutions/standard",
+ "working_directory": "solutions/fully-configurable",
"compliance": {
"authority": "scc-v3",
"profiles": [
@@ -63,9 +63,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": [
@@ -75,17 +76,24 @@
},
{
"role_crns": [
- "crn:v1:bluemix:public:iam::::serviceRole:Manager",
"crn:v1:bluemix:public:iam::::role:Editor"
],
- "service_name": "kms"
+ "service_name": "kms",
+ "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 only required when using HPCS for encryption."
}
],
"architecture": {
"features": [
{
- "title": " Creates an instance of Databases for RabbitMQ",
- "description": "This architecture creates an instance of IBM Cloud Messages for RabbitMQ with KMS encryption. It accepts or creates a resource group, and provides autoscaling rules."
+ "title": " ",
+ "description": "Configured to use IBM secure by default standards, but can be edited to fit your use case."
}
],
"diagrams": [
@@ -95,7 +103,7 @@
"url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-icd-rabbitmq/main/reference-architecture/deployable-architecture-rabbitmq.svg",
"type": "image/svg+xml"
},
- "description": "This architecture supports creating and configuring an instance of Messages for RabbitMQ instance with KMS encryption."
+ "description": "This architecture supports creating and configuring an instance of Messages for RabbitMQ instance with optional KMS encryption."
}
]
},
@@ -105,6 +113,7 @@
},
{
"key": "provider_visibility",
+ "hidden": true,
"options": [
{
"displayname": "private",
@@ -121,21 +130,23 @@
]
},
{
- "key": "use_existing_resource_group"
- },
- {
- "key": "resource_group_name"
+ "key": "existing_resource_group_name",
+ "display_name": "resource_group",
+ "custom_config": {
+ "type": "resource_group",
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "identifier": "rg_name"
+ }
+ }
},
{
"key": "prefix"
},
- {
- "key": "name"
- },
{
"key": "region",
"required": true,
- "default_value": "us-south",
"options": [
{
"displayname": "Chennai (che01)",
@@ -201,6 +212,31 @@
}
]
},
+ {
+ "key": "name"
+ },
+ {
+ "key": "resource_tags",
+ "type": "array",
+ "custom_config": {
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "key": "access_tags",
+ "type": "array",
+ "custom_config": {
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "type": "string"
+ }
+ }
+ },
{
"key": "members"
},
@@ -217,49 +253,93 @@
"key": "member_host_flavor"
},
{
- "key": "service_credential_names"
+ "key": "auto_scaling"
},
{
- "key": "admin_pass"
+ "key": "service_endpoints",
+ "options": [
+ {
+ "displayname": "private",
+ "value": "private"
+ },
+ {
+ "displayname": "public",
+ "value": "public"
+ },
+ {
+ "displayname": "public-and-private",
+ "value": "public-and-private"
+ }
+ ]
},
{
- "key": "users"
+ "key": "service_credential_names"
},
{
- "key": "tags",
+ "key": "service_credential_secrets",
+ "type": "array",
"custom_config": {
+ "type": "textarea",
"grouping": "deployment",
- "original_grouping": "deployment",
- "config_constraints": {
- "type": "string"
- }
+ "original_grouping": "deployment"
}
},
{
- "key": "access_tags",
+ "key": "admin_pass"
+ },
+ {
+ "key": "existing_secrets_manager_instance_crn"
+ },
+ {
+ "key": "existing_secrets_manager_endpoint_type",
+ "hidden": true,
+ "options": [
+ {
+ "displayname": "public",
+ "value": "public"
+ },
+ {
+ "displayname": "private",
+ "value": "private"
+ }
+ ]
+ },
+ {
+ "key": "skip_rabbitmq_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",
"grouping": "deployment",
- "original_grouping": "deployment",
- "config_constraints": {
- "type": "string"
- }
+ "original_grouping": "deployment"
}
},
{
- "key": "use_ibm_owned_encryption_key"
+ "key": "ibmcloud_kms_api_key"
},
{
- "key": "ibmcloud_kms_api_key"
+ "key": "kms_encryption_enabled"
},
{
- "key": "existing_kms_instance_crn",
- "required": true
+ "key": "existing_kms_instance_crn"
},
{
"key": "existing_kms_key_crn"
},
{
"key": "kms_endpoint_type",
+ "hidden": true,
"options": [
{
"displayname": "public",
@@ -278,41 +358,237 @@
"key": "key_name"
},
{
- "key": "auto_scaling"
+ "key": "backup_crn"
},
{
- "key": "existing_secrets_manager_instance_crn"
+ "key": "existing_backup_kms_key_crn"
},
{
- "key": "existing_secrets_manager_endpoint_type",
+ "key": "use_default_backup_encryption_key"
+ },
+ {
+ "key": "skip_rabbitmq_kms_auth_policy"
+ },
+ {
+ "key": "existing_rabbitmq_instance_crn"
+ },
+ {
+ "key": "cbr_rules"
+ }
+ ]
+ },
+ {
+ "label": "Security-enforced",
+ "name": "security-enforced",
+ "index": 2,
+ "install_type": "fullstack",
+ "working_directory": "solutions/security-enforced",
+ "compliance": {
+ "authority": "scc-v3",
+ "profiles": [
+ {
+ "profile_name": "IBM Cloud Framework for Financial Services",
+ "profile_version": "1.7.0"
+ }
+ ]
+ },
+ "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"
+ ],
+ "service_name": "messages-for-rabbitmq"
+ },
+ {
+ "role_crns": [
+ "crn:v1:bluemix:public:iam::::role:Editor"
+ ],
+ "service_name": "kms",
+ "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 only required when using HPCS for encryption."
+ }
+ ],
+ "architecture": {
+ "features": [
+ {
+ "title": " ",
+ "description": "Configured to use IBM secure by default standards that can't be changed."
+ }
+ ],
+ "diagrams": [
+ {
+ "diagram": {
+ "caption": "Messages for RabbitMQ instance on IBM Cloud",
+ "url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-icd-rabbitmq/main/reference-architecture/deployable-architecture-rabbitmq.svg",
+ "type": "image/svg+xml"
+ },
+ "description": "This architecture supports creating and configuring an instance of Messages for RabbitMQ instance with KMS encryption."
+ }
+ ]
+ },
+ "configuration": [
+ {
+ "key": "ibmcloud_api_key"
+ },
+ {
+ "key": "existing_resource_group_name",
+ "display_name": "resource_group",
+ "custom_config": {
+ "type": "resource_group",
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "identifier": "rg_name"
+ }
+ }
+ },
+ {
+ "key": "prefix"
+ },
+ {
+ "key": "region",
+ "required": true,
"options": [
{
- "displayname": "public",
- "value": "public"
+ "displayname": "Chennai (che01)",
+ "value": "che01"
},
{
- "displayname": "private",
- "value": "private"
+ "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": "service_credential_secrets"
+ "key": "rabbitmq_version",
+ "required": true,
+ "options": [
+ {
+ "displayname": "3.13",
+ "value": "3.13"
+ },
+ {
+ "displayname": "4.0",
+ "value": "4.0"
+ }
+ ]
},
{
- "key": "skip_rabbitmq_sm_auth_policy"
+ "key": "name"
},
{
- "key": "skip_rabbitmq_kms_auth_policy"
+ "key": "resource_tags",
+ "type": "array",
+ "custom_config": {
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "type": "string"
+ }
+ }
},
{
- "key": "backup_crn"
+ "key": "access_tags",
+ "type": "array",
+ "custom_config": {
+ "grouping": "deployment",
+ "original_grouping": "deployment",
+ "config_constraints": {
+ "type": "string"
+ }
+ }
},
{
- "key": "existing_backup_kms_key_crn"
+ "key": "members"
},
{
- "key": "use_default_backup_encryption_key"
+ "key": "member_memory_mb"
+ },
+ {
+ "key": "member_cpu_count"
+ },
+ {
+ "key": "member_disk_mb"
+ },
+ {
+ "key": "member_host_flavor"
+ },
+ {
+ "key": "auto_scaling"
+ },
+ {
+ "key": "service_credential_names"
+ },
+ {
+ "key": "service_credential_secrets",
+ "type": "array",
+ "custom_config": {
+ "type": "textarea",
+ "grouping": "deployment",
+ "original_grouping": "deployment"
+ }
+ },
+ {
+ "key": "admin_pass"
+ },
+ {
+ "key": "existing_secrets_manager_instance_crn"
+ },
+ {
+ "key": "skip_rabbitmq_secrets_manager_auth_policy"
},
{
"key": "admin_pass_secrets_manager_secret_group"
@@ -324,10 +600,44 @@
"key": "use_existing_admin_pass_secrets_manager_secret_group"
},
{
- "key": "cbr_rules"
+ "key": "users",
+ "type": "array",
+ "custom_config": {
+ "type": "textarea",
+ "grouping": "deployment",
+ "original_grouping": "deployment"
+ }
+ },
+ {
+ "key": "ibmcloud_kms_api_key"
+ },
+ {
+ "key": "existing_kms_instance_crn",
+ "required": true
+ },
+ {
+ "key": "existing_kms_key_crn"
+ },
+ {
+ "key": "key_ring_name"
+ },
+ {
+ "key": "key_name"
+ },
+ {
+ "key": "backup_crn"
+ },
+ {
+ "key": "existing_backup_kms_key_crn"
+ },
+ {
+ "key": "skip_rabbitmq_kms_auth_policy"
},
{
"key": "existing_rabbitmq_instance_crn"
+ },
+ {
+ "key": "cbr_rules"
}
]
}
diff --git a/reference-architecture/deployable-architecture-rabbitmq.svg b/reference-architecture/deployable-architecture-rabbitmq.svg
index 1071c607..dfed3a1d 100644
--- a/reference-architecture/deployable-architecture-rabbitmq.svg
+++ b/reference-architecture/deployable-architecture-rabbitmq.svg
@@ -1,4 +1,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/solutions/standard/DA-cbr_rules.md b/solutions/fully-configurable/DA-cbr_rules.md
similarity index 99%
rename from solutions/standard/DA-cbr_rules.md
rename to solutions/fully-configurable/DA-cbr_rules.md
index 6ddb077b..abb5e7cb 100644
--- a/solutions/standard/DA-cbr_rules.md
+++ b/solutions/fully-configurable/DA-cbr_rules.md
@@ -37,7 +37,7 @@ The `cbr_rules` input variable allows you to provide a rule for the target servi
### Example Rule For Context-Based Restrictions Configuration
```hcl
-cbr_rules = [
+[
{
"description" : "SCC Instance can be accessed from xyz"
"account_id" : "defc0df06b644a9cabc6e44f55b3880s."
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/fully-configurable/README.md b/solutions/fully-configurable/README.md
new file mode 100644
index 00000000..d5f5803d
--- /dev/null
+++ b/solutions/fully-configurable/README.md
@@ -0,0 +1,3 @@
+# Cloud automation for RabbitMQ (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
new file mode 100644
index 00000000..a8cd4380
--- /dev/null
+++ b/solutions/fully-configurable/catalogValidationValues.json.template
@@ -0,0 +1,9 @@
+{
+ "ibmcloud_api_key": $VALIDATION_APIKEY,
+ "region": "us-south",
+ "resource_tags": $TAGS,
+ "name": $PREFIX,
+ "existing_resource_group_name":"geretain-test-rabbitmq",
+ "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN,
+ "kms_encryption_enabled": true
+}
diff --git a/solutions/standard/main.tf b/solutions/fully-configurable/main.tf
similarity index 78%
rename from solutions/standard/main.tf
rename to solutions/fully-configurable/main.tf
index e3914d17..d41f51fb 100644
--- a/solutions/standard/main.tf
+++ b/solutions/fully-configurable/main.tf
@@ -1,29 +1,29 @@
#######################################################################################################################
# Resource Group
#######################################################################################################################
+locals {
+ prefix = var.prefix != null ? trimspace(var.prefix) != "" ? "${var.prefix}-" : "" : ""
+}
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.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_rabbitmq_instance_crn == null && !var.use_ibm_owned_encryption_key && var.existing_kms_key_crn == null ? true : false # no need to create any KMS resources if passing an existing key, or using IBM owned keys
- rabbitmq_key_name = var.prefix != null ? "${var.prefix}-${var.key_name}" : var.key_name
- rabbitmq_key_ring_name = var.prefix != null ? "${var.prefix}-${var.key_ring_name}" : var.key_ring_name
+ use_ibm_owned_encryption_key = !var.kms_encryption_enabled
+ create_new_kms_key = (
+ var.kms_encryption_enabled &&
+ var.existing_rabbitmq_instance_crn == null &&
+ var.existing_kms_key_crn == null
+ )
+ rabbitmq_key_name = "${local.prefix}${var.key_name}"
+ rabbitmq_key_ring_name = "${local.prefix}${var.key_ring_name}"
}
module "kms" {
@@ -48,7 +48,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.
}
]
}
@@ -92,24 +92,23 @@ 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_rabbitmq_instance_crn == null && !var.skip_rabbitmq_kms_auth_policy && var.ibmcloud_kms_api_key != null && !var.use_ibm_owned_encryption_key
- create_cross_account_backup_kms_auth_policy = var.existing_rabbitmq_instance_crn == null && !var.skip_rabbitmq_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_rabbitmq_kms_auth_policy && var.ibmcloud_kms_api_key != null
+ create_cross_account_backup_kms_auth_policy = var.kms_encryption_enabled && !var.skip_rabbitmq_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.existing_rabbitmq_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_rabbitmq_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_rabbitmq_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_rabbitmq_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.rabbitmq_key_ring_name, local.rabbitmq_key_name)].crn
- kms_key_id = var.existing_rabbitmq_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.rabbitmq_key_ring_name, local.rabbitmq_key_name)].key_id
- kms_region = var.existing_rabbitmq_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_rabbitmq_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_rabbitmq_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_rabbitmq_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_rabbitmq_instance_crn != null ? null : var.existing_kms_key_crn != null ? var.existing_kms_key_crn : module.kms[0].keys[format("%s.%s", local.rabbitmq_key_ring_name, local.rabbitmq_key_name)].crn
+ kms_key_id = !var.kms_encryption_enabled || var.existing_rabbitmq_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.rabbitmq_key_ring_name, local.rabbitmq_key_name)].key_id
+ kms_region = !var.kms_encryption_enabled || var.existing_rabbitmq_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
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_rabbitmq_instance_crn != null || var.use_ibm_owned_encryption_key ? null : var.existing_backup_kms_key_crn
+ backup_kms_key_crn = var.existing_rabbitmq_instance_crn != null || local.use_ibm_owned_encryption_key ? 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
}
@@ -227,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,20 +276,21 @@ data "ibm_database_connection" "existing_connection" {
# Create new instance
module "rabbitmq" {
count = var.existing_rabbitmq_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.name}" : var.name
+ name = "${local.prefix}${var.name}"
region = var.region
rabbitmq_version = var.rabbitmq_version
+ service_endpoints = var.service_endpoints
skip_iam_authorization_policy = var.skip_rabbitmq_kms_auth_policy
- use_ibm_owned_encryption_key = var.use_ibm_owned_encryption_key
+ 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
access_tags = var.access_tags
- tags = var.tags
+ tags = var.resource_tags
admin_pass = local.admin_pass
users = var.users
members = var.members
@@ -317,7 +319,7 @@ locals {
locals {
## Variable validation (approach based on https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400)
- create_sm_auth_policy = var.skip_rabbitmq_sm_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1
+ create_sm_auth_policy = var.skip_rabbitmq_secrets_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1
}
# Parse the Secrets Manager CRN
@@ -362,7 +364,7 @@ locals {
service_credentials_ttl = secret.service_credentials_ttl
service_credential_secret_description = secret.service_credential_secret_description
service_credentials_source_service_role_crn = secret.service_credentials_source_service_role_crn
- service_credentials_source_service_crn = module.rabbitmq[0].crn
+ service_credentials_source_service_crn = local.rabbitmq_crn
secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6
}
]
@@ -371,10 +373,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
}
diff --git a/solutions/standard/outputs.tf b/solutions/fully-configurable/outputs.tf
similarity index 100%
rename from solutions/standard/outputs.tf
rename to solutions/fully-configurable/outputs.tf
diff --git a/solutions/fully-configurable/provider.tf b/solutions/fully-configurable/provider.tf
new file mode 100644
index 00000000..e66dac2c
--- /dev/null
+++ b/solutions/fully-configurable/provider.tf
@@ -0,0 +1,14 @@
+provider "ibm" {
+ 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
+ private_endpoint_type = (var.provider_visibility == "private" && var.region == "ca-mon") ? "vpe" : null
+}
diff --git a/solutions/standard/variables.tf b/solutions/fully-configurable/variables.tf
similarity index 74%
rename from solutions/standard/variables.tf
rename to solutions/fully-configurable/variables.tf
index 7e6e492e..aefad033 100644
--- a/solutions/standard/variables.tf
+++ b/solutions/fully-configurable/variables.tf
@@ -7,21 +7,38 @@ variable "ibmcloud_api_key" {
description = "The IBM Cloud API key to deploy resources."
sensitive = true
}
-variable "use_existing_resource_group" {
- type = bool
- description = "Whether to use an existing resource group."
- default = false
-}
-variable "resource_group_name" {
+variable "existing_resource_group_name" {
type = string
- description = "The name of a new or an existing resource group to provision the Databases for RabbitMQ in. If a prefix input variable is specified, the prefix is added to the name in the `-` format."
+ description = "The name of an existing resource group to provision the Databases for RabbitMQ in."
+ default = "Default"
}
variable "prefix" {
type = string
- description = "Prefix to add to all resources created by this solution."
- default = null
+ 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 {
+ # - null and empty string is allowed
+ # - Must not contain consecutive hyphens (--): length(regexall("--", var.prefix)) == 0
+ # - Starts with a lowercase letter: [a-z]
+ # - Contains only lowercase letters (a–z), digits (0–9), and hyphens (-)
+ # - Must not end with a hyphen (-): [a-z0-9]
+ condition = (var.prefix == null || var.prefix == "" ? true :
+ alltrue([
+ can(regex("^[a-z][-a-z0-9]*[a-z0-9]$", var.prefix)),
+ length(regexall("--", var.prefix)) == 0
+ ])
+ )
+ error_message = "Prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It must not end with a hyphen('-'), and cannot contain consecutive hyphens ('--')."
+ }
+
+ validation {
+ # must not exceed 16 characters in length
+ condition = length(var.prefix) <= 16
+ error_message = "Prefix must not exceed 16 characters."
+ }
}
variable "name" {
@@ -31,7 +48,7 @@ variable "name" {
}
variable "region" {
- description = "The region where you want to deploy your instance."
+ 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"
@@ -41,22 +58,33 @@ variable "region" {
}
}
-variable "rabbitmq_version" {
- description = "The version of the Databases for RabbitMQ instance. If no value is specified, the current preferred version of Databases for RabbitMQ is used."
+variable "existing_rabbitmq_instance_crn" {
type = string
default = null
+ description = "The CRN of an existing Messages for RabbitMQ instance. If no value is specified, a new instance is created."
}
-variable "existing_rabbitmq_instance_crn" {
+variable "rabbitmq_version" {
+ description = "The version of the Messages for RabbitMQ instance."
type = string
default = null
- description = "The CRN of an existing Messages for RabbitMQ instance. If no value is specified, a new instance is created."
}
##############################################################################
# ICD hosting model properties
##############################################################################
+variable "service_endpoints" {
+ type = string
+ description = "The type of endpoint of the database instance. Possible values: `public`, `private`, `public-and-private`."
+ default = "private"
+
+ validation {
+ 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'"
+ }
+}
+
variable "members" {
type = number
description = "The number of members that are allocated. [Learn more](https://cloud.ibm.com/docs/messages-for-rabbitmq?topic=messages-for-rabbitmq-resources-scaling)."
@@ -95,7 +123,7 @@ variable "service_credential_names" {
variable "admin_pass" {
type = string
- description = "The password for the database administrator. If the admin password is null then the admin user ID cannot be accessed. More users can be specified 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
}
@@ -112,15 +140,15 @@ variable "users" {
description = "A list of users that you want to create on the database. Users block is supported by RabbitMQ version >= 6.0. 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 RabbitMQ instance. This blocks creates native RabbitMQ database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-rabbitmq/blob/main/solutions/standard/DA-types.md#users)"
}
-variable "tags" {
+variable "resource_tags" {
type = list(any)
- description = "The list of tags to be added to the Databases for RabbitMQ instance."
+ description = "The list of tags to be added to the Messages for RabbitMQ instance."
default = []
}
variable "access_tags" {
type = list(string)
- description = "A list of access tags to apply to the Databases for RabbitMQ instance created by the solution. [Learn more](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)."
+ description = "A list of access tags to apply to the Messages for RabbitMQ instance created by the solution. [Learn more](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)."
default = []
}
@@ -128,45 +156,36 @@ variable "access_tags" {
# Encryption
##############################################################
-variable "use_ibm_owned_encryption_key" {
+variable "kms_encryption_enabled" {
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."
+ 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
- # this validation ensures IBM-owned key is not used when KMS details are provided
validation {
- condition = (
+ condition = (!var.kms_encryption_enabled ||
var.existing_rabbitmq_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
- ))
+ 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."
+ 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)."
}
- # this validation ensures key info is provided when IBM-owned key is disabled and no RabbitMQ instance is given
validation {
- condition = !(
- var.existing_rabbitmq_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)."
+ 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."
}
}
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
}
@@ -213,7 +232,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
}
@@ -230,6 +249,7 @@ variable "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
@@ -332,7 +352,7 @@ variable "service_credential_secrets" {
}
}
-variable "skip_rabbitmq_sm_auth_policy" {
+variable "skip_rabbitmq_secrets_manager_auth_policy" {
type = bool
description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for RabbitMQ. If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the RabbitMQ 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."
default = false
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..ebf814cd
--- /dev/null
+++ b/solutions/security-enforced/README.md
@@ -0,0 +1,3 @@
+# Cloud automation for RabbitMQ (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/standard/catalogValidationValues.json.template b/solutions/security-enforced/catalogValidationValues.json.template
similarity index 61%
rename from solutions/standard/catalogValidationValues.json.template
rename to solutions/security-enforced/catalogValidationValues.json.template
index e69e502f..a0370e26 100644
--- a/solutions/standard/catalogValidationValues.json.template
+++ b/solutions/security-enforced/catalogValidationValues.json.template
@@ -1,8 +1,8 @@
{
"ibmcloud_api_key": $VALIDATION_APIKEY,
"region": "us-south",
- "tags": $TAGS,
+ "resource_tags": $TAGS,
"name": $PREFIX,
- "resource_group_name": $PREFIX,
+ "existing_resource_group_name": "geretain-test-rabbitmq",
"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..04d50458
--- /dev/null
+++ b/solutions/security-enforced/main.tf
@@ -0,0 +1,42 @@
+module "icd_rabbitmq" {
+ source = "../fully-configurable"
+ prefix = var.prefix
+ ibmcloud_api_key = var.ibmcloud_api_key
+ existing_resource_group_name = var.existing_resource_group_name
+ name = var.name
+ provider_visibility = "private"
+ region = var.region
+ rabbitmq_version = var.rabbitmq_version
+ existing_rabbitmq_instance_crn = var.existing_rabbitmq_instance_crn
+ service_endpoints = "private"
+ 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
+ kms_encryption_enabled = true
+ existing_kms_instance_crn = var.existing_kms_instance_crn
+ existing_kms_key_crn = var.existing_kms_key_crn
+ kms_endpoint_type = "private"
+ skip_rabbitmq_kms_auth_policy = var.skip_rabbitmq_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"
+ backup_crn = var.backup_crn
+ auto_scaling = var.auto_scaling
+ 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_rabbitmq_secrets_manager_auth_policy = var.skip_rabbitmq_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
+ cbr_rules = var.cbr_rules
+}
diff --git a/solutions/standard/moved.tf b/solutions/security-enforced/moved.tf
similarity index 100%
rename from solutions/standard/moved.tf
rename to solutions/security-enforced/moved.tf
diff --git a/solutions/security-enforced/outputs.tf b/solutions/security-enforced/outputs.tf
new file mode 100644
index 00000000..a2c7c8c0
--- /dev/null
+++ b/solutions/security-enforced/outputs.tf
@@ -0,0 +1,56 @@
+##############################################################################
+# Outputs
+##############################################################################
+
+output "id" {
+ description = "RabbitMQ instance id"
+ value = module.icd_rabbitmq.id
+}
+
+output "version" {
+ description = "RabbitMQ instance version"
+ value = module.icd_rabbitmq.version
+}
+
+output "guid" {
+ description = "RabbitMQ instance guid"
+ value = module.icd_rabbitmq.guid
+}
+
+output "crn" {
+ description = "RabbitMQ instance crn"
+ value = module.icd_rabbitmq.crn
+}
+
+output "service_credentials_json" {
+ description = "Service credentials json map"
+ value = module.icd_rabbitmq.service_credentials_json
+ sensitive = true
+}
+
+output "service_credentials_object" {
+ description = "Service credentials object"
+ value = module.icd_rabbitmq.service_credentials_object
+ sensitive = true
+}
+
+output "hostname" {
+ description = "Database connection hostname"
+ value = module.icd_rabbitmq.hostname
+}
+
+output "port" {
+ description = "Database connection port"
+ value = module.icd_rabbitmq.port
+}
+
+output "secrets_manager_secrets" {
+ description = "Service credential secrets"
+ value = module.icd_rabbitmq.secrets_manager_secrets
+}
+
+output "admin_pass" {
+ description = "RabbitMQ administrator password"
+ value = module.icd_rabbitmq.admin_pass
+ sensitive = true
+}
diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf
new file mode 100644
index 00000000..298a0d9e
--- /dev/null
+++ b/solutions/security-enforced/variables.tf
@@ -0,0 +1,352 @@
+##############################################################################
+# Input Variables
+##############################################################################
+
+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 RabbitMQ in."
+ default = "Default"
+}
+
+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)."
+
+ validation {
+ # - null and empty string is allowed
+ # - Must not contain consecutive hyphens (--): length(regexall("--", var.prefix)) == 0
+ # - Starts with a lowercase letter: [a-z]
+ # - Contains only lowercase letters (a–z), digits (0–9), and hyphens (-)
+ # - Must not end with a hyphen (-): [a-z0-9]
+ condition = (var.prefix == null || var.prefix == "" ? true :
+ alltrue([
+ can(regex("^[a-z][-a-z0-9]*[a-z0-9]$", var.prefix)),
+ length(regexall("--", var.prefix)) == 0
+ ])
+ )
+ error_message = "Prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It must not end with a hyphen('-'), and cannot contain consecutive hyphens ('--')."
+ }
+
+ validation {
+ # must not exceed 16 characters in length
+ condition = length(var.prefix) <= 16
+ error_message = "Prefix must not exceed 16 characters."
+ }
+}
+
+variable "name" {
+ type = string
+ description = "The name of the Databases for RabbitMQ instance. If a prefix input variable is specified, the prefix is added to the name in the `-` format."
+ default = "rabbitmq"
+}
+
+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."
+ type = string
+ default = "us-south"
+}
+
+variable "existing_rabbitmq_instance_crn" {
+ type = string
+ default = null
+ description = "The CRN of an existing Messages for RabbitMQ instance. If no value is specified, a new instance is created."
+}
+
+variable "rabbitmq_version" {
+ description = "The version of the Messages for RabbitMQ instance."
+ type = string
+ default = null
+}
+
+##############################################################################
+# ICD hosting model properties
+##############################################################################
+
+variable "members" {
+ type = number
+ description = "The number of members that are allocated. [Learn more](https://cloud.ibm.com/docs/messages-for-rabbitmq?topic=messages-for-rabbitmq-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/messages-for-rabbitmq?topic=messages-for-rabbitmq-resources-scaling)"
+ default = 8192
+}
+
+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/messages-for-rabbitmq?topic=messages-for-rabbitmq-resources-scaling)."
+ default = 0
+}
+
+variable "member_disk_mb" {
+ type = number
+ description = "The disk that is allocated per member. [Learn more](https://cloud.ibm.com/docs/messages-for-rabbitmq?topic=messages-for-rabbitmq-resources-scaling)."
+ default = 1024
+}
+
+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 = "multitenant"
+}
+
+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-rabbitmq/blob/main/solutions/standard/DA-types.md#svc-credential-name)"
+ type = map(string)
+ default = {}
+}
+
+variable "admin_pass" {
+ type = string
+ 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
+}
+
+variable "users" {
+ type = list(object({
+ name = string
+ password = string # pragma: allowlist secret
+ type = string # "type" is required to generate the connection string for the outputs.
+ role = optional(string)
+ }))
+ default = []
+ sensitive = true
+ description = "A list of users that you want to create on the database. Users block is supported by RabbitMQ version >= 6.0. 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 RabbitMQ instance. This blocks creates native RabbitMQ database users. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-rabbitmq/blob/main/solutions/standard/DA-types.md#users)"
+}
+
+variable "resource_tags" {
+ type = list(any)
+ description = "The list of resource tags to be added to the Messages for RabbitMQ instance."
+ default = []
+}
+
+variable "access_tags" {
+ type = list(string)
+ description = "A list of access tags to apply to the Messages for RabbitMQ instance created by the solution. [Learn more](https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial)."
+ default = []
+}
+
+##############################################################
+# 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. 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, var.existing_kms_key_crn == null])
+ error_message = "Either an existing_kms_instance_crn or an existing_kms_key_crn needs to be provided."
+ }
+}
+
+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
+}
+
+variable "skip_rabbitmq_kms_auth_policy" {
+ type = bool
+ description = "Whether to create an IAM authorization policy that permits all Databases for RabbitMQ 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 RabbitMQ instance. Leave this input empty if the same account owns both instances."
+ sensitive = true
+ default = null
+}
+
+variable "key_ring_name" {
+ type = string
+ default = "rabbitmq-key-ring"
+ description = "The name for the key ring created for the Databases for RabbitMQ 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 = "rabbitmq-key"
+ description = "The name for the key created for the Databases for RabbitMQ 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)."
+ default = null
+}
+
+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:'"
+ }
+}
+
+##############################################################
+# 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 = "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-rabbitmq/blob/main/solutions/standard/DA-types.md#autoscaling)"
+ 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 RabbitMQ instance."
+}
+
+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 RabbitMQ. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-icd-rabbitmq/tree/main/solutions/standard/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
+ )
+ error_message = "`existing_secrets_manager_instance_crn` is required when adding service credentials to a secrets manager secret."
+ }
+}
+
+variable "skip_rabbitmq_secrets_manager_auth_policy" {
+ type = bool
+ description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Databases for RabbitMQ. If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the RabbitMQ 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."
+ default = false
+}
+
+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 = "rabbitmq-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" {
+ 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 rabbitmq administrator secret. If a prefix input variable is specified, the prefix is added to the name in the `-` format."
+ default = "rabbitmq-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."
+ }
+}
+
+##############################################################
+# 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
+ tags = optional(list(object({
+ name = string
+ value = string
+ })))
+ operations = optional(list(object({
+ api_types = list(object({
+ api_type_id = string
+ }))
+ })))
+ }))
+ description = "(Optional, list) List of context-based restrictions rules to create."
+ default = []
+}
diff --git a/solutions/security-enforced/version.tf b/solutions/security-enforced/version.tf
new file mode 100644
index 00000000..2d5c091d
--- /dev/null
+++ b/solutions/security-enforced/version.tf
@@ -0,0 +1,5 @@
+terraform {
+ required_version = ">= 1.9.0"
+ # Lock DA into an exact provider version - renovate automation will keep it updated
+ required_providers {}
+}
diff --git a/solutions/standard/README.md b/solutions/standard/README.md
deleted file mode 100644
index 04b4a86a..00000000
--- a/solutions/standard/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
- # IBM Cloud Databases for RabbitMQ
-
-This architecture creates an instance of IBM Cloud Databases for RabbitMQ 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 RabbitMQ instance with KMS encryption.
-- Autoscaling rules for the database instance, if provided.
-- Service credential secrets and store them in secret manager.
-
-
-
-: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/standard/provider.tf b/solutions/standard/provider.tf
deleted file mode 100644
index 65c38f7d..00000000
--- a/solutions/standard/provider.tf
+++ /dev/null
@@ -1,11 +0,0 @@
-provider "ibm" {
- ibmcloud_api_key = var.ibmcloud_api_key
- region = var.region
- visibility = var.provider_visibility
-}
-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
-}
diff --git a/tests/other_test.go b/tests/other_test.go
index 778c1117..b063765c 100644
--- a/tests/other_test.go
+++ b/tests/other_test.go
@@ -27,7 +27,7 @@ func TestRunCompleteExample(t *testing.T) {
options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{
Testing: t,
TerraformDir: completeExampleTerraformDir,
- Prefix: "rabbitmq-upg",
+ Prefix: "rmq-upg",
BestRegionYAMLPath: regionSelectionPath,
ResourceGroup: resourceGroup,
TerraformVars: map[string]interface{}{
@@ -86,7 +86,7 @@ func TestRunRestoredDBExample(t *testing.T) {
options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{
Testing: t,
TerraformDir: "examples/backup-restore",
- Prefix: "rabbitmq-restored",
+ Prefix: "rmq-restored",
ResourceGroup: resourceGroup,
Region: fmt.Sprint(permanentResources["rabbitmqRegion"]),
TerraformVars: map[string]interface{}{
diff --git a/tests/pr_test.go b/tests/pr_test.go
index b3a1b3ae..2df5d794 100644
--- a/tests/pr_test.go
+++ b/tests/pr_test.go
@@ -24,9 +24,9 @@ import (
"github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testschematic"
)
-const standardSolutionTerraformDir = "solutions/standard"
+const fullyConfigurableSolutionTerraformDir = "solutions/fully-configurable"
+const securityEnforcedTerraformDir = "solutions/security-enforced"
const completeExampleTerraformDir = "examples/complete"
-const fscloudExampleTerraformDir = "examples/fscloud"
const earliestVersion = "3.13"
const latestVersion = "4.0"
@@ -60,21 +60,19 @@ 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: "rabbitmq-st-da",
+ Prefix: "rbtmq-da",
ResourceGroup: resourceGroup,
DeleteWorkspaceOnFail: false,
WaitJobCompleteMinutes: 60,
@@ -109,40 +107,41 @@ 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: "prefix", Value: options.Prefix, DataType: "string"},
{Name: "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_encryption_enabled", Value: true, DataType: "bool"},
{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: "rabbitmq_version", Value: latestVersion, DataType: "string"}, // Always lock this test into the latest supported RabbitMQ version
{Name: "service_credential_names", Value: string(serviceCredentialNamesJSON), 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: "admin_pass_secrets_manager_secret_group", Value: options.Prefix, DataType: "string"},
- {Name: "admin_pass_secrets_manager_secret_name", Value: options.Prefix, DataType: "string"},
}
err = options.RunSchematicTest()
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: "rabbitmq-st-da-upg",
+ Prefix: "rmq-upg",
ResourceGroup: resourceGroup,
})
options.TerraformVars = map[string]any{
- "access_tags": permanentResources["accessTags"],
- "existing_kms_instance_crn": permanentResources["hpcs_south_crn"],
- "kms_endpoint_type": "public",
- "provider_visibility": "public",
- "resource_group_name": options.Prefix,
+ "prefix": options.Prefix,
+ "access_tags": permanentResources["accessTags"],
+ "existing_kms_instance_crn": permanentResources["hpcs_south_crn"],
+ "kms_encryption_enabled": true,
+ "kms_endpoint_type": "public",
+ "provider_visibility": "public",
+ "existing_resource_group_name": resourceGroup,
}
output, err := options.RunTestUpgrade()
@@ -152,11 +151,74 @@ func TestRunStandardUpgradeSolution(t *testing.T) {
}
}
+func TestRunSecurityEnforcedSchematics(t *testing.T) {
+ t.Parallel()
+
+ options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{
+ Testing: t,
+ TarIncludePatterns: []string{
+ "*.tf",
+ fmt.Sprintf("%s/*.tf", fullyConfigurableSolutionTerraformDir),
+ fmt.Sprintf("%s/*.tf", securityEnforcedTerraformDir),
+ fmt.Sprintf("%s/*.sh", "scripts"),
+ },
+ TemplateFolder: securityEnforcedTerraformDir,
+ BestRegionYAMLPath: regionSelectionPath,
+ Prefix: "rmq-sec",
+ ResourceGroup: resourceGroup,
+ DeleteWorkspaceOnFail: false,
+ WaitJobCompleteMinutes: 60,
+ })
+
+ serviceCredentialSecrets := []map[string]any{
+ {
+ "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",
+ },
+ },
+ },
+ }
+
+ serviceCredentialNames := map[string]string{
+ "admin": "Administrator",
+ "user1": "Viewer",
+ "user2": "Editor",
+ }
+
+ serviceCredentialNamesJSON, err := json.Marshal(serviceCredentialNames)
+ if err != nil {
+ log.Fatalf("Error converting to JSON: %s", err)
+ }
+
+ options.TerraformVars = []testschematic.TestSchematicTerraformVar{
+ {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true},
+ {Name: "prefix", Value: options.Prefix, DataType: "string"},
+ {Name: "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: "existing_resource_group_name", Value: resourceGroup, DataType: "string"},
+ {Name: "rabbitmq_version", Value: latestVersion, DataType: "string"}, // Always lock this test into the latest supported RabbitMQ version
+ {Name: "service_credential_names", Value: string(serviceCredentialNamesJSON), 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"},
+ }
+ err = options.RunSchematicTest()
+ assert.Nil(t, err, "This should not have errored")
+}
+
func TestPlanValidation(t *testing.T) {
options := testhelper.TestOptionsDefault(&testhelper.TestOptions{
Testing: t,
- TerraformDir: standardSolutionTerraformDir,
- Prefix: "validate-plan",
+ TerraformDir: fullyConfigurableSolutionTerraformDir,
+ Prefix: "val-plan",
ResourceGroup: resourceGroup,
Region: "us-south", // skip VPC region picker
})
@@ -164,28 +226,29 @@ func TestPlanValidation(t *testing.T) {
options.TerraformOptions.NoColor = true
options.TerraformOptions.Logger = logger.Discard
options.TerraformOptions.Vars = map[string]any{
- "prefix": options.Prefix,
- "region": "us-south",
- "rabbitmq_version": earliestVersion,
- "provider_visibility": "public",
- "resource_group_name": options.Prefix,
+ "prefix": options.Prefix,
+ "region": "us-south",
+ "rabbitmq_version": earliestVersion,
+ "provider_visibility": "public",
+ "existing_resource_group_name": resourceGroup,
}
// Test the DA when using an existing KMS instance
- var standardSolutionWithExistingKms = map[string]any{
+ var fullyConfigurableSolutionWithExistingKms = map[string]any{
"access_tags": permanentResources["accessTags"],
"existing_kms_instance_crn": permanentResources["hpcs_south_crn"],
+ "kms_encryption_enabled": true,
}
// Test the DA when using IBM owned encryption key
- var standardSolutionWithUseIbmOwnedEncKey = map[string]any{
- "use_ibm_owned_encryption_key": true,
+ var fullyConfigurableWithUseIbmOwnedEncKey = map[string]any{
+ "kms_encryption_enabled": false,
}
// Create a map of the variables
tfVarsMap := map[string]map[string]any{
- "standardSolutionWithExistingKms": standardSolutionWithExistingKms,
- "standardSolutionWithUseIbmOwnedEncKey": standardSolutionWithUseIbmOwnedEncKey,
+ "fullyConfigurableSolutionWithExistingKms": fullyConfigurableSolutionWithExistingKms,
+ "fullyConfigurableWithUseIbmOwnedEncKey": fullyConfigurableWithUseIbmOwnedEncKey, //pragma: allowlist secret
}
_, initErr := terraform.InitE(t, options.TerraformOptions)
@@ -233,6 +296,7 @@ func TestRunExistingInstance(t *testing.T) {
Vars: map[string]any{
"prefix": prefix,
"region": region,
+ "resource_group": resourceGroup,
"rabbitmq_version": latestVersion,
"service_endpoints": "public-and-private",
},
@@ -251,14 +315,12 @@ func TestRunExistingInstance(t *testing.T) {
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: "rabbitmq-da",
+ Prefix: "rmq-da-ex",
ResourceGroup: resourceGroup,
DeleteWorkspaceOnFail: false,
WaitJobCompleteMinutes: 60,
@@ -266,10 +328,10 @@ func TestRunExistingInstance(t *testing.T) {
options.TerraformVars = []testschematic.TestSchematicTerraformVar{
{Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true},
+ {Name: "prefix", Value: options.Prefix, DataType: "string"},
{Name: "existing_rabbitmq_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "rabbitmq_crn"), DataType: "string"},
- {Name: "resource_group_name", Value: fmt.Sprintf("%s-resource-group", prefix), DataType: "string"},
+ {Name: "existing_resource_group_name", Value: resourceGroup, 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()