diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml index da3e88c0..fc4f3f47 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: c7ac3ee6-4f48-4236-b974-b0cd8c624a46 variations: - - name: standard + - 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 + - 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 diff --git a/.secrets.baseline b/.secrets.baseline index 6ba41d81..ef628661 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2023-12-14T05:17:42Z", + "generated_at": "2025-05-07T17:56:08Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -77,7 +77,7 @@ } ], "results": { - "solutions/standard/DA-types.md": [ + "solutions/fully-configurable/DA-types.md": [ { "hashed_secret": "1e5c2f367f02e47a8c160cda1cd9d91decbac441", "is_secret": false, @@ -86,6 +86,26 @@ "type": "Secret Keyword", "verified_result": null } + ], + "solutions/fully-configurable/README.md": [ + { + "hashed_secret": "99046450b7d19bfd57bfe3773719f57af84c7f12", + "is_secret": false, + "is_verified": false, + "line_number": 91, + "type": "Secret Keyword", + "verified_result": null + } + ], + "solutions/security-enforced/README.md": [ + { + "hashed_secret": "99046450b7d19bfd57bfe3773719f57af84c7f12", + "is_secret": false, + "is_verified": false, + "line_number": 67, + "type": "Secret Keyword", + "verified_result": null + } ] }, "version": "0.13.1+ibm.62.dss", diff --git a/common-dev-assets b/common-dev-assets index e0e7dbe4..98689194 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit e0e7dbe46b41b888a617ec7f7e574af3b26a4349 +Subproject commit 986891949784c26319860f021aaa626616a76d78 diff --git a/cra-config.yaml b/cra-config.yaml index e709426a..48cb9ae0 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -1,12 +1,16 @@ # More info about this file at https://github.com/terraform-ibm-modules/common-pipeline-assets/blob/main/.github/workflows/terraform-test-pipeline.md#cra-config-yaml version: "v1" CRA_TARGETS: - - CRA_TARGET: "solutions/standard" # Target directory for CRA scan. If not provided, the CRA Scan will not be run. + - CRA_TARGET: "solutions/fully-configurable" # Target directory for CRA scan. If not provided, the CRA Scan will not be run. CRA_IGNORE_RULES_FILE: "cra-tf-validate-ignore-rules.json" # CRA Ignore file to use. If not provided, it checks the repo root directory for `cra-tf-validate-ignore-rules.json` PROFILE_ID: "fe96bd4d-9b37-40f2-b39f-a62760e326a3" # SCC profile ID (currently set to 'IBM Cloud Framework for Financial Services' '1.7.0' profile). CRA_ENVIRONMENT_VARIABLES: - TF_VAR_resource_group_name: "test" + TF_VAR_prefix: "test" + TF_VAR_existing_resource_group_name: "Default" TF_VAR_existing_kms_instance_crn: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" TF_VAR_kms_endpoint_url: "https://e6dce284-e80f-46e1-a3c1-830f7adff7a9.api.private.us-south.hs-crypto.appdomain.cloud" + TF_VAR_existing_cos_instance_crn: "crn:v1:bluemix:public:cloud-object-storage:global:a/abac0df06b644a9cabc6e44f55b3880e:855ed836-05ce-4f39-98fa-508774f29323::" TF_VAR_cross_region_location: "us" TF_VAR_provider_visibility: "public" + TF_VAR_kms_encryption_enabled: true + TF_VAR_enable_collecting_failed_events: true diff --git a/examples/fscloud/version.tf b/examples/fscloud/version.tf index 5d80ef7c..625a5863 100644 --- a/examples/fscloud/version.tf +++ b/examples/fscloud/version.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0" + required_version = ">= 1.9.0" # Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main # module's version.tf (usually a basic example), and 1 example that will always use the latest provider version. diff --git a/ibm_catalog.json b/ibm_catalog.json index 1f3aadc6..153c8a7f 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -9,11 +9,12 @@ "target_terraform", "terraform", "solution", - "dev_ops" + "security" ], "keywords": [ "events", "notifications", + "event notifications", "events-notifications", "IaC", "infrastructure as code", @@ -21,7 +22,7 @@ "solution" ], "short_description": "Creates and configures an IBM Cloud Event Notifications instance.", - "long_description": "This architecture supports creating and configuring an IBM Cloud Event Notifications instance.", + "long_description": "This deployable architecture is used to provision and configure an [IBM Cloud Event Notifications](https://www.ibm.com/products/event-notifications) instance.\n\n\n💡 This Terraform-based automation is part of a broader suite of IBM-maintained Infrastructure as Code (IaC) asset collection, each following the naming pattern \"Cloud automation for *servicename*\" and focusing on single IBM Cloud service. These single-service deployable architectures can be used on their own to streamline and automate service deployments through an [IaC approach](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-understanding-projects), or assembled together into a broader [automated IaC stack](https://cloud.ibm.com/docs/secure-enterprise?topic=secure-enterprise-config-stack) to automate the deployment of an end-to-end solution architecture.", "offering_docs_url": "https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/blob/main/solutions/standard/README.md", "offering_icon_url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-event-notifications/main/images/en_icon.svg", "provider_name": "IBM", @@ -42,10 +43,10 @@ "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 that repository [https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/issues](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/issues). Please note this product is not supported via the IBM Cloud Support Center.", "flavors": [ { - "label": "Standard", - "name": "standard", + "label": "Security-enforced", + "name": "security-enforced", "install_type": "fullstack", - "working_directory": "solutions/standard", + "working_directory": "solutions/security-enforced", "compliance": { "authority": "scc-v3", "profiles": [ @@ -64,49 +65,212 @@ "required": true }, { - "key": "use_existing_resource_group" + "key": "existing_resource_group_name", + "required": true, + "custom_config": { + "type": "resource_group", + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "identifier": "rg_name" + } + } + }, + { + "key": "region", + "required": true, + "options": [ + { + "value": "au-syd" + }, + { + "value": "eu-de" + }, + { + "value": "eu-gb" + }, + { + "value": "eu-es" + }, + { + "value": "us-south" + } + ] + }, + { + "key": "existing_kms_instance_crn", + "required": true + }, + { + "key": "kms_endpoint_url", + "required": true + }, + { + "key": "event_notifications_instance_name" + }, + { + "key": "event_notifications_resource_tags" + }, + { + "key": "existing_kms_root_key_crn" + }, + { + "key": "event_notifications_key_ring_name" + }, + { + "key": "event_notifications_key_name" + }, + { + "key": "cos_key_name" + }, + { + "key": "skip_event_notifications_kms_auth_policy" + }, + { + "key": "ibmcloud_kms_api_key" + }, + { + "key": "existing_cos_instance_crn" + }, + { + "key": "cos_bucket_name" + }, + { + "key": "skip_event_notifications_cos_auth_policy" + }, + { + "key": "skip_cos_kms_auth_policy" + }, + { + "key": "cos_bucket_access_tags" + }, + { + "key": "add_bucket_name_suffix" + }, + { + "key": "cos_bucket_region" + }, + { + "key": "existing_secrets_manager_instance_crn" + }, + { + "key": "skip_event_notifications_secrets_manager_auth_policy" + }, + { + "key": "service_credential_secrets" + }, + { + "key": "service_credential_names" + }, + { + "key": "existing_event_notifications_instance_crn" + }, + { + "key":"cbr_rules" + } + ], + "iam_permissions": [ + { + "role_crns": [ + "crn:v1:bluemix:public:iam::::serviceRole:Manager", + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "service_name": "event-notifications" + } + ], + "architecture": { + "descriptions": "This architecture supports creating and configuring an IBM Cloud Event Notifications instance.", + "features": [ + { + "title": "Creates an Event Notifications instance", + "description": "Creates and configures an Event Notifications instance." + }, + { + "title": "Creates key rings and keys", + "description": "Creates key rings and keys in an existing KMS instance." + }, + { + "title": "Collects events that fail delivery", + "description": "Connect an existing Object Storage service instance and bucket. Alternatively, create instances to connect to an Event Notifications instance and collect events that faile delivery." + } + ], + "diagrams": [ + { + "diagram": { + "caption": "IBM Cloud Event Notifications", + "url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-event-notifications/main/reference-architectures/en.svg", + "type": "image/svg+xml" + }, + "description": "This architecture supports creating and configuring an IBM Cloud Event Notifications instance." + } + ] + } + }, + { + "label": "Fully configurable", + "name": "fully-configurable", + "install_type": "fullstack", + "working_directory": "solutions/fully-configurable", + "compliance": { + "authority": "scc-v3", + "profiles": [ + { + "profile_name": "IBM Cloud Framework for Financial Services", + "profile_version": "1.7.0" + } + ] + }, + "configuration": [ + { + "key": "ibmcloud_api_key" + }, + { + "key": "prefix", + "required": true }, { - "key": "resource_group_name" + "key": "existing_resource_group_name", + "required": true, + "custom_config": { + "type": "resource_group", + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "identifier": "rg_name" + } + } }, { "key": "region", "required": true, "options": [ { - "displayname": "Sydney (au-syd)", "value": "au-syd" }, { - "displayname": "Frankfurt (eu-de)", "value": "eu-de" }, { - "displayname": "London (eu-gb)", "value": "eu-gb" }, { - "displayname": "Madrid (eu-es)", "value": "eu-es" }, { - "displayname": "Dallas (us-south)", "value": "us-south" } ] }, { - "key": "event_notification_name" + "key": "event_notifications_instance_name" }, { "key": "service_plan", "options": [ { - "displayname": "lite", "value": "lite" }, { - "displayname": "standard", "value": "standard" } ] @@ -115,42 +279,30 @@ "key": "service_endpoints", "options": [ { - "displayname": "public", "value": "public" }, { - "displayname": "public-and-private", "value": "public-and-private" } ] }, { - "key": "tags" + "key": "event_notifications_resource_tags" }, { - "key": "existing_kms_instance_crn", - "required": true + "key": "event_notifications_access_tags" }, { - "key": "kms_endpoint_url", - "required": true + "key": "existing_event_notifications_instance_crn" }, { - "key": "provider_visibility", - "options": [ - { - "displayname": "private", - "value": "private" - }, - { - "displayname": "public", - "value": "public" - }, - { - "displayname": "public-and-private", - "value": "public-and-private" - } - ] + "key": "kms_encryption_enabled" + }, + { + "key": "existing_kms_instance_crn" + }, + { + "key": "kms_endpoint_url" }, { "key": "existing_kms_root_key_crn" @@ -159,109 +311,84 @@ "key": "kms_endpoint_type", "options": [ { - "displayname": "public", "value": "public" }, { - "displayname": "private", "value": "private" } ] }, { - "key": "en_key_ring_name" + "key": "provider_visibility", + "hidden": true, + "options": [ + { + "value": "private" + }, + { + "value": "public" + }, + { + "value": "public-and-private" + } + ] }, { - "key": "en_key_name" + "key": "event_notifications_key_name" }, { - "key": "cos_key_ring_name" + "key": "event_notifications_key_ring_name" }, { "key": "cos_key_name" }, { - "key": "skip_en_kms_auth_policy" + "key": "skip_event_notifications_kms_auth_policy" }, { "key": "ibmcloud_kms_api_key" }, { - "key": "existing_cos_instance_crn" + "key" : "enable_collecting_failed_events" }, { - "key": "existing_cos_bucket_name" + "key": "existing_cos_instance_crn" }, { "key": "cos_bucket_name" }, - { - "key": "skip_en_cos_auth_policy" - }, - { - "key": "skip_cos_kms_auth_policy" - }, - { - "key": "cos_instance_name" - }, - { - "key": "cos_instance_tags" - }, - { - "key": "cos_instance_access_tags" - }, { "key": "add_bucket_name_suffix" }, { - "key": "cos_plan", - "options": [ - { - "displayname": "Standard", - "value": "standard" - }, - { - "displayname": "Lite", - "value": "lite" - }, - { - "displayname": "One Rate", - "value": "cos-one-rate-plan" - } - ] + "key": "cos_bucket_class" }, { - "key": "cross_region_location" + "key": "cos_bucket_access_tags" }, { - "key": "cos_bucket_region" + "key": "skip_event_notifications_cos_auth_policy" }, { - "key": "archive_days" + "key": "skip_cos_kms_auth_policy" }, { - "key": "retention_enabled" + "key": "cos_bucket_region" }, { "key": "management_endpoint_type_for_bucket", "options": [ { - "displayname": "private", "value": "private" }, { - "displayname": "public", "value": "public" }, { - "displayname": "direct", "value": "direct" } ] }, - { - "key": "existing_cos_endpoint" - }, { "key": "existing_secrets_manager_instance_crn" }, @@ -269,17 +396,15 @@ "key": "existing_secrets_manager_endpoint_type", "options": [ { - "displayname": "private", "value": "private" }, { - "displayname": "public", "value": "public" } ] }, { - "key": "skip_en_sm_auth_policy" + "key": "skip_event_notifications_secrets_manager_auth_policy" }, { "key": "service_credential_secrets" @@ -287,20 +412,8 @@ { "key": "service_credential_names" }, - { - "key": "existing_monitoring_crn" - }, - { - "key": "existing_en_instance_crn" - }, { "key":"cbr_rules" - }, - { - "key":"archive_filter_prefix" - }, - { - "key":"expire_filter_prefix" } ], "iam_permissions": [ diff --git a/main.tf b/main.tf index 008c0fc3..73645459 100644 --- a/main.tf +++ b/main.tf @@ -1,5 +1,5 @@ ########################################################### -# This file creates an event notificaiton resource instance +# This file creates an Event Notifications resource instance ########################################################### locals { # tflint-ignore: terraform_unused_declarations diff --git a/reference-architectures/en.svg b/reference-architectures/en.svg index 94c5695e..d7b0d9fa 100644 --- a/reference-architectures/en.svg +++ b/reference-architectures/en.svg @@ -1,4 +1,4 @@ - + -
IBM Cloud
IBM Cloud
Region
Region
Resource Group
Resource Group
EventNotifications
 Existing KMS
 Existing KMS
Key Ring
Key Ring
Root Key
COS
COS
Bucket
Bucket
Failed Event
Faile...
....
Text is not SVG - cannot display
+
IBM Cloud
IBM Cloud
Region
Region
Existing Resource Group
Existing Resource Group
EventNotifications
                      (Optional) Existing KMS
(Optional)...
Key Ring
Key Ring
Root Key
                       (Optional) Existing COS
(Optional...
Bucket
Bucket
Failed Event
Faile...
....
Text is not SVG - cannot display
\ 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 100% rename from solutions/standard/DA-cbr_rules.md rename to solutions/fully-configurable/DA-cbr_rules.md diff --git a/solutions/standard/DA-types.md b/solutions/fully-configurable/DA-types.md similarity index 100% rename from solutions/standard/DA-types.md rename to solutions/fully-configurable/DA-types.md diff --git a/solutions/fully-configurable/README.md b/solutions/fully-configurable/README.md new file mode 100644 index 00000000..45923c09 --- /dev/null +++ b/solutions/fully-configurable/README.md @@ -0,0 +1,110 @@ +# Cloud automation for Event Notifications (Fully configurable) + +## Prerequisites +- An existing resource group + +When `existing_en_instance_crn` is not passed, this solution configures the following infrastructure: + +- optionally a KMS key ring +- optionally a KMS key for IBM Event Notifications encryption +- optionally a KMS key for IBM Cloud Object Storage encryption +- optionally an IBM Cloud Object Storage bucket to collect events that fail delivery +- an IBM Event Notifications instance + +When `existing_en_instance_crn` is passed, this solution ignores ALL other inputs and sets the outputs based on the CRN. + + +:exclamation: **Important:** This solution is not intended to be called by one or more 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). + +![event-notifications-deployable-architecture](../../reference-architecture/en.svg) + + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.9.0 | +| [ibm](#requirement\_ibm) | 1.78.0 | +| [time](#requirement\_time) | 0.13.1 | + +### Modules + +| Name | Source | Version | +|------|--------|---------| +| [cos\_buckets](#module\_cos\_buckets) | terraform-ibm-modules/cos/ibm//modules/buckets | 8.21.8 | +| [cos\_kms\_key\_crn\_parser](#module\_cos\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.1.0 | +| [event\_notifications](#module\_event\_notifications) | ../.. | n/a | +| [existing\_cos\_crn\_parser](#module\_existing\_cos\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.1.0 | +| [existing\_en\_crn\_parser](#module\_existing\_en\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.1.0 | +| [existing\_kms\_crn\_parser](#module\_existing\_kms\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.1.0 | +| [existing\_kms\_key\_crn\_parser](#module\_existing\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.1.0 | +| [existing\_sm\_crn\_parser](#module\_existing\_sm\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.1.0 | +| [kms](#module\_kms) | terraform-ibm-modules/kms-all-inclusive/ibm | 5.0.2 | +| [resource\_group](#module\_resource\_group) | terraform-ibm-modules/resource-group/ibm | 1.1.6 | +| [secrets\_manager\_service\_credentials](#module\_secrets\_manager\_service\_credentials) | terraform-ibm-modules/secrets-manager/ibm//modules/secrets | 2.2.6 | + +### Resources + +| Name | Type | +|------|------| +| [ibm_iam_authorization_policy.cos_kms_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/1.78.0/docs/resources/iam_authorization_policy) | resource | +| [ibm_iam_authorization_policy.en_kms_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/1.78.0/docs/resources/iam_authorization_policy) | resource | +| [ibm_iam_authorization_policy.secrets_manager_key_manager](https://registry.terraform.io/providers/IBM-Cloud/ibm/1.78.0/docs/resources/iam_authorization_policy) | resource | +| [time_sleep.wait_for_en_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/0.13.1/docs/resources/sleep) | resource | +| [ibm_resource_instance.existing_en_instance](https://registry.terraform.io/providers/IBM-Cloud/ibm/1.78.0/docs/data-sources/resource_instance) | data source | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [add\_bucket\_name\_suffix](#input\_add\_bucket\_name\_suffix) | Whether to add a randomly generated 4-character suffix to the newly provisioned Object Storage bucket name. Set to `false` if you want full control over bucket naming by using the `cos_bucket_name` variable. | `bool` | `true` | no | +| [cbr\_rules](#input\_cbr\_rules) | The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md) |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [cos\_bucket\_access\_tags](#input\_cos\_bucket\_access\_tags) | A list of access tags to apply to the Cloud Object Storage bucket created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | +| [cos\_bucket\_class](#input\_cos\_bucket\_class) | The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`. | `string` | `"standard"` | no | +| [cos\_bucket\_name](#input\_cos\_bucket\_name) | The name to use when creating the Object Storage bucket for the storage of failed delivery events. Bucket names are globally unique. If `add_bucket_name_suffix` is set to `true`, a random 4 character string is added to this name to help ensure that the bucket name is unique. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"base-event-notifications-bucket"` | no | +| [cos\_bucket\_region](#input\_cos\_bucket\_region) | The COS bucket region. If `cos_bucket_region` is set to null, then `region` will be used. | `string` | `null` | no | +| [cos\_key\_name](#input\_cos\_key\_name) | The name of the key which will be created for the Event Notifications. Not used if supplying an existing key. Only use if 'enable\_collecting\_failed\_events' is true. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications-cos-key"` | no | +| [enable\_collecting\_failed\_events](#input\_enable\_collecting\_failed\_events) | Set to true to enable Cloud Object Storage integration. If true a Cloud Object Storage instance to store failed events in should also be passed using variable `existing_cos_instance_crn`. For more info see https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-cfe-integrations. | `bool` | `false` | no | +| [event\_notifications\_access\_tags](#input\_event\_notifications\_access\_tags) | A list of access tags to apply to the Event Notifications instance created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | +| [event\_notifications\_instance\_name](#input\_event\_notifications\_instance\_name) | The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications"` | no | +| [event\_notifications\_key\_name](#input\_event\_notifications\_key\_name) | The name for the key that will be created for the Event Notifications instance. Not used if an existing key is specified. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications-key"` | no | +| [event\_notifications\_key\_ring\_name](#input\_event\_notifications\_key\_ring\_name) | The name of the key ring which will be created for the Event Notifications instance. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications-key-ring"` | no | +| [event\_notifications\_resource\_tags](#input\_event\_notifications\_resource\_tags) | The list of tags to add to the Event Notifications instance. | `list(string)` | `[]` | no | +| [existing\_cos\_instance\_crn](#input\_existing\_cos\_instance\_crn) | The CRN of an IBM Cloud Object Storage instance. If not supplied, Cloud Object Storage will not be configured. To use, 'enable\_collecting\_failed\_events' must be set to true. | `string` | `null` | no | +| [existing\_event\_notifications\_instance\_crn](#input\_existing\_event\_notifications\_instance\_crn) | The CRN of existing Event Notifications instance. If not supplied, a new instance is created. | `string` | `null` | no | +| [existing\_kms\_instance\_crn](#input\_existing\_kms\_instance\_crn) | The CRN of the KMS instance (Hyper Protect Crypto Services or Key Protect instance). If the KMS instance is in different account you must also provide a value for `ibmcloud_kms_api_key`. To use an existing kms instance you must also provide a value for 'kms\_endpoint\_url' and 'existing\_kms\_root\_key\_crn' should be null. A value should not be passed passing existing EN instance using the `existing_event_notifications_instance_crn` input. | `string` | `null` | no | +| [existing\_kms\_root\_key\_crn](#input\_existing\_kms\_root\_key\_crn) | The key CRN of a root key which will be used to encrypt the data. To use an existing key you must also provide a value for 'kms\_endpoint\_url' and 'existing\_kms\_instance\_crn' should be null. If no value passed, a new key will be created in the instance provided in the `existing_kms_instance_crn` input. | `string` | `null` | no | +| [existing\_resource\_group\_name](#input\_existing\_resource\_group\_name) | The name of an existing resource group to provision the resources. | `string` | `"Default"` | no | +| [existing\_secrets\_manager\_endpoint\_type](#input\_existing\_secrets\_manager\_endpoint\_type) | The endpoint type to use if `existing_secrets_manager_instance_crn` is specified. Possible values: public, private. | `string` | `"private"` | no | +| [existing\_secrets\_manager\_instance\_crn](#input\_existing\_secrets\_manager\_instance\_crn) | The CRN of existing secrets manager to use to create service credential secrets for Event Notification instance. | `string` | `null` | no | +| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The API key to use for IBM Cloud. | `string` | n/a | yes | +| [ibmcloud\_kms\_api\_key](#input\_ibmcloud\_kms\_api\_key) | 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 Event Notifications instance. Leave this input empty if the same account owns both instances. | `string` | `null` | no | +| [kms\_encryption\_enabled](#input\_kms\_encryption\_enabled) | Set to true to enable KMS encryption on Event Notifications instance and Cloud Object Storage bucket. When set to true 'kms\_endpoint\_url' and one of 'existing\_kms\_instance\_crn' or 'existing\_kms\_root\_key\_crn' must be set. | `bool` | `false` | no | +| [kms\_endpoint\_type](#input\_kms\_endpoint\_type) | The type of the endpoint that is used for communicating with the KMS instance. Possible values: `public` or `private` (default). Only used if not supplying an existing root key. | `string` | `"private"` | no | +| [kms\_endpoint\_url](#input\_kms\_endpoint\_url) | The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input. | `string` | `null` | no | +| [management\_endpoint\_type\_for\_bucket](#input\_management\_endpoint\_type\_for\_bucket) | The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Available values: `public`, `private`, `direct`. Make sure to enable virtual routing and forwarding in your account if you specify `private`, and that the Terraform runtime has access to the IBM Cloud private network. | `string` | `"private"` | no | +| [prefix](#input\_prefix) | Prefix to add to all resources created by this solution. To not use any prefix value, you can set this value to `null` or an empty string. | `string` | n/a | yes | +| [provider\_visibility](#input\_provider\_visibility) | Set the visibility value for the IBM terraform provider. Supported values are `public`, `private`, `public-and-private`. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints). | `string` | `"private"` | no | +| [region](#input\_region) | The region in which the Event Notifications resources are provisioned. | `string` | `"us-south"` | no | +| [service\_credential\_names](#input\_service\_credential\_names) | The mapping of names and roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets | `map(string)` | `{}` | no | +| [service\_credential\_secrets](#input\_service\_credential\_secrets) | Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets). |
list(object({
secret_group_name = string
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)

}))
}))
| `[]` | no | +| [service\_endpoints](#input\_service\_endpoints) | Specify whether you want to enable public, or both public and private service endpoints. Possible values: `public`, `public-and-private` | `string` | `"public-and-private"` | no | +| [service\_plan](#input\_service\_plan) | The pricing plan of the Event Notifications instance. Possible values: `Lite`, `Standard` | `string` | `"standard"` | no | +| [skip\_cos\_kms\_auth\_policy](#input\_skip\_cos\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits the COS instance to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_key_management_service_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | +| [skip\_event\_notifications\_cos\_auth\_policy](#input\_skip\_event\_notifications\_cos\_auth\_policy) | Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy. | `bool` | `false` | no | +| [skip\_event\_notifications\_kms\_auth\_policy](#input\_skip\_event\_notifications\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | +| [skip\_event\_notifications\_secrets\_manager\_auth\_policy](#input\_skip\_event\_notifications\_secrets\_manager\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing\_secrets\_manager\_instance\_crn' is not passed. | `bool` | `false` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| [crn](#output\_crn) | Event Notification crn | +| [event\_notification\_instance\_name](#output\_event\_notification\_instance\_name) | Event Notification name | +| [guid](#output\_guid) | Event Notification guid | +| [service\_credential\_secret\_groups](#output\_service\_credential\_secret\_groups) | Service credential secret groups | +| [service\_credential\_secrets](#output\_service\_credential\_secrets) | Service credential secrets | +| [service\_credentials\_json](#output\_service\_credentials\_json) | Service credentials json map | +| [service\_credentials\_object](#output\_service\_credentials\_object) | Service credentials object | + diff --git a/solutions/fully-configurable/catalogValidationValues.json.template b/solutions/fully-configurable/catalogValidationValues.json.template new file mode 100644 index 00000000..0f0dba2d --- /dev/null +++ b/solutions/fully-configurable/catalogValidationValues.json.template @@ -0,0 +1,9 @@ +{ + "ibmcloud_api_key": $VALIDATION_APIKEY, + "existing_resource_group_name": "geretain-test-event-notifications", + "event_notifications_resource_tags": $TAGS, + "kms_encryption_enabled": true, + "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN, + "kms_endpoint_url": $HPCS_US_SOUTH_PRIVATE_ENDPOINT, + "prefix": $PREFIX +} diff --git a/solutions/standard/main.tf b/solutions/fully-configurable/main.tf similarity index 54% rename from solutions/standard/main.tf rename to solutions/fully-configurable/main.tf index 79733fbf..8ade0d52 100644 --- a/solutions/standard/main.tf +++ b/solutions/fully-configurable/main.tf @@ -2,110 +2,102 @@ # Resource Group ######################################################################################################################## -# Create new resource group, or take in existing group module "resource_group" { - count = var.existing_en_instance_crn == null ? 1 : 0 source = "terraform-ibm-modules/resource-group/ibm" - version = "1.2.0" - resource_group_name = var.use_existing_resource_group == false ? try("${local.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 + version = "1.1.6" + existing_resource_group_name = var.existing_resource_group_name } ####################################################################################################################### # KMS keys ####################################################################################################################### -# Input variable validation -locals { - prefix = var.prefix != null ? (var.prefix != "" ? var.prefix : null) : null -} - -# If existing KMS root key CRN passed, parse details from it -module "kms_root_key_crn_parser" { - count = var.existing_kms_root_key_crn != null ? 1 : 0 - source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" - version = "1.1.0" - crn = var.existing_kms_root_key_crn -} - -# If existing KMS intance CRN passed, parse details from it -module "kms_instance_crn_parser" { +# parse KMS details from the existing KMS instance CRN +module "existing_kms_crn_parser" { count = var.existing_kms_instance_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" version = "1.1.0" crn = var.existing_kms_instance_crn } -# If not using an existing COS bucket, or an existing EN instance, parse details from the KMS key CRN used for COS -module "cos_kms_key_crn_parser" { - count = var.existing_cos_bucket_name == null && var.existing_en_instance_crn == null ? 1 : 0 +# If existing KMS root key CRN passed, parse details from it +module "existing_kms_key_crn_parser" { + count = var.existing_kms_root_key_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" version = "1.1.0" - crn = local.cos_kms_key_crn + crn = var.existing_kms_root_key_crn } locals { - # If an existing KMS root key, or an existing EN instance is passed, do not create a new KMS root key - create_kms_keys = var.existing_kms_root_key_crn != null || var.existing_en_instance_crn != null ? false : true - # If existing KMS root key CRN passed, parse the ID from it - existing_en_kms_root_key_id = var.existing_kms_root_key_crn != null ? module.kms_root_key_crn_parser[0].resource : null - # Determine the KMS root key ID value (new key or existing key) - en_kms_key_id = local.existing_en_kms_root_key_id != null ? local.existing_en_kms_root_key_id : var.existing_en_instance_crn == null ? module.kms[0].keys[format("%s.%s", local.en_key_ring_name, local.en_key_name)].key_id : null - # If existing KMS instance CRN passed, parse the region from it - kms_region = var.existing_kms_instance_crn != null ? module.kms_instance_crn_parser[0].region : null - # If existing KMS instance CRN passed, parse the GUID from it - kms_instance_guid = var.existing_kms_instance_crn != null ? module.kms_instance_crn_parser[0].service_instance : null - # If existing KMS instance CRN passed, parse the service name from it - kms_service_name = var.existing_kms_instance_crn != null ? module.kms_instance_crn_parser[0].service_name : null - # If existing KMS instance CRN passed, parse the account ID from it - # TODO: update logic once CRN parser supports outputting account id (tracked in https://github.com/terraform-ibm-modules/terraform-ibm-common-utilities/issues/17) - kms_account_id = var.existing_kms_instance_crn != null ? split("/", module.kms_instance_crn_parser[0].scope)[1] : null - # Create cross account EN / KMS auth policy if not using existing EN instance, if 'skip_en_kms_auth_policy' is false, and a value is passed for 'ibmcloud_kms_api_key' - create_cross_account_en_kms_auth_policy = var.existing_en_instance_crn == null && !var.skip_en_kms_auth_policy && var.ibmcloud_kms_api_key != null - # Create cross account COS / KMS auth policy if not using existing EN instance, if not using existing bucket, if 'skip_cos_kms_auth_policy' is false, and if a value is passed for 'ibmcloud_kms_api_key' - create_cross_account_cos_kms_auth_policy = var.existing_en_instance_crn == null && var.existing_cos_bucket_name == null && !var.skip_cos_kms_auth_policy && var.ibmcloud_kms_api_key != null + prefix = (var.prefix != null && trimspace(var.prefix) != "" ? "${var.prefix}-" : "") + + # If an existing KMS root key, or an existing EN instance is passed, or KMS is not enabled do not create a new KMS root key + create_kms_keys = !var.kms_encryption_enabled || var.existing_kms_root_key_crn != null || var.existing_event_notifications_instance_crn != null ? false : true + + kms_region = var.kms_encryption_enabled ? var.existing_kms_instance_crn != null ? module.existing_kms_crn_parser[0].region : var.existing_kms_root_key_crn != null ? module.existing_kms_key_crn_parser[0].region : null : null + existing_kms_guid = var.kms_encryption_enabled ? var.existing_kms_instance_crn != null ? module.existing_kms_crn_parser[0].service_instance : var.existing_kms_root_key_crn != null ? module.existing_kms_key_crn_parser[0].service_instance : null : null + kms_service_name = var.kms_encryption_enabled ? var.existing_kms_instance_crn != null ? module.existing_kms_crn_parser[0].service_name : var.existing_kms_root_key_crn != null ? module.existing_kms_key_crn_parser[0].service_name : null : null + kms_account_id = var.kms_encryption_enabled ? var.existing_kms_instance_crn != null ? module.existing_kms_crn_parser[0].account_id : var.existing_kms_root_key_crn != null ? module.existing_kms_key_crn_parser[0].account_id : null : null + en_kms_key_id = local.create_kms_keys ? module.kms[0].keys[format("%s.%s", local.en_key_ring_name, local.en_key_name)].key_id : var.existing_kms_root_key_crn != null ? module.existing_kms_key_crn_parser[0].resource : null + existing_kms_instance_crn = var.kms_encryption_enabled ? var.existing_kms_instance_crn != null ? var.existing_kms_instance_crn : "crn:v1:bluemix:${module.existing_kms_key_crn_parser[0].ctype}:${module.existing_kms_key_crn_parser[0].service_name}:${module.existing_kms_key_crn_parser[0].region}:${module.existing_kms_key_crn_parser[0].scope}:${module.existing_kms_key_crn_parser[0].service_instance}::" : null + + # Create cross account EN / KMS auth policy if not using existing EN instance, if 'skip_en_kms_auth_policy' is false, and a value is passed for 'ibmcloud_key_management_service_api_key' + create_cross_account_en_kms_auth_policy = var.existing_event_notifications_instance_crn == null && !var.skip_event_notifications_kms_auth_policy && var.ibmcloud_kms_api_key != null + # Create cross account COS / KMS auth policy if not using existing EN instance, if 'skip_cos_kms_auth_policy' is false, and if a value is passed for 'ibmcloud_key_management_service_api_key' + create_cross_account_cos_kms_auth_policy = var.existing_event_notifications_instance_crn == null && !var.skip_cos_kms_auth_policy && var.ibmcloud_kms_api_key != null # If a prefix value is passed, add it to the EN key name - en_key_name = try("${local.prefix}-${var.en_key_name}", var.en_key_name) + en_key_name = "${local.prefix}${var.event_notifications_key_name}" # If a prefix value is passed, add it to the EN key ring name - en_key_ring_name = try("${local.prefix}-${var.en_key_ring_name}", var.en_key_ring_name) - # If a prefix value is passed, add it to the COS key name - cos_key_name = try("${local.prefix}-${var.cos_key_name}", var.cos_key_name) - # If a prefix value is passed, add it to the COS key ring name - cos_key_ring_name = try("${local.prefix}-${var.cos_key_ring_name}", var.cos_key_ring_name) + en_key_ring_name = "${local.prefix}${var.event_notifications_key_ring_name}" + # Use existing key if set. Else if new key and if a prefix value is passed, add it to the COS key name + cos_key_name = "${local.prefix}${var.cos_key_name}" # Determine the COS KMS key CRN (new key or existing key). It will only have a value if not using an existing bucket or existing EN instance - cos_kms_key_crn = var.existing_en_instance_crn != null || var.existing_cos_bucket_name != null ? null : var.existing_kms_root_key_crn != null ? var.existing_kms_root_key_crn : module.kms[0].keys[format("%s.%s", local.cos_key_ring_name, local.cos_key_name)].crn + cos_kms_key_crn = var.existing_event_notifications_instance_crn != null ? null : var.existing_kms_root_key_crn != null ? var.existing_kms_root_key_crn : module.kms[0].keys[format("%s.%s", local.en_key_ring_name, local.cos_key_name)].crn # If existing KMS instance CRN passed, parse the key ID from it cos_kms_key_id = local.cos_kms_key_crn != null ? module.cos_kms_key_crn_parser[0].resource : null - # Event Notifications KMS Key ring config - en_kms_key = { - key_ring_name = local.en_key_ring_name - existing_key_ring = false - keys = [ - { - key_name = local.en_key_name - standard_key = false - rotation_interval_month = 3 - dual_auth_delete_enabled = false - force_delete = true - } - ] - } - # Event Notifications COS bucket KMS Key ring config - en_cos_kms_key = { - key_ring_name = local.cos_key_ring_name - existing_key_ring = false - keys = [ - { - key_name = local.cos_key_name - standard_key = false - rotation_interval_month = 3 - dual_auth_delete_enabled = false - force_delete = true - } - ] +} + +module "kms" { + providers = { + ibm = ibm.kms } - # If not using existing EN instance or KMS key, create Key. Don't create a COS KMS key if using existing COS bucket. - all_keys = local.create_kms_keys ? var.existing_cos_bucket_name != null ? [local.en_kms_key] : concat([local.en_kms_key], [local.en_cos_kms_key]) : [] + count = local.create_kms_keys ? 1 : 0 + source = "terraform-ibm-modules/kms-all-inclusive/ibm" + version = "5.0.2" + create_key_protect_instance = false + region = local.kms_region + existing_kms_instance_crn = var.existing_kms_instance_crn + key_ring_endpoint_type = var.kms_endpoint_type + key_endpoint_type = var.kms_endpoint_type + keys = [ + { + key_ring_name = local.en_key_ring_name + keys = [ + { + key_name = local.en_key_name + standard_key = false + rotation_interval_month = 3 + dual_auth_delete_enabled = false + force_delete = true + }, + { + key_name = local.cos_key_name + standard_key = false + rotation_interval_month = 3 + dual_auth_delete_enabled = false + force_delete = true + } + ] + } + ] +} + +# If not using an existing EN instance, parse details from the new or existing KMS key CRN used for COS +module "cos_kms_key_crn_parser" { + count = (local.create_kms_keys || var.existing_kms_root_key_crn != null) ? 1 : 0 + source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" + version = "1.1.0" + crn = local.cos_kms_key_crn } # Create cross account IAM Authorization Policy to allow COS to read the KMS encryption key @@ -116,7 +108,7 @@ resource "ibm_iam_authorization_policy" "cos_kms_policy" { source_service_name = "cloud-object-storage" source_resource_instance_id = local.cos_instance_guid roles = ["Reader"] - description = "Allow the COS instance ${local.cos_instance_guid} to read the ${local.kms_service_name} key ${local.cos_kms_key_id} from the instance ${local.kms_instance_guid}" + description = "Allow the COS instance ${local.cos_instance_guid} to read the ${local.kms_service_name} key ${local.cos_kms_key_id} from the instance ${local.existing_kms_guid}" resource_attributes { name = "serviceName" operator = "stringEquals" @@ -130,7 +122,7 @@ resource "ibm_iam_authorization_policy" "cos_kms_policy" { resource_attributes { name = "serviceInstance" operator = "stringEquals" - value = local.kms_instance_guid + value = local.existing_kms_guid } resource_attributes { name = "resourceType" @@ -157,7 +149,7 @@ resource "ibm_iam_authorization_policy" "en_kms_policy" { source_service_name = "event-notifications" source_resource_instance_id = module.event_notifications[0].guid roles = ["Reader"] - description = "Allow the EN instance with GUID ${module.event_notifications[0].guid} to read the ${local.kms_service_name} key ${local.cos_kms_key_id} from the instance ${local.kms_instance_guid}}" + description = "Allow the EN instance with GUID ${module.event_notifications[0].guid} to read the ${local.kms_service_name} key ${local.cos_kms_key_id} from the instance ${local.existing_kms_guid}}" resource_attributes { name = "serviceName" operator = "stringEquals" @@ -171,7 +163,7 @@ resource "ibm_iam_authorization_policy" "en_kms_policy" { resource_attributes { name = "serviceInstance" operator = "stringEquals" - value = local.kms_instance_guid + value = local.existing_kms_guid } resource_attributes { name = "resourceType" @@ -190,28 +182,12 @@ resource "ibm_iam_authorization_policy" "en_kms_policy" { } } -# Create KMS root keys -module "kms" { - providers = { - ibm = ibm.kms - } - count = local.create_kms_keys ? 1 : 0 - source = "terraform-ibm-modules/kms-all-inclusive/ibm" - version = "5.0.2" - create_key_protect_instance = false - region = local.kms_region - existing_kms_instance_crn = var.existing_kms_instance_crn - key_ring_endpoint_type = var.kms_endpoint_type - key_endpoint_type = var.kms_endpoint_type - keys = local.all_keys -} - ####################################################################################################################### # COS ####################################################################################################################### -# If existing COS intance CRN passed, parse details from it -module "cos_instance_crn_parser" { +# parse COS details from the existing COS instance CRN +module "existing_cos_crn_parser" { count = var.existing_cos_instance_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" version = "1.1.0" @@ -219,48 +195,40 @@ module "cos_instance_crn_parser" { } locals { - # If a bucket name is passed, or an existing EN CRN is passed; do not create COS resources - create_cos_bucket = var.existing_cos_bucket_name != null || var.existing_en_instance_crn != null ? false : true + # If not collecting failed events, or an existing EN CRN is passed; do not create COS resources + create_cos_bucket = !var.enable_collecting_failed_events || var.existing_event_notifications_instance_crn != null ? false : true # determine COS details - cos_bucket_name = var.existing_cos_bucket_name != null ? var.existing_cos_bucket_name : local.create_cos_bucket ? try("${local.prefix}-${var.cos_bucket_name}", var.cos_bucket_name) : null - cos_bucket_name_with_suffix = var.existing_cos_bucket_name != null ? var.existing_cos_bucket_name : local.create_cos_bucket ? module.cos[0].bucket_name : null - cos_bucket_region = var.cos_bucket_region != null ? var.cos_bucket_region : var.cross_region_location != null ? null : var.region - cos_instance_name = try("${local.prefix}-${var.cos_instance_name}", var.cos_instance_name) - cos_endpoint = var.existing_cos_bucket_name == null ? (local.create_cos_bucket ? "https://${module.cos[0].s3_endpoint_direct}" : null) : var.existing_cos_endpoint - # If not using existing EN instance, and if existing COS instance CRN passed, parse the GUID from it, otherwise get GUID from COS module output - cos_instance_guid = var.existing_en_instance_crn == null ? var.existing_cos_instance_crn == null ? module.cos[0].cos_instance_guid : module.cos_instance_crn_parser[0].service_instance : null - # If not using existing EN instance, parse the COS account ID from the CRN - # TODO: update logic once CRN parser supports outputting account id (tracked in https://github.com/terraform-ibm-modules/terraform-ibm-common-utilities/issues/17) - cos_account_id = var.existing_en_instance_crn == null ? var.existing_cos_instance_crn != null ? split("/", module.cos_instance_crn_parser[0].scope)[1] : module.cos[0].cos_account_id : null + cos_bucket_name = var.existing_event_notifications_instance_crn == null && !var.enable_collecting_failed_events ? null : local.create_cos_bucket ? "${local.prefix}${var.cos_bucket_name}" : null + cos_bucket_name_with_suffix = var.existing_event_notifications_instance_crn == null && var.enable_collecting_failed_events ? module.cos_buckets[0].buckets[local.cos_bucket_name].bucket_name : null + cos_bucket_region = var.existing_event_notifications_instance_crn == null && var.cos_bucket_region != null && var.cos_bucket_region != "" ? var.cos_bucket_region : var.region + cos_instance_guid = var.existing_event_notifications_instance_crn == null ? (var.existing_cos_instance_crn == null ? (length(module.cos_buckets) > 0 ? module.cos_buckets.bucket_configs.cos_instance_guid : null) : module.existing_cos_crn_parser[0].service_instance) : null + cos_bucket_endpoint = var.existing_event_notifications_instance_crn == null && var.enable_collecting_failed_events ? "https://${module.cos_buckets[0].buckets[local.cos_bucket_name].s3_endpoint_direct}" : null + cos_account_id = var.existing_event_notifications_instance_crn == null ? var.existing_cos_instance_crn != null ? split("/", module.existing_cos_crn_parser[0].scope)[1] : null : null } -module "cos" { - count = local.create_cos_bucket ? 1 : 0 - source = "terraform-ibm-modules/cos/ibm" - version = "8.21.20" - create_cos_instance = var.existing_cos_instance_crn == null ? true : false - create_cos_bucket = local.create_cos_bucket - existing_cos_instance_id = var.existing_cos_instance_crn - skip_iam_authorization_policy = local.create_cross_account_en_kms_auth_policy || local.create_cross_account_cos_kms_auth_policy || var.skip_cos_kms_auth_policy - add_bucket_name_suffix = var.add_bucket_name_suffix - resource_group_id = module.resource_group[0].resource_group_id - region = local.cos_bucket_region - cross_region_location = var.cross_region_location - cos_instance_name = local.cos_instance_name - cos_plan = var.cos_plan - cos_tags = var.cos_instance_tags - bucket_name = local.cos_bucket_name - access_tags = var.cos_instance_access_tags - management_endpoint_type_for_bucket = var.management_endpoint_type_for_bucket - existing_kms_instance_guid = local.kms_instance_guid - kms_key_crn = local.cos_kms_key_crn - monitoring_crn = var.existing_monitoring_crn - retention_enabled = var.retention_enabled - archive_days = var.archive_days - expire_filter_prefix = var.expire_filter_prefix - archive_filter_prefix = var.archive_filter_prefix +locals { + bucket_config = [{ + access_tags = var.cos_bucket_access_tags + bucket_name = local.cos_bucket_name + add_bucket_name_suffix = var.add_bucket_name_suffix + kms_encryption_enabled = var.kms_encryption_enabled + kms_guid = local.existing_kms_guid + kms_key_crn = local.cos_kms_key_crn + skip_iam_authorization_policy = var.skip_cos_kms_auth_policy + management_endpoint_type = var.management_endpoint_type_for_bucket + storage_class = var.cos_bucket_class + resource_instance_id = var.existing_cos_instance_crn + region_location = local.cos_bucket_region + force_delete = true + }] } +module "cos_buckets" { + count = var.enable_collecting_failed_events && var.existing_event_notifications_instance_crn == null ? 1 : 0 + source = "terraform-ibm-modules/cos/ibm//modules/buckets" + version = "8.21.8" + bucket_configs = local.bucket_config +} ######################################################################################################################## # Event Notifications @@ -268,21 +236,21 @@ module "cos" { # If existing EN intance CRN passed, parse details from it module "existing_en_crn_parser" { - count = var.existing_en_instance_crn != null ? 1 : 0 + count = var.existing_event_notifications_instance_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" version = "1.1.0" - crn = var.existing_en_instance_crn + crn = var.existing_event_notifications_instance_crn } locals { # determine if existing EN instance being used - use_existing_en_instance = var.existing_en_instance_crn != null + use_existing_en_instance = var.existing_event_notifications_instance_crn != null # if using existing EN instance, parse the GUID from it existing_en_instance_guid = local.use_existing_en_instance ? module.existing_en_crn_parser[0].service_instance : null # determine the EN GUID eventnotification_guid = local.use_existing_en_instance ? local.existing_en_instance_guid : module.event_notifications[0].guid # determine the EN CRN - eventnotification_crn = local.use_existing_en_instance ? var.existing_en_instance_crn : module.event_notifications[0].crn + eventnotification_crn = local.use_existing_en_instance ? var.existing_event_notifications_instance_crn : module.event_notifications[0].crn } # Lookup instance if using an existing one @@ -294,25 +262,26 @@ data "ibm_resource_instance" "existing_en_instance" { module "event_notifications" { count = local.use_existing_en_instance ? 0 : 1 source = "../.." - resource_group_id = module.resource_group[0].resource_group_id + resource_group_id = module.resource_group.resource_group_id region = var.region - name = try("${local.prefix}-${var.event_notification_name}", var.event_notification_name) + name = "${local.prefix}${var.event_notifications_instance_name}" plan = var.service_plan - tags = var.tags + tags = var.event_notifications_resource_tags + access_tags = var.event_notifications_access_tags service_endpoints = var.service_endpoints service_credential_names = var.service_credential_names # KMS Related - kms_encryption_enabled = true + kms_encryption_enabled = var.kms_encryption_enabled kms_endpoint_url = var.kms_endpoint_url - existing_kms_instance_crn = var.existing_kms_instance_crn + existing_kms_instance_crn = local.existing_kms_instance_crn root_key_id = local.en_kms_key_id - skip_en_kms_auth_policy = local.create_cross_account_en_kms_auth_policy || local.create_cross_account_cos_kms_auth_policy || var.skip_en_kms_auth_policy + skip_en_kms_auth_policy = local.create_cross_account_en_kms_auth_policy || var.skip_event_notifications_kms_auth_policy # COS Related - cos_integration_enabled = true + cos_integration_enabled = var.enable_collecting_failed_events cos_bucket_name = local.cos_bucket_name_with_suffix - cos_instance_id = var.existing_cos_instance_crn != null ? var.existing_cos_instance_crn : module.cos[0].cos_instance_crn - skip_en_cos_auth_policy = var.skip_en_cos_auth_policy - cos_endpoint = local.cos_endpoint + cos_instance_id = var.existing_cos_instance_crn + skip_en_cos_auth_policy = var.skip_event_notifications_cos_auth_policy + cos_endpoint = local.cos_bucket_endpoint cbr_rules = var.cbr_rules } @@ -320,7 +289,7 @@ module "event_notifications" { # Service Credentials ######################################################################################################################## -# If existing EN intance CRN passed, parse details from it +# If existing EN instance CRN passed, parse details from it module "existing_sm_crn_parser" { count = var.existing_secrets_manager_instance_crn != null ? 1 : 0 source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser" @@ -359,7 +328,7 @@ locals { # create a service authorization between Secrets Manager and the target service (Event Notification) resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" { - count = var.skip_en_sm_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1 + count = var.skip_event_notifications_secrets_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1 source_service_name = "secrets-manager" source_resource_instance_id = local.existing_secrets_manager_instance_guid target_service_name = "event-notifications" diff --git a/solutions/standard/outputs.tf b/solutions/fully-configurable/outputs.tf similarity index 80% rename from solutions/standard/outputs.tf rename to solutions/fully-configurable/outputs.tf index 79a54881..7fc15782 100644 --- a/solutions/standard/outputs.tf +++ b/solutions/fully-configurable/outputs.tf @@ -4,12 +4,12 @@ output "event_notification_instance_name" { description = "Event Notification name" - value = var.existing_en_instance_crn == null ? module.event_notifications[0].event_notification_instance_name : data.ibm_resource_instance.existing_en_instance[0].name + value = var.existing_event_notifications_instance_crn == null ? module.event_notifications[0].event_notification_instance_name : data.ibm_resource_instance.existing_en_instance[0].name } output "crn" { description = "Event Notification crn" - value = local.use_existing_en_instance ? var.existing_en_instance_crn : module.event_notifications[0].crn + value = local.use_existing_en_instance ? var.existing_event_notifications_instance_crn : module.event_notifications[0].crn } output "guid" { diff --git a/solutions/standard/provider.tf b/solutions/fully-configurable/provider.tf similarity index 100% rename from solutions/standard/provider.tf rename to solutions/fully-configurable/provider.tf diff --git a/solutions/standard/variables.tf b/solutions/fully-configurable/variables.tf similarity index 60% rename from solutions/standard/variables.tf rename to solutions/fully-configurable/variables.tf index 6829ac9e..76a5b94a 100644 --- a/solutions/standard/variables.tf +++ b/solutions/fully-configurable/variables.tf @@ -2,31 +2,27 @@ # Common variables ######################################################################################################################## +variable "existing_resource_group_name" { + type = string + description = "The name of an existing resource group to provision the resources." + default = "Default" +} + variable "ibmcloud_api_key" { type = string description = "The API key to use for IBM Cloud." sensitive = true } + 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 + 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)." default = "private" - validation { condition = contains(["public", "private", "public-and-private"], var.provider_visibility) error_message = "Invalid visibility option. Allowed values are 'public', 'private', or 'public-and-private'." } } -variable "use_existing_resource_group" { - type = bool - description = "Whether to use an existing resource group." - default = false -} - -variable "resource_group_name" { - type = string - description = "The name of a new or an existing resource group in which to provision the Databases for Elasicsearch in. If a `prefix` input variable is specified, it is added to this name in the `-value` format." -} variable "region" { type = string @@ -34,17 +30,9 @@ variable "region" { default = "us-south" } -variable "existing_monitoring_crn" { - type = string - nullable = true - default = null - description = "The CRN of an IBM Cloud Monitoring instance used to monitor the IBM Cloud Object Storage bucket that is used for storing failed events. If no value passed, metrics are sent to the instance associated to the container's location unless otherwise specified in the Metrics Router service configuration. Ignored if using existing Object Storage bucket." -} - variable "prefix" { type = string - description = "(Optional) Prefix to add to all resources created by this solution. To not use any prefix value, you can set this value to `null` or an empty string." - default = "dev" + description = "Prefix to add to all resources created by this solution. To not use any prefix value, you can set this value to `null` or an empty string." validation { condition = (var.prefix == null ? true : alltrue([ @@ -56,13 +44,26 @@ variable "prefix" { } } +variable "event_notifications_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Event Notifications instance created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." + default = [] + + validation { + condition = alltrue([ + for tag in var.event_notifications_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\", see https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits for more details" + } +} + ######################################################################################################################## # Event Notifications ######################################################################################################################## variable "service_credential_names" { type = map(string) - description = "The mapping of names and roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/standard/DA-types.md#service-credential-secrets" + description = "The mapping of names and roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets" default = {} validation { @@ -71,10 +72,10 @@ variable "service_credential_names" { } } -variable "event_notification_name" { +variable "event_notifications_instance_name" { type = string description = "The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format." - default = "base-event-notifications" + default = "event-notifications" } variable "service_plan" { @@ -85,7 +86,6 @@ variable "service_plan" { condition = contains(["lite", "standard"], var.service_plan) error_message = "The specified pricing plan is not available. The following plans are supported: `Lite`, `Standard`" } - } variable "service_endpoints" { @@ -98,15 +98,15 @@ variable "service_endpoints" { } } -variable "tags" { +variable "event_notifications_resource_tags" { type = list(string) description = "The list of tags to add to the Event Notifications instance." default = [] } -variable "existing_en_instance_crn" { +variable "existing_event_notifications_instance_crn" { type = string - description = "The CRN of existing event notification instance. If not supplied, a new instance is created." + description = "The CRN of existing Event Notifications instance. If not supplied, a new instance is created." default = null } @@ -114,26 +114,69 @@ variable "existing_en_instance_crn" { # KMS ######################################################################################################################## +variable "kms_encryption_enabled" { + type = bool + description = "Set to true to enable KMS encryption on Event Notifications instance and Cloud Object Storage bucket. When set to true 'kms_endpoint_url' and one of 'existing_kms_instance_crn' or 'existing_kms_root_key_crn' must be set." + default = false + + validation { + condition = var.kms_encryption_enabled == true ? (var.existing_kms_instance_crn != null || var.existing_kms_root_key_crn != null) && length(var.kms_endpoint_url) > 0 : true + error_message = "You must provide at least one of 'existing_kms_instance_crn' or 'existing_kms_root_key_crn' and also set the 'kms_endpoint_url' variable if 'kms_encryption_enabled' is set to true." + } + + validation { + condition = var.kms_encryption_enabled == false ? (var.existing_kms_root_key_crn == null && var.existing_kms_instance_crn == null && var.kms_endpoint_url == null) : true + error_message = "If 'kms_encryption_enabled' is set to false. You should not pass values for 'existing_kms_instance_crn', 'existing_kms_root_key_crn' or 'kms_endpoint_url'." + } +} + variable "existing_kms_instance_crn" { type = string - description = "The CRN of the KMS instance (Hyper Protect Crypto Services or Key Protect instance). If the KMS instance is in different account you must also provide a value for `ibmcloud_kms_api_key`." + description = "The CRN of the KMS instance (Hyper Protect Crypto Services or Key Protect instance). If the KMS instance is in different account you must also provide a value for `ibmcloud_kms_api_key`. To use an existing kms instance you must also provide a value for 'kms_endpoint_url' and 'existing_kms_root_key_crn' should be null. A value should not be passed passing existing EN instance using the `existing_event_notifications_instance_crn` input." default = null + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)), + var.existing_kms_instance_crn == null, + ]) + error_message = "The provided KMS instance CRN in the input 'existing_kms_instance_crn' in not valid." + } + validation { - condition = var.existing_en_instance_crn == null ? (var.existing_kms_instance_crn != null && var.kms_endpoint_url != null) : true - error_message = ("A value for 'existing_kms_instance_crn' and 'kms_endpoint_url' must be passed when no value is passed for 'existing_en_instance_crn'.") + condition = var.existing_kms_instance_crn != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'existing_kms_instance_crn' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." } } -variable "existing_kms_root_key_crn" { +variable "kms_endpoint_url" { type = string - description = "The key CRN of a root key, existing in the KMS instance passed in the `existing_kms_instance_crn` input, which will be used to encrypt the data. If no value passed, a new key will be created in the instance provided in the `existing_kms_instance_crn` input." + description = "The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input." default = null + + validation { + condition = var.kms_endpoint_url != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'kms_endpoint_url' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." + } } -variable "kms_endpoint_url" { +variable "existing_kms_root_key_crn" { type = string - description = "The KMS endpoint URL to use when you configure KMS encryption. The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_en_instance_crn` input." + description = "The key CRN of a root key which will be used to encrypt the data. To use an existing key you must also provide a value for 'kms_endpoint_url' and 'existing_kms_instance_crn' should be null. If no value passed, a new key will be created in the instance provided in the `existing_kms_instance_crn` input." default = null + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}:key:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", var.existing_kms_root_key_crn)), + var.existing_kms_root_key_crn == null, + ]) + error_message = "The provided KMS key CRN in the input 'existing_kms_root_key_crn' in not valid." + } + + validation { + condition = var.existing_kms_root_key_crn != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'existing_kms_root_key_crn' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." + } } variable "kms_endpoint_type" { @@ -146,31 +189,25 @@ variable "kms_endpoint_type" { } } -variable "en_key_ring_name" { +variable "event_notifications_key_name" { type = string - default = "en-key-ring" - description = "The name of the key ring which will be created for the Event Notifications instance. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "event-notifications-key" + description = "The name for the key that will be created for the Event Notifications instance. Not used if an existing key is specified. If a `prefix` input variable is specified, it is added to this name in the `-value` format." } -variable "en_key_name" { - type = string - default = "en-key" - description = "The name for the key that will be created for the Event Notifications. Not used if an existing key is specfied. If a `prefix` input variable is specified, it is added to this name in the `-value` format." -} - -variable "cos_key_ring_name" { +variable "cos_key_name" { type = string - default = "en-cos-key-ring" - description = "The name of the key ring which will be created for Object Storage. Not used if supplying an existing key or if `existing_cos_bucket_name` is specified. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "event-notifications-cos-key" + description = "The name of the key which will be created for the Event Notifications. Not used if supplying an existing key. Only use if 'enable_collecting_failed_events' is true. If a `prefix` input variable is specified, it is added to this name in the `-value` format." } -variable "cos_key_name" { +variable "event_notifications_key_ring_name" { type = string - default = "en-cos-key" - description = "The name of the key which will be created for the Event Notifications. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "event-notifications-key-ring" + description = "The name of the key ring which will be created for the Event Notifications instance. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format." } -variable "skip_en_kms_auth_policy" { +variable "skip_event_notifications_kms_auth_policy" { type = bool description = "Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." default = false @@ -181,30 +218,31 @@ variable "ibmcloud_kms_api_key" { 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 Event Notifications instance. Leave this input empty if the same account owns both instances." sensitive = true default = null + validation { + condition = var.ibmcloud_kms_api_key != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'ibmcloud_kms_api_key' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." + } } ######################################################################################################################## # COS ######################################################################################################################## -variable "existing_cos_instance_crn" { - type = string - nullable = true - default = null - description = "The CRN of an IBM Cloud Object Storage instance. If not supplied, a new instance is created." +variable "enable_collecting_failed_events" { + type = bool + description = "Set to true to enable Cloud Object Storage integration. If true a Cloud Object Storage instance to store failed events in should also be passed using variable `existing_cos_instance_crn`. For more info see https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-cfe-integrations." + default = false + validation { + condition = var.enable_collecting_failed_events == true ? length(var.existing_cos_instance_crn) > 0 : true + error_message = "You must provide an 'existing_cos_instance_crn' if 'enable_collecting_failed_events' is set to true." + } } -variable "existing_cos_bucket_name" { +variable "existing_cos_instance_crn" { type = string nullable = true default = null - description = "The name of an existing bucket inside the existing Object Storage instance. If not supplied, a new bucket is created." - - validation { - condition = var.existing_cos_bucket_name != null ? (var.existing_cos_instance_crn != null && var.existing_cos_endpoint != null) : true - error_message = "When passing a value for 'existing_cos_bucket_name', you must also pass values for 'existing_cos_instance_crn' and 'existing_cos_endpoint'." - } - + description = "The CRN of an IBM Cloud Object Storage instance. If not supplied, Cloud Object Storage will not be configured. To use, 'enable_collecting_failed_events' must be set to true." } variable "cos_bucket_name" { @@ -213,86 +251,53 @@ variable "cos_bucket_name" { default = "base-event-notifications-bucket" } -variable "skip_en_cos_auth_policy" { - type = bool - description = "Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy." - default = false -} - -variable "skip_cos_kms_auth_policy" { - type = bool - description = "Set to true to skip the creation of an IAM authorization policy that permits the COS instance to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." - default = false -} - -variable "cos_instance_name" { - type = string - default = "base-event-notifications-cos" - description = "The name to use when creating the Object Storage instance. If a `prefix` input variable is specified, it is added to this name in the `-value` format." -} - -variable "cos_instance_tags" { - type = list(string) - description = "The optional list of tags to add to the Object Storage instance. Only used if not supplying an existing instance." - default = [] -} - -variable "cos_instance_access_tags" { - type = list(string) - description = "The list of access tags to apply to the Object Storage instance. Only used if not supplying an existing instance." - default = [] -} - variable "add_bucket_name_suffix" { type = bool - description = "Whether to add a randomly generated 4-character suffix to the newly provisioned Object Storage bucket name. Used only if not using an existing bucket. Set to `false` if you want full control over bucket naming by using the `cos_bucket_name` variable." + description = "Whether to add a randomly generated 4-character suffix to the newly provisioned Object Storage bucket name. Set to `false` if you want full control over bucket naming by using the `cos_bucket_name` variable." default = true } -variable "cos_plan" { - description = "The plan that is used for creating the Object Storage instance. Available values: `lite`, `standard` and `cos-one-rate-plan`." +variable "cos_bucket_class" { type = string default = "standard" + description = "The storage class of the newly provisioned Cloud Object Storage bucket. Specify one of the following values for the storage class: `standard`, `vault`, `cold`, `smart` (default), or `onerate_active`." validation { - condition = contains(["standard", "lite", "cos-one-rate-plan"], var.cos_plan) - error_message = "The specified cos_plan is not a valid selection." - } -} - -variable "cross_region_location" { - description = "Specify the cross-regional bucket location. Possiblevalues: `us`, `eu`, and `ap`. If you pass a value for this variable, you must set the value of `cos_bucket_region` to null. If `cross_region_location` and `cos_bucket_region` are both set to null, then `region` will be used." - type = string - default = null - - validation { - condition = var.cross_region_location == null || can(regex("us|eu|ap", var.cross_region_location)) - error_message = "The variable `cross_region_location` value must be `us` or `eu`, `ap`, or `null`." + condition = contains(["standard", "vault", "cold", "smart", "onerate_active"], var.cos_bucket_class) + error_message = "Specify one of the following values for the `cos_bucket_class`: `standard`, `vault`, `cold`, `smart`, or `onerate_active`." } } -variable "cos_bucket_region" { - type = string - description = "The COS bucket region. If you pass a value for this variable, you must set the value of `cross_region_location` to null. If `cross_region_location` and `cos_bucket_region` are both set to null, then `region` will be used." - default = null +variable "cos_bucket_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Cloud Object Storage bucket created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." + default = [] validation { - condition = var.cos_bucket_region == null || var.cross_region_location == null - error_message = "Cannot provide values for both 'cos_bucket_region' and 'cross_region_location'. Pick one or the other, or alternatively, pass no value for either and allow it to default to the 'region' input." + condition = alltrue([ + for tag in var.cos_bucket_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\", see https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits for more details" } } -variable "archive_days" { - description = "Specifies the number of days when the archive rule action takes effect. This must be set to null when when using var.cross_region_location as archive data is not supported with this feature." - type = number - default = null +variable "skip_event_notifications_cos_auth_policy" { + type = bool + description = "Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy." + default = false } -variable "retention_enabled" { +variable "skip_cos_kms_auth_policy" { type = bool - description = "Set to `true` to skip the creation of an IAM authorization policy that permits all Event Notifications instances in the resource group to read the encryption key from the KMS instance." + description = "Set to true to skip the creation of an IAM authorization policy that permits the COS instance to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_key_management_service_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." default = false } +variable "cos_bucket_region" { + type = string + description = "The COS bucket region. If `cos_bucket_region` is set to null, then `region` will be used." + default = null +} + variable "management_endpoint_type_for_bucket" { description = "The type of endpoint for the IBM Terraform provider to use to manage Object Storage buckets. Available values: `public`, `private`, `direct`. Make sure to enable virtual routing and forwarding in your account if you specify `private`, and that the Terraform runtime has access to the IBM Cloud private network." type = string @@ -303,24 +308,6 @@ variable "management_endpoint_type_for_bucket" { } } -variable "existing_cos_endpoint" { - type = string - description = "The endpoint URL for your bucket region. [Learn more](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-endpoints). Only required if using an existing bucket with the `existing_cos_bucket_name` variable." - default = null -} - -variable "expire_filter_prefix" { - type = string - description = "Apply expire lifecycle rule to only objects with the following prefix. Defaults to apply to all objects." - default = null -} - -variable "archive_filter_prefix" { - type = string - description = "Apply archive lifecycle rule to only objects with the following prefix. Defaults to apply to all objects." - default = null -} - ############################################################################## ## Secrets Manager Service Credentials ############################################################################## @@ -359,7 +346,7 @@ variable "service_credential_secrets" { })) })) default = [] - description = "Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/standard/DA-types.md#service-credential-secrets)." + description = "Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets)." validation { # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select Event Notifications and select the role @@ -378,7 +365,7 @@ variable "service_credential_secrets" { } -variable "skip_en_sm_auth_policy" { +variable "skip_event_notifications_secrets_manager_auth_policy" { type = bool default = false description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing_secrets_manager_instance_crn' is not passed." @@ -399,6 +386,6 @@ variable "cbr_rules" { })) }))) })) - description = "The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/standard/DA-cbr_rules.md)" + description = "The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md)" default = [] } 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..21052bc2 --- /dev/null +++ b/solutions/security-enforced/README.md @@ -0,0 +1,84 @@ +# Cloud automation for Event Notifications (Security Enforced) + +## Prerequisites +- An existing resource group +- An existing COS instance +- An existing KMS instance (or key) if you want to encrypt the COS bucket and Event Notifications + +When `existing_event_notifications_instance_crn` is not passed, this solution configures the following infrastructure: + +- a KMS key ring and key for IBM Event Notifications encryption +- a KMS key ring and key for IBM Cloud Object Storage encryption +- an IBM Cloud Object Storage bucket to collect events that fail delivery +- an IBM Event Notifications instance + +When `existing_event_notifications_instance_crn` is passed, this solution ignores ALL other inputs and sets the outputs based on the CRN. + +- required inputs MUST still be set, but will be ignored. + +:exclamation: **Important:** This solution is not intended to be called by one or more 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). + +![event-notifications-deployable-architecture](../../reference-architecture/en.svg) + + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.9.0 | + +### Modules + +| Name | Source | Version | +|------|--------|---------| +| [event\_notifications](#module\_event\_notifications) | ../fully-configurable | n/a | + +### Resources + +No resources. + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [add\_bucket\_name\_suffix](#input\_add\_bucket\_name\_suffix) | Whether to add a randomly generated 4-character suffix to the newly provisioned Object Storage bucket name. Set to `false` if you want full control over bucket naming by using the `cos_bucket_name` variable. | `bool` | `true` | no | +| [cbr\_rules](#input\_cbr\_rules) | The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md) |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | +| [cos\_bucket\_access\_tags](#input\_cos\_bucket\_access\_tags) | A list of access tags to apply to the Cloud Object Storage bucket created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | +| [cos\_bucket\_name](#input\_cos\_bucket\_name) | The name to use when creating the Object Storage bucket for the storage of failed delivery events. Bucket names are globally unique. If `add_bucket_name_suffix` is set to `true`, a random 4 character string is added to this name to help ensure that the bucket name is unique. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"base-event-notifications-bucket"` | no | +| [cos\_bucket\_region](#input\_cos\_bucket\_region) | The COS bucket region. If `cos_bucket_region` is set to null, then `region` will be used. | `string` | `null` | no | +| [cos\_key\_name](#input\_cos\_key\_name) | The name of the key which will be created for the Event Notifications. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications-cos-key"` | no | +| [event\_notifications\_instance\_name](#input\_event\_notifications\_instance\_name) | The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications"` | no | +| [event\_notifications\_key\_name](#input\_event\_notifications\_key\_name) | The name for the key that will be created for the Event Notifications instance. Not used if an existing key is specified. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications-key"` | no | +| [event\_notifications\_key\_ring\_name](#input\_event\_notifications\_key\_ring\_name) | The name of the key ring which will be created for the Event Notifications instance. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format. | `string` | `"event-notifications-key-ring"` | no | +| [event\_notifications\_resource\_tags](#input\_event\_notifications\_resource\_tags) | The list of tags to add to the Event Notifications instance. | `list(string)` | `[]` | no | +| [existing\_cos\_instance\_crn](#input\_existing\_cos\_instance\_crn) | The CRN of an IBM Cloud Object Storage instance. If not supplied, Cloud Object Storage will not be configured. | `string` | `null` | no | +| [existing\_event\_notifications\_instance\_crn](#input\_existing\_event\_notifications\_instance\_crn) | The CRN of existing Event Notifications instance. If not supplied, a new instance is created. | `string` | `null` | no | +| [existing\_kms\_instance\_crn](#input\_existing\_kms\_instance\_crn) | The CRN of the KMS instance (Hyper Protect Crypto Services or Key Protect instance). If the KMS instance is in different account you must also provide a value for `ibmcloud_kms_api_key`. To use an existing kms instance you must also provide a value for 'kms\_endpoint\_url' and 'existing\_kms\_root\_key\_crn' should be null. A value should not be passed passing existing EN instance using the `existing_event_notifications_instance_crn` input. | `string` | `null` | no | +| [existing\_kms\_root\_key\_crn](#input\_existing\_kms\_root\_key\_crn) | The key CRN of a root key which will be used to encrypt the data. To use an existing key you must also provide a value for 'kms\_endpoint\_url' and 'existing\_kms\_instance\_crn' should be null. If no value passed, a new key will be created in the instance provided in the `existing_kms_instance_crn` input. | `string` | `null` | no | +| [existing\_resource\_group\_name](#input\_existing\_resource\_group\_name) | The name of an existing resource group to provision the resources. | `string` | `"Default"` | no | +| [existing\_secrets\_manager\_instance\_crn](#input\_existing\_secrets\_manager\_instance\_crn) | The CRN of existing secrets manager to use to create service credential secrets for Event Notification instance. | `string` | `null` | no | +| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The API key to use for IBM Cloud. | `string` | n/a | yes | +| [ibmcloud\_kms\_api\_key](#input\_ibmcloud\_kms\_api\_key) | 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 Event Notifications instance. Leave this input empty if the same account owns both instances. | `string` | `null` | no | +| [kms\_endpoint\_url](#input\_kms\_endpoint\_url) | The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input. | `string` | `null` | no | +| [prefix](#input\_prefix) | Prefix to add to all resources created by this solution. To not use any prefix value, you can set this value to `null` or an empty string. | `string` | n/a | yes | +| [region](#input\_region) | The region in which the Event Notifications resources are provisioned. | `string` | `"us-south"` | no | +| [service\_credential\_names](#input\_service\_credential\_names) | The mapping of names and roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets | `map(string)` | `{}` | no | +| [service\_credential\_secrets](#input\_service\_credential\_secrets) | Service credential secrets configuration for Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets). |
list(object({
secret_group_name = string
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)

}))
}))
| `[]` | no | +| [skip\_cos\_kms\_auth\_policy](#input\_skip\_cos\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits the COS instance to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_key_management_service_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | +| [skip\_event\_notifications\_cos\_auth\_policy](#input\_skip\_event\_notifications\_cos\_auth\_policy) | Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy. | `bool` | `false` | no | +| [skip\_event\_notifications\_kms\_auth\_policy](#input\_skip\_event\_notifications\_kms\_auth\_policy) | Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | +| [skip\_event\_notifications\_secrets\_manager\_auth\_policy](#input\_skip\_event\_notifications\_secrets\_manager\_auth\_policy) | Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing\_secrets\_manager\_instance\_crn' is not passed. | `bool` | `false` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| [crn](#output\_crn) | Event Notification crn | +| [event\_notification\_instance\_name](#output\_event\_notification\_instance\_name) | Event Notification name | +| [guid](#output\_guid) | Event Notification guid | +| [service\_credential\_secret\_groups](#output\_service\_credential\_secret\_groups) | Service credential secret groups | +| [service\_credential\_secrets](#output\_service\_credential\_secrets) | Service credential secrets | +| [service\_credentials\_json](#output\_service\_credentials\_json) | Service credentials json map | +| [service\_credentials\_object](#output\_service\_credentials\_object) | Service credentials object | + diff --git a/solutions/security-enforced/catalogValidationValues.json.template b/solutions/security-enforced/catalogValidationValues.json.template new file mode 100644 index 00000000..ef8348a4 --- /dev/null +++ b/solutions/security-enforced/catalogValidationValues.json.template @@ -0,0 +1,9 @@ +{ + "ibmcloud_api_key": $VALIDATION_APIKEY, + "existing_resource_group_name": "geretain-test-event-notifications", + "event_notifications_resource_tags": $TAGS, + "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN, + "kms_endpoint_url": $HPCS_US_SOUTH_PRIVATE_ENDPOINT, + "existing_cos_instance_crn": $COS_INSTANCE_CRN, + "prefix": $PREFIX +} diff --git a/solutions/security-enforced/main.tf b/solutions/security-enforced/main.tf new file mode 100644 index 00000000..78c2846e --- /dev/null +++ b/solutions/security-enforced/main.tf @@ -0,0 +1,43 @@ + +module "event_notifications" { + source = "../fully-configurable" + existing_resource_group_name = var.existing_resource_group_name + ibmcloud_api_key = var.ibmcloud_api_key + provider_visibility = "private" + region = var.region + prefix = var.prefix + service_credential_names = var.service_credential_names + event_notifications_instance_name = var.event_notifications_instance_name + service_plan = "standard" + service_endpoints = "public-and-private" + event_notifications_resource_tags = var.event_notifications_resource_tags + existing_event_notifications_instance_crn = var.existing_event_notifications_instance_crn + # KMS Related + kms_encryption_enabled = true + existing_kms_instance_crn = var.existing_kms_instance_crn + kms_endpoint_url = var.kms_endpoint_url + existing_kms_root_key_crn = var.existing_kms_root_key_crn + kms_endpoint_type = "private" + event_notifications_key_name = var.event_notifications_key_name + cos_key_name = var.cos_key_name + event_notifications_key_ring_name = var.event_notifications_key_ring_name + skip_event_notifications_kms_auth_policy = var.skip_event_notifications_kms_auth_policy + ibmcloud_kms_api_key = var.ibmcloud_kms_api_key + # COS Related + enable_collecting_failed_events = true + existing_cos_instance_crn = var.existing_cos_instance_crn + cos_bucket_name = var.cos_bucket_name + add_bucket_name_suffix = var.add_bucket_name_suffix + cos_bucket_class = "standard" + cos_bucket_access_tags = var.cos_bucket_access_tags + skip_event_notifications_cos_auth_policy = var.skip_event_notifications_cos_auth_policy + skip_cos_kms_auth_policy = var.skip_cos_kms_auth_policy + cos_bucket_region = var.cos_bucket_region + management_endpoint_type_for_bucket = "private" + # Secrets Manager Related + 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_event_notifications_secrets_manager_auth_policy = var.skip_event_notifications_secrets_manager_auth_policy + cbr_rules = var.cbr_rules +} diff --git a/solutions/security-enforced/outputs.tf b/solutions/security-enforced/outputs.tf new file mode 100644 index 00000000..66a55c29 --- /dev/null +++ b/solutions/security-enforced/outputs.tf @@ -0,0 +1,40 @@ +############################################################################## +# Outputs +############################################################################## + +output "event_notification_instance_name" { + description = "Event Notification name" + value = module.event_notifications.event_notification_instance_name +} + +output "crn" { + description = "Event Notification crn" + value = module.event_notifications.crn +} + +output "guid" { + description = "Event Notification guid" + value = module.event_notifications.guid +} + +output "service_credentials_json" { + description = "Service credentials json map" + value = module.event_notifications.service_credentials_json + sensitive = true +} + +output "service_credentials_object" { + description = "Service credentials object" + value = module.event_notifications.service_credentials_object + sensitive = true +} + +output "service_credential_secrets" { + description = "Service credential secrets" + value = module.event_notifications.service_credential_secrets +} + +output "service_credential_secret_groups" { + description = "Service credential secret groups" + value = module.event_notifications.service_credential_secret_groups +} diff --git a/solutions/security-enforced/provider.tf b/solutions/security-enforced/provider.tf new file mode 100644 index 00000000..4c6add22 --- /dev/null +++ b/solutions/security-enforced/provider.tf @@ -0,0 +1 @@ +# Explicit provider config not required here as provider config in fully-configurable is used diff --git a/solutions/security-enforced/variables.tf b/solutions/security-enforced/variables.tf new file mode 100644 index 00000000..5f9c2aad --- /dev/null +++ b/solutions/security-enforced/variables.tf @@ -0,0 +1,284 @@ +######################################################################################################################## +# Common variables +######################################################################################################################## + +variable "existing_resource_group_name" { + type = string + description = "The name of an existing resource group to provision the resources." + default = "Default" +} + +variable "ibmcloud_api_key" { + type = string + description = "The API key to use for IBM Cloud." + sensitive = true +} + +variable "region" { + type = string + description = "The region in which the Event Notifications resources are provisioned." + default = "us-south" +} + +variable "prefix" { + type = string + description = "Prefix to add to all resources created by this solution. To not use any prefix value, you can set this value to `null` or an empty string." + validation { + condition = (var.prefix == null ? true : + alltrue([ + can(regex("^[a-z]{0,1}[-a-z0-9]{0,14}[a-z0-9]{0,1}$", var.prefix)), + length(regexall("^.*--.*", var.prefix)) == 0 + ]) + ) + error_message = "Prefix must begin with a lowercase letter, contain only lowercase letters, numbers, and - characters. Prefixes must end with a lowercase letter or number and be 16 or fewer characters." + } +} + +######################################################################################################################## +# Event Notifications +######################################################################################################################## + +variable "service_credential_names" { + type = map(string) + description = "The mapping of names and roles for service credentials that you want to create for the Event Notifications instance. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets" + default = {} + + validation { + condition = alltrue([for name, role in var.service_credential_names : contains(["Manager", "Writer", "Reader", "Event Source Manager", "Channel Editor", "Event Notification Publisher", "Status Reporter", "Device Manager", "Email Sender", "Custom Email Status Reporter"], role)]) + error_message = "The specified service credential role is not valid. The following values are valid for service credential roles: 'Manager', 'Writer', 'Reader', 'Event Source Manager', 'Channel Editor', 'Event Notification Publisher', 'Status Reporter', 'Device Manager', 'Email Sender', 'Custom Email Status Reporter'" + } +} + +variable "event_notifications_instance_name" { + type = string + description = "The name of the Event Notifications instance that is created by this solution. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "event-notifications" +} + +variable "event_notifications_resource_tags" { + type = list(string) + description = "The list of tags to add to the Event Notifications instance." + default = [] +} + +variable "existing_event_notifications_instance_crn" { + type = string + description = "The CRN of existing Event Notifications instance. If not supplied, a new instance is created." + default = null +} + +######################################################################################################################## +# KMS +######################################################################################################################## + +variable "existing_kms_instance_crn" { + type = string + description = "The CRN of the KMS instance (Hyper Protect Crypto Services or Key Protect instance). If the KMS instance is in different account you must also provide a value for `ibmcloud_kms_api_key`. To use an existing kms instance you must also provide a value for 'kms_endpoint_url' and 'existing_kms_root_key_crn' should be null. A value should not be passed passing existing EN instance using the `existing_event_notifications_instance_crn` input." + default = null + + validation { + condition = anytrue([ + can(regex("^crn:(.*:){3}(kms|hs-crypto):(.*:){2}[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}::$", var.existing_kms_instance_crn)), + var.existing_kms_instance_crn == null, + ]) + error_message = "The provided KMS instance CRN in the input 'existing_kms_instance_crn' in not valid." + } + + validation { + condition = var.existing_kms_instance_crn != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'existing_kms_instance_crn' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." + } +} + +variable "kms_endpoint_url" { + type = string + description = "The KMS endpoint URL to use when you configure KMS encryption. When set to true, a value must be passed for either `existing_kms_root_key_crn` or `existing_kms_instance_crn` (to create a new key). The Hyper Protect Crypto Services endpoint URL format is `https://api.private..hs-crypto.cloud.ibm.com:` and the Key Protect endpoint URL format is `https://.kms.cloud.ibm.com`. Not required if passing an existing instance using the `existing_event_notifications_instance_crn` input." + default = null + + validation { + condition = var.kms_endpoint_url != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'kms_endpoint_url' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." + } +} + +variable "existing_kms_root_key_crn" { + type = string + description = "The key CRN of a root key which will be used to encrypt the data. To use an existing key you must also provide a value for 'kms_endpoint_url' and 'existing_kms_instance_crn' should be null. If no value passed, a new key will be created in the instance provided in the `existing_kms_instance_crn` input." + default = null + + validation { + condition = var.existing_kms_root_key_crn != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'existing_kms_root_key_crn' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." + } + + validation { + condition = var.existing_kms_root_key_crn != null ? var.existing_kms_instance_crn == null : true + error_message = "A value should not be passed for 'existing_kms_instance_crn' when passing an existing key value using the 'existing_kms_root_key_crn' input." + } + + validation { + condition = var.existing_kms_root_key_crn == null ? var.existing_kms_instance_crn != null : true + error_message = "A value must be passed for either 'existing_kms_instance_crn' (to create a new key) or 'existing_kms_root_key_crn' (to use existing key) to encrypt the COS bucket." + } +} + +variable "event_notifications_key_name" { + type = string + default = "event-notifications-key" + description = "The name for the key that will be created for the Event Notifications instance. Not used if an existing key is specified. If a `prefix` input variable is specified, it is added to this name in the `-value` format." +} + +variable "cos_key_name" { + type = string + default = "event-notifications-cos-key" + description = "The name of the key which will be created for the Event Notifications. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format." +} + +variable "event_notifications_key_ring_name" { + type = string + default = "event-notifications-key-ring" + description = "The name of the key ring which will be created for the Event Notifications instance. Not used if supplying an existing key. If a `prefix` input variable is specified, it is added to this name in the `-value` format." +} + +variable "skip_event_notifications_kms_auth_policy" { + type = bool + description = "Set to true to skip the creation of an IAM authorization policy that permits the Event Notifications instance to read the encryption key from the KMS instance. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." + default = false +} + +variable "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 Event Notifications instance. Leave this input empty if the same account owns both instances." + sensitive = true + default = null + + validation { + condition = var.ibmcloud_kms_api_key != null ? var.existing_event_notifications_instance_crn == null : true + error_message = "A value should not be passed for 'ibmcloud_kms_api_key' when passing an existing EN instance using the 'existing_event_notifications_instance_crn' input." + } +} + +######################################################################################################################## +# COS +######################################################################################################################## + +variable "existing_cos_instance_crn" { + type = string + nullable = true + default = null + description = "The CRN of an IBM Cloud Object Storage instance. If not supplied, Cloud Object Storage will not be configured." + validation { + condition = var.existing_cos_instance_crn == null ? var.existing_event_notifications_instance_crn != null : true + error_message = "A value must be passed for 'existing_cos_instance_crn' when creating a new instance." + } +} + +variable "cos_bucket_name" { + type = string + description = "The name to use when creating the Object Storage bucket for the storage of failed delivery events. Bucket names are globally unique. If `add_bucket_name_suffix` is set to `true`, a random 4 character string is added to this name to help ensure that the bucket name is unique. If a `prefix` input variable is specified, it is added to this name in the `-value` format." + default = "base-event-notifications-bucket" +} + +variable "add_bucket_name_suffix" { + type = bool + description = "Whether to add a randomly generated 4-character suffix to the newly provisioned Object Storage bucket name. Set to `false` if you want full control over bucket naming by using the `cos_bucket_name` variable." + default = true +} + +variable "cos_bucket_access_tags" { + type = list(string) + description = "A list of access tags to apply to the Cloud Object Storage bucket created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." + default = [] + + validation { + condition = alltrue([ + for tag in var.cos_bucket_access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\", see https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits for more details" + } +} + +variable "skip_event_notifications_cos_auth_policy" { + type = bool + description = "Set to `true` to skip the creation of an IAM authorization policy that permits the Event Notifications instance `Object Writer` and `Reader` access to the given Object Storage bucket. Set to `true` to use an existing policy." + default = false +} + +variable "skip_cos_kms_auth_policy" { + type = bool + description = "Set to true to skip the creation of an IAM authorization policy that permits the COS instance to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_key_management_service_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." + default = false +} + +variable "cos_bucket_region" { + type = string + description = "The COS bucket region. If `cos_bucket_region` is set to null, then `region` will be used." + 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 Event Notification 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 Event Notification. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-types.md#service-credential-secrets)." + + validation { + # Service roles CRNs can be found at https://cloud.ibm.com/iam/roles, select Event Notifications and select the role + condition = alltrue([ + for group in var.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" + } +} + +variable "skip_event_notifications_secrets_manager_auth_policy" { + type = bool + default = false + description = "Whether an IAM authorization policy is created for Secrets Manager instance to create a service credential secrets for Event Notification.If set to false, the Secrets Manager instance passed by the user is granted the Key Manager access to the Event Notifications instance created by the Deployable Architecture. Set to `true` to use an existing policy. The value of this is ignored if any value for 'existing_secrets_manager_instance_crn' is not passed." +} +variable "cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "The list of context-based restrictions rules to create. [Learn more](https://github.com/terraform-ibm-modules/terraform-ibm-event-notifications/tree/main/solutions/fully-configurable/DA-cbr_rules.md)" + default = [] +} 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 5e5c64a4..00000000 --- a/solutions/standard/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Event Notifications solution - -When `existing_en_instance_crn` is not passed, this solution configures the following infrastructure: - -- a resource group, if one is not passed in. -- optionally a KMS key ring and key for IBM Event Notifications encryption -- optionally a KMS key ring and key for IBM Cloud Object Storage encryption -- optionally an IBM Cloud Object Storage instance -- optionally an IBM Cloud Object Storage bucket to collect events that fail delivery -- an IBM Event Notifications instance - -When `existing_en_instance_crn` is passed, this solution ignores ALL other inputs and sets the outputs based on the CRN. - -- required inputs MUST still be set, but will be ignored. - -:exclamation: **Important:** This solution is not intended to be called by one or more 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/standard/catalogValidationValues.json.template deleted file mode 100644 index 23e834dd..00000000 --- a/solutions/standard/catalogValidationValues.json.template +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ibmcloud_api_key": $VALIDATION_APIKEY, - "resource_group_name": $PREFIX, - "tags": $TAGS, - "existing_kms_instance_crn": $HPCS_US_SOUTH_CRN, - "kms_endpoint_url": $HPCS_US_SOUTH_PRIVATE_ENDPOINT -} diff --git a/solutions/standard/moved.tf b/solutions/standard/moved.tf deleted file mode 100644 index a5e2e7d3..00000000 --- a/solutions/standard/moved.tf +++ /dev/null @@ -1,14 +0,0 @@ -moved { - from = module.cos - to = module.cos[0] -} - -moved { - from = module.event_notifications - to = module.event_notifications[0] -} - -moved { - from = module.resource_group - to = module.resource_group[0] -} diff --git a/tests/existing-resources/main.tf b/tests/existing-resources/main.tf index 860eda12..091a3a02 100644 --- a/tests/existing-resources/main.tf +++ b/tests/existing-resources/main.tf @@ -27,3 +27,11 @@ module "cos" { retention_enabled = false kms_encryption_enabled = false } + +module "kms_key" { + source = "terraform-ibm-modules/kms-key/ibm" + version = "1.4.0" + kms_instance_id = "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9::" + key_name = "${var.prefix}-root-key" + force_delete = true # Setting it to true for testing purpose +} diff --git a/tests/existing-resources/outputs.tf b/tests/existing-resources/outputs.tf index 3c3b05ca..85cf8cac 100644 --- a/tests/existing-resources/outputs.tf +++ b/tests/existing-resources/outputs.tf @@ -41,3 +41,8 @@ output "s3_endpoint_direct_url" { description = "COS bucket name" value = "https://${module.cos.s3_endpoint_direct}" } + +output "key_crn" { + description = "KMS key crn" + value = module.kms_key.crn +} diff --git a/tests/existing-resources/version.tf b/tests/existing-resources/version.tf index 97b20938..0a1384e0 100644 --- a/tests/existing-resources/version.tf +++ b/tests/existing-resources/version.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0" + required_version = ">= 1.9.0" required_providers { ibm = { source = "ibm-cloud/ibm" diff --git a/tests/pr_test.go b/tests/pr_test.go index 526c442f..b20c8a4c 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -24,7 +24,8 @@ import ( const completeExampleDir = "examples/complete" const fsExampleDir = "examples/fscloud" -const solutionDADir = "solutions/standard" +const secEnforcedDir = "solutions/security-enforced" +const fullyConfigurableDADir = "solutions/fully-configurable" // Use existing group for tests const resourceGroup = "geretain-test-event-notifications" @@ -101,7 +102,7 @@ func TestCompleteExampleInSchematics(t *testing.T) { assert.Nil(t, err, "This should not have errored") } -func TestDAInSchematics(t *testing.T) { +func TestSecurityEnforcedDAInSchematics(t *testing.T) { t.Parallel() var region = validRegions[rand.Intn(len(validRegions))] @@ -111,9 +112,10 @@ func TestDAInSchematics(t *testing.T) { Prefix: "en-da", TarIncludePatterns: []string{ "*.tf", - solutionDADir + "/*.tf", + fullyConfigurableDADir + "/*.tf", + secEnforcedDir + "/*.tf", }, - TemplateFolder: solutionDADir, + TemplateFolder: secEnforcedDir, Tags: []string{"test-schematic"}, DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 60, @@ -151,12 +153,85 @@ func TestDAInSchematics(t *testing.T) { } options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "prefix", Value: options.Prefix, DataType: "string"}, {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "region", Value: region, DataType: "string"}, - {Name: "resource_group_name", Value: options.Prefix, DataType: "string"}, + {Name: "existing_resource_group_name", Value: permanentResources["general_test_storage_cos_instance_resource_group"], DataType: "string"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, {Name: "kms_endpoint_url", Value: permanentResources["hpcs_south_private_endpoint"], DataType: "string"}, - {Name: "cross_region_location", Value: "us", DataType: "string"}, + {Name: "existing_secrets_manager_instance_crn", Value: permanentResources["secretsManagerCRN"], DataType: "string"}, + {Name: "service_credential_secrets", Value: serviceCredentialSecrets, DataType: "list(object)"}, + {Name: "service_credential_names", Value: string(serviceCredentialNamesJSON), DataType: "map(string)"}, + {Name: "existing_cos_instance_crn", Value: permanentResources["general_test_storage_cos_instance_crn"], DataType: "string"}, + } + + err = options.RunSchematicTest() + assert.Nil(t, err, "This should not have errored") +} + +func TestFullyConfigurableDAInSchematics(t *testing.T) { + t.Parallel() + + var region = validRegions[rand.Intn(len(validRegions))] + + options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ + Testing: t, + Prefix: "en-da", + TarIncludePatterns: []string{ + "*.tf", + fullyConfigurableDADir + "/*.tf", + }, + TemplateFolder: fullyConfigurableDADir, + Tags: []string{"test-schematic"}, + DeleteWorkspaceOnFail: false, + WaitJobCompleteMinutes: 60, + }) + + serviceCredentialSecrets := []map[string]interface{}{ + { + "secret_group_name": fmt.Sprintf("%s-secret-group", options.Prefix), + "service_credentials": []map[string]string{ + { + "secret_name": fmt.Sprintf("%s-cred-reader", options.Prefix), + "service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::serviceRole:Reader", + }, + { + "secret_name": fmt.Sprintf("%s-cred-writer", options.Prefix), + "service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::serviceRole:Writer", + }, + { + "secret_name": fmt.Sprintf("%s-cred-editor", options.Prefix), + "service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::role:Editor", + }, + }, + }, + } + + serviceCredentialNames := map[string]string{ + "admin": "Manager", + "user1": "Writer", + "user2": "Reader", + } + + serviceCredentialNamesJSON, err := json.Marshal(serviceCredentialNames) + if err != nil { + log.Fatalf("Error converting to JSON: %s", err) + } + + options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "prefix", Value: options.Prefix, DataType: "string"}, + {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "region", Value: region, DataType: "string"}, + {Name: "existing_resource_group_name", Value: permanentResources["general_test_storage_cos_instance_resource_group"], DataType: "string"}, + + {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, + {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, + {Name: "kms_endpoint_url", Value: permanentResources["hpcs_south_private_endpoint"], DataType: "string"}, + + {Name: "enable_collecting_failed_events", Value: true, DataType: "bool"}, + {Name: "existing_cos_instance_crn", Value: permanentResources["general_test_storage_cos_instance_crn"], DataType: "string"}, + {Name: "cos_bucket_region", Value: "us-south", DataType: "string"}, + {Name: "existing_secrets_manager_instance_crn", Value: permanentResources["secretsManagerCRN"], DataType: "string"}, {Name: "service_credential_secrets", Value: serviceCredentialSecrets, DataType: "list(object)"}, {Name: "service_credential_names", Value: string(serviceCredentialNamesJSON), DataType: "map(string)"}, @@ -200,26 +275,23 @@ func TestFSCloudInSchematics(t *testing.T) { assert.Nil(t, err, "This should not have errored") } -func TestRunUpgradeDASolution(t *testing.T) { +func TestRunSecurityEnforcedUpgradeDASolution(t *testing.T) { t.Parallel() var region = validRegions[rand.Intn(len(validRegions))] options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ Testing: t, - TerraformDir: solutionDADir, + TerraformDir: secEnforcedDir, Prefix: "en-da-upg", }) terraformVars := map[string]interface{}{ - "ibmcloud_api_key": options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], - "resource_group_name": options.Prefix, - "region": region, - "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], - "kms_endpoint_url": permanentResources["hpcs_south_public_endpoint"], - "kms_endpoint_type": "public", - "provider_visibility": "public", - "management_endpoint_type_for_bucket": "public", + "ibmcloud_api_key": options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], + "existing_resource_group_name": options.Prefix, + "region": region, + "existing_kms_instance_crn": permanentResources["hpcs_south_crn"], + "kms_endpoint_url": permanentResources["hpcs_south_public_endpoint"], } options.TerraformVars = terraformVars @@ -272,88 +344,86 @@ func TestRunExistingResourcesInstances(t *testing.T) { options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ Testing: t, - Prefix: "en-exs-res", + Prefix: "enexres", TarIncludePatterns: []string{ "*.tf", - solutionDADir + "/*.tf", + fullyConfigurableDADir + "/*.tf", }, - TemplateFolder: solutionDADir, + TemplateFolder: fullyConfigurableDADir, Tags: []string{"test-schematic"}, DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 60, }) options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "prefix", Value: options.Prefix, DataType: "string"}, {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "region", Value: region, DataType: "string"}, - {Name: "resource_group_name", Value: terraform.Output(t, existingTerraformOptions, "resource_group_name"), DataType: "string"}, - {Name: "use_existing_resource_group", Value: true, DataType: "bool"}, - {Name: "existing_en_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "event_notification_instance_crn"), DataType: "string"}, + {Name: "existing_resource_group_name", Value: permanentResources["general_test_storage_cos_instance_resource_group"], DataType: "string"}, + {Name: "existing_event_notifications_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "event_notification_instance_crn"), DataType: "string"}, } err := options.RunSchematicTest() assert.NoError(t, err, "TestRunExistingResourcesInstances using existing RG and EN Failed") // ------------------------------------------------------------------------------------ - // Deploy EN DA passing in existing RG, COS instance (not bucket), and KMS key + // Deploy EN DA passing in existing RG, COS instance, and KMS key // ------------------------------------------------------------------------------------ options2 := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ Testing: t, - Prefix: "en-exs-res2", + Prefix: "enexres2", TarIncludePatterns: []string{ "*.tf", - solutionDADir + "/*.tf", + fullyConfigurableDADir + "/*.tf", }, - TemplateFolder: solutionDADir, + TemplateFolder: fullyConfigurableDADir, Tags: []string{"test-schematic"}, DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 60, }) options2.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "prefix", Value: options.Prefix, DataType: "string"}, {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, - {Name: "ibmcloud_kms_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "region", Value: region, DataType: "string"}, - {Name: "resource_group_name", Value: terraform.Output(t, existingTerraformOptions, "resource_group_name"), DataType: "string"}, - {Name: "use_existing_resource_group", Value: true, DataType: "bool"}, - {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, - {Name: "existing_kms_root_key_crn", Value: permanentResources["hpcs_south_root_key_crn"], DataType: "string"}, + {Name: "existing_resource_group_name", Value: permanentResources["general_test_storage_cos_instance_resource_group"], DataType: "string"}, + {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, + {Name: "existing_kms_root_key_crn", Value: terraform.Output(t, existingTerraformOptions, "key_crn"), DataType: "string"}, {Name: "kms_endpoint_url", Value: permanentResources["hpcs_south_private_endpoint"], DataType: "string"}, + {Name: "enable_collecting_failed_events", Value: true, DataType: "bool"}, {Name: "existing_cos_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "cos_crn"), DataType: "string"}, } err2 := options2.RunSchematicTest() assert.NoError(t, err2, "TestRunExistingResourcesInstances using existing RG, COS instance, and KMS key Failed") // ------------------------------------------------------------------------------------ - // Deploy EN DA passing in existing RG, COS instance and bucket + // Deploy EN DA passing in existing RG, COS instance and KMS instance // ------------------------------------------------------------------------------------ - options3 := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ Testing: t, - Prefix: "en-exs-res2", + Prefix: "enexsres3", TarIncludePatterns: []string{ "*.tf", - solutionDADir + "/*.tf", + fullyConfigurableDADir + "/*.tf", }, - TemplateFolder: solutionDADir, + TemplateFolder: fullyConfigurableDADir, Tags: []string{"test-schematic"}, DeleteWorkspaceOnFail: false, WaitJobCompleteMinutes: 60, }) options3.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "prefix", Value: options3.Prefix, DataType: "string"}, {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, {Name: "region", Value: region, DataType: "string"}, - {Name: "resource_group_name", Value: terraform.Output(t, existingTerraformOptions, "resource_group_name"), DataType: "string"}, - {Name: "use_existing_resource_group", Value: true, DataType: "bool"}, + {Name: "existing_resource_group_name", Value: permanentResources["general_test_storage_cos_instance_resource_group"], DataType: "string"}, {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, + {Name: "kms_encryption_enabled", Value: true, DataType: "bool"}, {Name: "kms_endpoint_url", Value: permanentResources["hpcs_south_private_endpoint"], DataType: "string"}, + {Name: "enable_collecting_failed_events", Value: true, DataType: "bool"}, {Name: "existing_cos_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "cos_crn"), DataType: "string"}, - {Name: "existing_cos_bucket_name", Value: terraform.Output(t, existingTerraformOptions, "bucket_name"), DataType: "string"}, - {Name: "existing_cos_endpoint", Value: terraform.Output(t, existingTerraformOptions, "s3_endpoint_direct_url"), DataType: "string"}, + {Name: "cos_bucket_name", Value: terraform.Output(t, existingTerraformOptions, "bucket_name"), DataType: "string"}, } err3 := options3.RunSchematicTest() - assert.NoError(t, err3, "TestRunExistingResourcesInstances using existing RG, COS instance and bucket Failed") - + assert.NoError(t, err3, "TestRunExistingResourcesInstances using existing RG, COS instance and KMS instance Failed") } - // Check if "DO_NOT_DESTROY_ON_FAILURE" is set envVal, _ := os.LookupEnv("DO_NOT_DESTROY_ON_FAILURE") // Destroy the temporary existing resources if required