Skip to content

Commit c991e94

Browse files
authored
feat: added support for to create Secrets Manager owned service credentials (#372)
1 parent 6d92291 commit c991e94

21 files changed

+567
-49
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ You need the following permissions to run this module.
105105

106106
| Name | Version |
107107
|------|---------|
108-
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
108+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.0 |
109109
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.76.0, <2.0.0 |
110110
| <a name="requirement_time"></a> [time](#requirement\_time) | >= 0.9.1 |
111111

examples/basic/version.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
terraform {
2-
required_version = ">= 1.3.0"
2+
required_version = ">= 1.9.0"
33
required_providers {
44
ibm = {
55
source = "IBM-Cloud/ibm"

examples/complete/version.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
terraform {
2-
required_version = ">= 1.3.0"
2+
required_version = ">= 1.9.0"
33
required_providers {
44
# Use latest version of provider in non-basic examples to verify latest version works with module
55
ibm = {

examples/fscloud/version.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
terraform {
2-
required_version = ">= 1.3.0"
2+
required_version = ">= 1.9.0"
33
required_providers {
44
# Use latest version of provider in non-basic examples to verify latest version works with module
55
ibm = {

ibm_catalog.json

+24
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,18 @@
150150
},
151151
{
152152
"key": "service_credential_names"
153+
},
154+
{
155+
"key": "existing_secrets_manager_endpoint_type"
156+
},
157+
{
158+
"key": "existing_secrets_manager_instance_crn"
159+
},
160+
{
161+
"key": "service_credential_secrets"
162+
},
163+
{
164+
"key": "skip_event_streams_secrets_manager_auth_policy"
153165
}
154166
],
155167
"iam_permissions": [
@@ -348,6 +360,18 @@
348360
},
349361
{
350362
"key": "iam_token_only"
363+
},
364+
{
365+
"key": "existing_secrets_manager_endpoint_type"
366+
},
367+
{
368+
"key": "existing_secrets_manager_instance_crn"
369+
},
370+
{
371+
"key": "service_credential_secrets"
372+
},
373+
{
374+
"key": "skip_event_streams_secrets_manager_auth_policy"
351375
}
352376
],
353377
"iam_permissions": [

main.tf

+5-34
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,11 @@
33
#######################################################################################
44

55
locals {
6-
# Validation (approach based on https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400)
7-
8-
# tflint-ignore: terraform_unused_declarations
9-
validate_kms_plan = var.plan != "enterprise-3nodes-2tb" && var.kms_key_crn != null ? tobool("KMS encryption is only supported for enterprise plan.") : true
10-
# tflint-ignore: terraform_unused_declarations
11-
validate_metrics = var.plan != "enterprise-3nodes-2tb" && length(var.metrics) > 0 ? tobool("Metrics are only supported for enterprise plan.") : true
12-
# tflint-ignore: terraform_unused_declarations
13-
validate_quotas = var.plan != "enterprise-3nodes-2tb" && length(var.quotas) > 0 ? tobool("Quotas are only supported for enterprise plan.") : true
14-
# tflint-ignore: terraform_unused_declarations
15-
validate_schema_global_rule = var.plan != "enterprise-3nodes-2tb" && var.schema_global_rule != null ? tobool("Schema global rule is only supported for enterprise plan.") : true
16-
17-
# tflint-ignore: terraform_unused_declarations
18-
validate_kms_values = !var.kms_encryption_enabled && var.kms_key_crn != null ? tobool("When passing values for var.kms_key_crn, you must set var.kms_encryption_enabled to true. Otherwise unset them to use default encryption.") : true
19-
# tflint-ignore: terraform_unused_declarations
20-
validate_kms_vars = var.kms_encryption_enabled && var.kms_key_crn == null ? tobool("When setting var.kms_encryption_enabled to true, a value must be passed for var.kms_key_crn and/or var.backup_encryption_key_crn.") : true
21-
# tflint-ignore: terraform_unused_declarations
22-
validate_auth_policy = var.kms_encryption_enabled && var.skip_kms_iam_authorization_policy == false && var.kms_key_crn == null ? tobool("When var.skip_kms_iam_authorization_policy is set to false, and var.kms_encryption_enabled to true, a value must be passed for var.kms_key_crn in order to create the auth policy.") : true
23-
# tflint-ignore: terraform_unused_declarations
24-
validate_throughput_lite_standard = ((var.plan == "lite" || var.plan == "standard") && var.throughput != 150) ? tobool("Throughput value cannot be changed in lite and standard plan. Default value is 150.") : true
25-
# tflint-ignore: terraform_unused_declarations
26-
validate_storage_size_lite_standard = ((var.plan == "lite" || var.plan == "standard") && var.storage_size != 2048) ? tobool("Storage size value cannot be changed in lite and standard plan. Default value is 2048.") : true
27-
# tflint-ignore: terraform_unused_declarations
28-
validate_service_end_points_lite_standard = ((var.plan == "lite" || var.plan == "standard") && var.service_endpoints != "public") ? tobool("Service endpoint cannot be changed in lite and standard plan. Default is public.") : true
29-
# tflint-ignore: terraform_unused_declarations
30-
validate_mirroring_topics = var.mirroring == null && var.mirroring_topic_patterns != null ? tobool("When passing values for var.mirroring_topic_patterns, values must also be passed for var.mirroring.") : true
31-
# tflint-ignore: terraform_unused_declarations
32-
validate_mirroring_config = var.mirroring != null && var.mirroring_topic_patterns == null ? tobool("When passing values for var.mirroring, values must also be passed for var.mirroring_topic_patterns.") : true
33-
# tflint-ignore: terraform_unused_declarations
34-
validate_iam_token_only = var.plan != "enterprise-3nodes-2tb" && var.iam_token_only ? tobool("iam_token_only is only supported for enterprise plan") : true
35-
parsed_kms_key_crn = var.kms_key_crn != null ? split(":", var.kms_key_crn) : []
36-
kms_service = length(local.parsed_kms_key_crn) > 0 ? local.parsed_kms_key_crn[4] : null
37-
kms_scope = length(local.parsed_kms_key_crn) > 0 ? local.parsed_kms_key_crn[6] : null
38-
kms_account_id = length(local.parsed_kms_key_crn) > 0 ? split("/", local.kms_scope)[1] : null
39-
kms_key_id = length(local.parsed_kms_key_crn) > 0 ? local.parsed_kms_key_crn[9] : null
6+
parsed_kms_key_crn = var.kms_key_crn != null ? split(":", var.kms_key_crn) : []
7+
kms_service = length(local.parsed_kms_key_crn) > 0 ? local.parsed_kms_key_crn[4] : null
8+
kms_scope = length(local.parsed_kms_key_crn) > 0 ? local.parsed_kms_key_crn[6] : null
9+
kms_account_id = length(local.parsed_kms_key_crn) > 0 ? split("/", local.kms_scope)[1] : null
10+
kms_key_id = length(local.parsed_kms_key_crn) > 0 ? local.parsed_kms_key_crn[9] : null
4011
}
4112

4213
# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478

modules/fscloud/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The default values in this profile were scanned by [IBM Code Risk Analyzer (CRA)
99

1010
| Name | Version |
1111
|------|---------|
12-
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
12+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.0 |
1313
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.76.0, <2.0.0 |
1414

1515
### Modules

modules/fscloud/version.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
terraform {
2-
required_version = ">= 1.3.0"
2+
required_version = ">= 1.9.0"
33
required_providers {
44
# The below tflint-ignore is required because although the below provider is not directly required by this submodule,
55
# it is required by consuming modules, and if not set here, the top level module calling this module will not be

solutions/enterprise/DA-types.md

+70
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
Several optional input variables in the IBM Cloud Event Streams deployable architecture use complex object types. You specify these inputs when you configure you deployable architecture.
44

55
- [Service credentials](#svc-credential-name) (`service_credential_names`)
6+
- [Service credential secrets](#service-credential-secrets) (`service_credential_secrets`)
67
- [Quotas](#quotas) (`quotas`)
78
- [Mirroring](#mirroring) (`quotas`)
89

910
## Service credentials <a name="svc-credential-name"></a>
1011

1112
You can specify a set of IAM credentials to connect to the instance with the `service_credential_names` input variable. Include a credential name and IAM service role for each key-value pair. Each role provides a specific level of access to the instance. For more information, see [Adding and viewing credentials](https://cloud.ibm.com/docs/account?topic=account-service_credentials&interface=ui).
1213

14+
If you want to add service credentials to secret manager and to allow secret manager to manage it, you should use `service_credential_secrets` , see [Service credential secrets](#service-credential-secrets).
15+
1316
- Variable name: `service_credential_names`.
1417
- Type: A map. The key is the name of the service credential. The value is the role that is assigned to that credential.
1518
- Default value: An empty map (`{}`).
@@ -29,6 +32,73 @@ You can specify a set of IAM credentials to connect to the instance with the `se
2932
}
3033
```
3134

35+
## Service credential secrets <a name="service-credential-secrets"></a>
36+
37+
When you add an IBM Event Streams deployable architecture from the IBM Cloud catalog to IBM Cloud Project, you can configure service credentials. In edit mode for the projects configuration, from the configure panel click the optional tab.
38+
39+
To enter a custom value, use the edit action to open the "Edit Array" panel. Add the service credential secrets configurations to the array here.
40+
41+
In the configuration, specify the secret group name, whether it already exists or will be created and include all the necessary service credential secrets that need to be created within that secret group.
42+
43+
[Learn more](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-getting-started#getting-started) about service credential secrets.
44+
45+
- Variable name: `service_credential_secrets`.
46+
- Type: A list of objects that represent service credential secret groups and secrets
47+
- Default value: An empty list (`[]`)
48+
49+
### Options for service_credential_secrets
50+
51+
- `secret_group_name` (required): A unique human-readable name that identifies this service credential secret group.
52+
- `secret_group_description` (optional, default = `null`): A human-readable description for this secret group.
53+
- `existing_secret_group`: (optional, default = `false`): Set to true, if secret group name provided in the variable `secret_group_name` already exists.
54+
- `service_credentials`: (required): A list of object that represents a service credential secret.
55+
56+
#### Options for service_credentials
57+
58+
- `secret_name`: (required): A unique human-readable name of the secret to create.
59+
- `service_credentials_source_service_role_crn`: (required): The CRN of the role to give the service credential in the IBM Cloud Database service. Service credentials role CRNs can be found at https://cloud.ibm.com/iam/roles, select the IBM Cloud Database and select the role.
60+
- `secret_labels`: (optional, default = `[]`): Labels of the secret to create. Up to 30 labels can be created. Labels can be 2 - 30 characters, including spaces. Special characters that are not permitted include the angled brackets (<>), comma (,), colon (:), ampersand (&), and vertical pipe character (|).
61+
- `secret_auto_rotation`: (optional, default = `true`): Whether to configure automatic rotation of service credential.
62+
- `secret_auto_rotation_unit`: (optional, default = `day`): Specifies the unit of time for rotation of a secret. Acceptable values are `day` or `month`.
63+
- `secret_auto_rotation_interval`: (optional, default = `89`): Specifies the rotation interval for the rotation unit.
64+
- `service_credentials_ttl`: (optional, default = `7776000`): The time-to-live (TTL) to assign to generated service credentials (in seconds).
65+
- `service_credential_secret_description`: (optional, default = `null`): Description of the secret to create.
66+
67+
The following example includes all the configuration options for four service credentials and two secret groups.
68+
```hcl
69+
[
70+
{
71+
"secret_group_name": "sg-1"
72+
"existing_secret_group": true
73+
"service_credentials": [ #pragma: allowlist secret
74+
{
75+
"secret_name": "cred-1"
76+
"service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::role:Writer"
77+
"secret_labels": ["test-writer-1", "test-writer-2"]
78+
"secret_auto_rotation": true
79+
"secret_auto_rotation_unit": "day"
80+
"secret_auto_rotation_interval": 89
81+
"service_credentials_ttl": 7776000
82+
"service_credential_secret_description": "sample description"
83+
},
84+
{
85+
"secret_name": "cred-2"
86+
"service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::role:Reader"
87+
}
88+
]
89+
},
90+
{
91+
"secret_group_name": "sg-2"
92+
"service_credentials": [ #pragma: allowlist secret
93+
{
94+
"secret_name": "cred-3"
95+
"service_credentials_source_service_role_crn": "crn:v1:bluemix:public:iam::::role:Editor"
96+
}
97+
]
98+
}
99+
]
100+
```
101+
32102
## Quotas <a name="quotas"></a>
33103

34104
You can set quotas of an Event Streams service instance. Both the default quota and user quotas may be managed. Quotas are only available on Event Streams Enterprise plan service instances. For more information, see [Event Streams Quotas](https://cloud.ibm.com/docs/EventStreams?topic=EventStreams-enabling_kafka_quotas).

solutions/enterprise/main.tf

+69
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,72 @@ module "event_streams" {
166166
update_timeout = var.update_timeout
167167
delete_timeout = var.delete_timeout
168168
}
169+
170+
########################################################################################################################
171+
# Service Credentials
172+
########################################################################################################################
173+
174+
# If existing EN intance CRN passed, parse details from it
175+
module "existing_sm_crn_parser" {
176+
count = var.existing_secrets_manager_instance_crn != null ? 1 : 0
177+
source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
178+
version = "1.1.0"
179+
crn = var.existing_secrets_manager_instance_crn
180+
}
181+
182+
locals {
183+
# parse SM GUID from CRN
184+
existing_secrets_manager_instance_guid = var.existing_secrets_manager_instance_crn != null ? module.existing_sm_crn_parser[0].service_instance : null
185+
# parse SM region from CRN
186+
existing_secrets_manager_instance_region = var.existing_secrets_manager_instance_crn != null ? module.existing_sm_crn_parser[0].region : null
187+
# generate list of service credential secrets to create
188+
service_credential_secrets = [
189+
for service_credentials in var.service_credential_secrets : {
190+
secret_group_name = service_credentials.secret_group_name
191+
secret_group_description = service_credentials.secret_group_description
192+
existing_secret_group = service_credentials.existing_secret_group
193+
secrets = [
194+
for secret in service_credentials.service_credentials : {
195+
secret_name = secret.secret_name
196+
secret_labels = secret.secret_labels
197+
secret_auto_rotation = secret.secret_auto_rotation
198+
secret_auto_rotation_unit = secret.secret_auto_rotation_unit
199+
secret_auto_rotation_interval = secret.secret_auto_rotation_interval
200+
service_credentials_ttl = secret.service_credentials_ttl
201+
service_credential_secret_description = secret.service_credential_secret_description
202+
service_credentials_source_service_role_crn = secret.service_credentials_source_service_role_crn
203+
service_credentials_source_service_crn = module.event_streams.crn
204+
secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6
205+
}
206+
]
207+
}
208+
]
209+
}
210+
211+
# create a service authorization between Secrets Manager and the target service (Event Streams)
212+
resource "ibm_iam_authorization_policy" "secrets_manager_key_manager" {
213+
count = var.skip_event_streams_secrets_manager_auth_policy || var.existing_secrets_manager_instance_crn == null ? 0 : 1
214+
source_service_name = "secrets-manager"
215+
source_resource_instance_id = local.existing_secrets_manager_instance_guid
216+
target_service_name = "messagehub"
217+
target_resource_instance_id = module.event_streams.guid
218+
roles = ["Key Manager"]
219+
description = "Allow Secrets Manager instance to manage key for the event-streams instance"
220+
}
221+
222+
# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478
223+
resource "time_sleep" "wait_for_en_authorization_policy" {
224+
depends_on = [ibm_iam_authorization_policy.secrets_manager_key_manager]
225+
create_duration = "30s"
226+
}
227+
228+
module "secrets_manager_service_credentials" {
229+
count = length(local.service_credential_secrets) > 0 ? 1 : 0
230+
depends_on = [time_sleep.wait_for_en_authorization_policy]
231+
source = "terraform-ibm-modules/secrets-manager/ibm//modules/secrets"
232+
version = "1.22.0"
233+
existing_sm_instance_guid = local.existing_secrets_manager_instance_guid
234+
existing_sm_instance_region = local.existing_secrets_manager_instance_region
235+
endpoint_type = var.existing_secrets_manager_endpoint_type
236+
secrets = local.service_credential_secrets
237+
}

solutions/enterprise/outputs.tf

+10
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ output "service_credentials_object" {
5353
sensitive = true
5454
}
5555

56+
output "service_credential_secrets" {
57+
description = "Service credential secrets"
58+
value = length(local.service_credential_secrets) > 0 ? module.secrets_manager_service_credentials[0].secrets : null
59+
}
60+
61+
output "service_credential_secret_groups" {
62+
description = "Service credential secret groups"
63+
value = length(local.service_credential_secrets) > 0 ? module.secrets_manager_service_credentials[0].secret_groups : null
64+
}
65+
5666
output "mirroring_config_id" {
5767
description = "The ID of the mirroring config in CRN format"
5868
value = module.event_streams.mirroring_config_id

0 commit comments

Comments
 (0)