diff --git a/common-dev-assets b/common-dev-assets index 8a13c7bc..279ef172 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit 8a13c7bc97e6e00b17615320a48fb89fe2a099f7 +Subproject commit 279ef17206e4b671a7c7c5ef442f032969fdb033 diff --git a/ibm_catalog.json b/ibm_catalog.json index a9ebb210..12e7f913 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -153,19 +153,6 @@ } ] }, - { - "key": "allowed_network", - "options": [ - { - "displayname": "Public and private", - "value": "public-and-private" - }, - { - "displayname": "Private only", - "value": "private-only" - } - ] - }, { "key": "secret_manager_tags" }, @@ -217,6 +204,24 @@ { "key": "skip_kms_iam_authorization_policy" }, + { + "key": "enable_event_notification" + }, + { + "key": "existing_secrets_manager_crn" + }, + { + "key": "ibmcloud_kms_api_key" + }, + { + "key": "sm_en_email_list" + }, + { + "key": "sm_en_from_email" + }, + { + "key": "sm_en_reply_to_email" + }, { "key": "existing_secrets_manager_kms_key_crn" }, diff --git a/modules/fscloud/README.md b/modules/fscloud/README.md index f9ad0738..4301b8b7 100644 --- a/modules/fscloud/README.md +++ b/modules/fscloud/README.md @@ -51,6 +51,7 @@ No resources. | [enable\_event\_notification](#input\_enable\_event\_notification) | Set this to true to enable lifecycle notifications for your Secrets Manager instance by connecting an Event Notifications service. When setting this to true, a value must be passed for `existing_en_instance_crn` variable. | `bool` | `false` | no | | [existing\_en\_instance\_crn](#input\_existing\_en\_instance\_crn) | The CRN of the Event Notifications service to enable lifecycle notifications for your Secrets Manager instance. | `string` | `null` | no | | [existing\_kms\_instance\_guid](#input\_existing\_kms\_instance\_guid) | The GUID of the Hyper Protect Crypto Services instance in which the key specified in `kms_key_crn` is coming from. | `string` | n/a | yes | +| [existing\_sm\_instance\_crn](#input\_existing\_sm\_instance\_crn) | The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created. | `string` | `null` | no | | [kms\_key\_crn](#input\_kms\_key\_crn) | The root key CRN of Hyper Protect Crypto Services (HPCS) that you want to use for encryption. | `string` | n/a | yes | | [region](#input\_region) | The region to provision the Secrets Manager instance to. | `string` | n/a | yes | | [resource\_group\_id](#input\_resource\_group\_id) | The ID of the resource group to provision the Secrets Manager instance to. | `string` | n/a | yes | @@ -58,6 +59,7 @@ No resources. | [secrets\_manager\_name](#input\_secrets\_manager\_name) | The name to give the Secrets Manager instance. | `string` | n/a | yes | | [service\_plan](#input\_service\_plan) | The Secrets Manager plan to provision. | `string` | `"standard"` | no | | [skip\_en\_iam\_authorization\_policy](#input\_skip\_en\_iam\_authorization\_policy) | Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances (scoped to the resource group) an 'Event Source Manager' role to the given Event Notifications instance passed in the `existing_en_instance_crn` input variable. In addition, no policy is created if `enable_event_notification` is set to false. | `bool` | `false` | no | +| [skip\_kms\_iam\_authorization\_policy](#input\_skip\_kms\_iam\_authorization\_policy) | Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances in the resource group to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account. | `bool` | `false` | no | | [sm\_tags](#input\_sm\_tags) | The list of resource tags that you want to associate with your Secrets Manager instance. | `list(string)` | `[]` | no | ### Outputs diff --git a/modules/fscloud/main.tf b/modules/fscloud/main.tf index 3221d13c..2e50028e 100644 --- a/modules/fscloud/main.tf +++ b/modules/fscloud/main.tf @@ -1,18 +1,20 @@ module "secrets_manager" { - source = "../.." - resource_group_id = var.resource_group_id - region = var.region - secrets_manager_name = var.secrets_manager_name #tfsec:ignore:general-secrets-no-plaintext-exposure - sm_service_plan = var.service_plan - sm_tags = var.sm_tags - allowed_network = "private-only" - endpoint_type = "private" - kms_encryption_enabled = true - existing_kms_instance_guid = var.existing_kms_instance_guid - enable_event_notification = var.enable_event_notification - existing_en_instance_crn = var.existing_en_instance_crn - skip_en_iam_authorization_policy = var.skip_en_iam_authorization_policy - kms_key_crn = var.kms_key_crn - cbr_rules = var.cbr_rules - secrets = var.secrets + source = "../.." + resource_group_id = var.resource_group_id + region = var.region + secrets_manager_name = var.secrets_manager_name #tfsec:ignore:general-secrets-no-plaintext-exposure + existing_sm_instance_crn = var.existing_sm_instance_crn + sm_service_plan = var.service_plan + sm_tags = var.sm_tags + allowed_network = "private-only" + endpoint_type = "private" + kms_encryption_enabled = true + existing_kms_instance_guid = var.existing_kms_instance_guid + enable_event_notification = var.enable_event_notification + existing_en_instance_crn = var.existing_en_instance_crn + skip_en_iam_authorization_policy = var.skip_en_iam_authorization_policy + skip_kms_iam_authorization_policy = var.skip_kms_iam_authorization_policy + kms_key_crn = var.kms_key_crn + cbr_rules = var.cbr_rules + secrets = var.secrets } diff --git a/modules/fscloud/variables.tf b/modules/fscloud/variables.tf index 4d741838..315ab8c4 100644 --- a/modules/fscloud/variables.tf +++ b/modules/fscloud/variables.tf @@ -29,6 +29,18 @@ variable "sm_tags" { default = [] } +variable "existing_sm_instance_crn" { + type = string + description = "The CRN of an existing Secrets Manager instance. If not supplied, a new instance is created." + default = null +} + +variable "skip_kms_iam_authorization_policy" { + type = bool + description = "Set to true to skip the creation of an IAM authorization policy that permits all Secrets Manager instances in the resource group to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account." + default = false +} + ############################################################################## # Key Management Service (KMS) ############################################################################## diff --git a/moved.tf b/moved.tf index ebee0498..484bde5d 100644 --- a/moved.tf +++ b/moved.tf @@ -1,8 +1,3 @@ -moved { - from = ibm_iam_authorization_policy.policy - to = ibm_iam_authorization_policy.kms_policy -} - moved { from = ibm_resource_instance.secrets_manager_instance to = ibm_resource_instance.secrets_manager_instance[0] diff --git a/solutions/standard/main.tf b/solutions/standard/main.tf index 7b96c6e8..35674df6 100644 --- a/solutions/standard/main.tf +++ b/solutions/standard/main.tf @@ -97,21 +97,18 @@ locals { secrets_manager_guid = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[7] : null) : module.secrets_manager.secrets_manager_guid secrets_manager_crn = var.existing_secrets_manager_crn != null ? var.existing_secrets_manager_crn : module.secrets_manager.secrets_manager_crn secrets_manager_region = var.existing_secrets_manager_crn != null ? (length(local.parsed_existing_secrets_manager_crn) > 0 ? local.parsed_existing_secrets_manager_crn[5] : null) : module.secrets_manager.secrets_manager_region - sm_endpoint_type = var.existing_secrets_manager_crn != null ? var.existing_secrets_endpoint_type : var.allowed_network == "private-only" ? "private" : "public" } module "secrets_manager" { depends_on = [time_sleep.wait_for_authorization_policy] - source = "../.." + source = "../../modules/fscloud" existing_sm_instance_crn = var.existing_secrets_manager_crn resource_group_id = var.existing_secrets_manager_crn == null ? module.resource_group[0].resource_group_id : data.ibm_resource_instance.existing_sm[0].resource_group_id region = var.region secrets_manager_name = try("${local.prefix}-${var.secrets_manager_instance_name}", var.secrets_manager_instance_name) - sm_service_plan = var.service_plan - allowed_network = var.allowed_network + service_plan = var.service_plan sm_tags = var.secret_manager_tags # kms dependency - kms_encryption_enabled = true existing_kms_instance_guid = local.existing_kms_guid kms_key_crn = local.kms_key_crn skip_kms_iam_authorization_policy = var.skip_kms_iam_authorization_policy || local.create_cross_account_auth_policy @@ -119,7 +116,6 @@ module "secrets_manager" { enable_event_notification = var.enable_event_notification existing_en_instance_crn = var.existing_event_notification_instance_crn skip_en_iam_authorization_policy = var.skip_event_notification_iam_authorization_policy - endpoint_type = local.sm_endpoint_type cbr_rules = var.cbr_rules } @@ -131,7 +127,7 @@ module "iam_secrets_engine" { region = local.secrets_manager_region iam_engine_name = try("${local.prefix}-${var.iam_engine_name}", var.iam_engine_name) secrets_manager_guid = local.secrets_manager_guid - endpoint_type = local.sm_endpoint_type + endpoint_type = "private" } locals { @@ -157,7 +153,7 @@ module "secrets_manager_public_cert_engine" { dns_config_name = var.dns_provider_name ca_config_name = var.ca_name acme_letsencrypt_private_key = var.acme_letsencrypt_private_key - service_endpoints = local.sm_endpoint_type + service_endpoints = "private" } @@ -173,7 +169,7 @@ module "private_secret_engine" { root_ca_max_ttl = var.root_ca_max_ttl intermediate_ca_name = var.intermediate_ca_name certificate_template_name = var.certificate_template_name - endpoint_type = local.sm_endpoint_type + endpoint_type = "private" } data "ibm_resource_instance" "existing_sm" { diff --git a/solutions/standard/moved.tf b/solutions/standard/moved.tf new file mode 100644 index 00000000..4064d8b9 --- /dev/null +++ b/solutions/standard/moved.tf @@ -0,0 +1,14 @@ +moved { + from = module.secrets_manager.ibm_resource_instance.secrets_manager_instance + to = module.secrets_manager.module.secrets_manager.ibm_resource_instance.secrets_manager_instance +} + +moved { + from = module.secrets_manager.ibm_iam_authorization_policy.kms_policy + to = module.secrets_manager.module.secrets_manager.ibm_iam_authorization_policy.kms_policy +} + +moved { + from = module.secrets_manager.time_sleep.wait_for_authorization_policy + to = module.secrets_manager.module.secrets_manager.time_sleep.wait_for_authorization_policy +} diff --git a/solutions/standard/variables.tf b/solutions/standard/variables.tf index a47d95e9..d1e92009 100644 --- a/solutions/standard/variables.tf +++ b/solutions/standard/variables.tf @@ -58,16 +58,6 @@ variable "existing_secrets_manager_crn" { default = null } -variable "existing_secrets_endpoint_type" { - type = string - description = "The endpoint type to use if existing_secrets_manager_crn is specified. Possible values: public, private." - default = "private" - validation { - condition = contains(["public", "private"], var.existing_secrets_endpoint_type) - error_message = "Only \"public\" and \"private\" are allowed values for 'existing_secrets_endpoint_type'." - } -} - variable "service_plan" { type = string description = "The pricing plan to use when provisioning a Secrets Manager instance. Possible values: `standard`, `trial`. Applies only if `provision_sm_instance` is set to `true`." @@ -78,16 +68,6 @@ variable "service_plan" { } } -variable "allowed_network" { - type = string - description = "The types of service endpoints to set on the Secrets Manager instance. Possible values: `private-only`, `public-and-private`." - default = "private-only" - validation { - condition = contains(["private-only", "public-and-private"], var.allowed_network) - error_message = "The specified allowed_network is not a valid selection." - } -} - variable "secret_manager_tags" { type = list(any) description = "The list of resource tags you want to associate with your Secrets Manager instance." diff --git a/tests/existing-resources/main.tf b/tests/existing-resources/main.tf index 3bcfc747..ffd1a20b 100644 --- a/tests/existing-resources/main.tf +++ b/tests/existing-resources/main.tf @@ -47,16 +47,3 @@ module "key_protect" { } ] } - -############################################################################## -# Secrets Manager -############################################################################## - -module "secrets_manager" { - source = "../.." - resource_group_id = module.resource_group.resource_group_id - region = var.region - secrets_manager_name = "${var.prefix}-secrets-manager" #tfsec:ignore:general-secrets-no-plaintext-exposure - sm_service_plan = "trial" - sm_tags = var.resource_tags -} diff --git a/tests/existing-resources/outputs.tf b/tests/existing-resources/outputs.tf index dce49432..31bcaf96 100644 --- a/tests/existing-resources/outputs.tf +++ b/tests/existing-resources/outputs.tf @@ -22,8 +22,3 @@ output "event_notification_instance_crn" { value = module.event_notifications.crn description = "CRN of created event notification" } - -output "secrets_manager_instance_crn" { - value = module.secrets_manager.secrets_manager_crn - description = "CRN of created secret manager instance" -} diff --git a/tests/pr_test.go b/tests/pr_test.go index e3e03aa9..56e84e37 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -93,8 +93,14 @@ func TestRunDASolutionSchematics(t *testing.T) { // Set up a schematics test options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ - Testing: t, - TarIncludePatterns: []string{"*.tf", fmt.Sprintf("%s/*.tf", solutionsTerraformDir), "modules/secrets/*.tf"}, + Testing: t, + TarIncludePatterns: []string{ + "*.tf", + fmt.Sprintf("%s/*.tf", solutionsTerraformDir), + fmt.Sprintf("%s/*.tf", fscloudExampleTerraformDir), + fmt.Sprintf("%s/*.tf", "modules/secrets"), + fmt.Sprintf("%s/*.tf", "modules/fscloud"), + }, TemplateFolder: solutionsTerraformDir, ResourceGroup: resourceGroup, Prefix: "sm-da", @@ -182,65 +188,41 @@ func TestRunExistingResourcesInstances(t *testing.T) { assert.True(t, existErr == nil, "Init and Apply of temp existing resource failed") } else { - // ------------------------------------------------------------------------------------ - // Test passing an existing SM, RG, EN - // ------------------------------------------------------------------------------------ - - options := testhelper.TestOptionsDefault(&testhelper.TestOptions{ - Testing: t, - TerraformDir: solutionsTerraformDir, - // Do not hard fail the test if the implicit destroy steps fail to allow a full destroy of resource to occur - ImplicitRequired: false, - TerraformVars: map[string]interface{}{ - "ibmcloud_api_key": os.Getenv("TF_VAR_ibmcloud_api_key"), - "region": region, - "resource_group_name": terraform.Output(t, existingTerraformOptions, "resource_group_name"), - "use_existing_resource_group": true, - "enable_event_notification": true, - "existing_event_notification_instance_crn": terraform.Output(t, existingTerraformOptions, "event_notification_instance_crn"), - "existing_secrets_manager_crn": terraform.Output(t, existingTerraformOptions, "secrets_manager_instance_crn"), - "iam_engine_enabled": true, - "private_engine_enabled": true, - "existing_secrets_endpoint_type": "public", - "provider_visibility": "public", - }, - }) - - output, err := options.RunTestConsistency() - assert.Nil(t, err, "This should not have errored") - assert.NotNil(t, output, "Expected some output") - // ------------------------------------------------------------------------------------ // Test passing existing RG, EN, and KMS key // ------------------------------------------------------------------------------------ - - options2 := testhelper.TestOptionsDefault(&testhelper.TestOptions{ - Testing: t, - TerraformDir: solutionsTerraformDir, - // Do not hard fail the test if the implicit destroy steps fail to allow a full destroy of resource to occur - ImplicitRequired: false, - TerraformVars: map[string]interface{}{ - "ibmcloud_api_key": os.Getenv("TF_VAR_ibmcloud_api_key"), - "region": region, - "resource_group_name": terraform.Output(t, existingTerraformOptions, "resource_group_name"), - "use_existing_resource_group": true, - "enable_event_notification": true, - "existing_event_notification_instance_crn": terraform.Output(t, existingTerraformOptions, "event_notification_instance_crn"), - "existing_secrets_manager_kms_key_crn": terraform.Output(t, existingTerraformOptions, "secrets_manager_kms_key_crn"), - "existing_kms_instance_crn": terraform.Output(t, existingTerraformOptions, "secrets_manager_kms_instance_crn"), - "service_plan": "trial", - "iam_engine_enabled": true, - "private_engine_enabled": true, - "existing_secrets_endpoint_type": "public", - "provider_visibility": "public", - "allowed_network": "public-and-private", + options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ + Testing: t, + TarIncludePatterns: []string{ + "*.tf", + fmt.Sprintf("%s/*.tf", solutionsTerraformDir), + fmt.Sprintf("%s/*.tf", "modules/secrets"), + fmt.Sprintf("%s/*.tf", "modules/fscloud"), }, + TemplateFolder: solutionsTerraformDir, + ResourceGroup: resourceGroup, + Tags: []string{"test-schematic"}, + DeleteWorkspaceOnFail: false, + WaitJobCompleteMinutes: 60, }) - output2, err := options2.RunTestConsistency() - assert.Nil(t, err, "This should not have errored") - assert.NotNil(t, output2, "Expected some output") - + options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "region", Value: validRegions[rand.Intn(len(validRegions))], 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: "enable_event_notification", Value: true, DataType: "bool"}, + {Name: "existing_event_notification_instance_crn", Value: terraform.Output(t, existingTerraformOptions, "event_notification_instance_crn"), DataType: "string"}, + {Name: "existing_secrets_manager_kms_key_crn", Value: permanentResources["hpcs_south_root_key_crn"], DataType: "string"}, + {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, + {Name: "service_plan", Value: "trial", DataType: "string"}, + {Name: "iam_engine_enabled", Value: true, DataType: "bool"}, + {Name: "private_engine_enabled", Value: true, DataType: "bool"}, + {Name: "existing_kms_instance_crn", Value: permanentResources["hpcs_south_crn"], DataType: "string"}, + } + + err := options.RunSchematicTest() + assert.NoError(t, err, "Schematic Test had unexpected error") } // Check if "DO_NOT_DESTROY_ON_FAILURE" is set