Skip to content

Commit f0ebcaf

Browse files
feat: add custom credential support (#413)
1 parent b943c2d commit f0ebcaf

File tree

11 files changed

+180
-6
lines changed

11 files changed

+180
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ You need the following permissions to run this module.
106106
| <a name="input_kms_key_crn"></a> [kms\_key\_crn](#input\_kms\_key\_crn) | The root key CRN of a key management service like Key Protect or Hyper Protect Crypto Services that you want to use for encryption. Only used if `kms_encryption_enabled` is set to `true`. | `string` | `null` | no |
107107
| <a name="input_region"></a> [region](#input\_region) | The region where the instance is created. Not required if passing a value for `existing_sm_instance_crn`. | `string` | `null` | no |
108108
| <a name="input_resource_group_id"></a> [resource\_group\_id](#input\_resource\_group\_id) | The ID of the resource group that contains the Secrets Manager instance. | `string` | n/a | yes |
109-
| <a name="input_secrets"></a> [secrets](#input\_secrets) | Secret Manager secrets configurations. | <pre>list(object({<br/> secret_group_name = string<br/> secret_group_description = optional(string)<br/> existing_secret_group = optional(bool, false)<br/> create_access_group = optional(bool, false)<br/> access_group_name = optional(string)<br/> access_group_roles = optional(list(string))<br/> access_group_tags = optional(list(string))<br/> secrets = optional(list(object({<br/> secret_name = string<br/> secret_description = optional(string)<br/> secret_type = optional(string)<br/> imported_cert_certificate = optional(string)<br/> imported_cert_private_key = optional(string)<br/> imported_cert_intermediate = optional(string)<br/> secret_username = optional(string)<br/> secret_labels = optional(list(string), [])<br/> secret_payload_password = optional(string, "")<br/> secret_auto_rotation = optional(bool, true)<br/> secret_auto_rotation_unit = optional(string, "day")<br/> secret_auto_rotation_interval = optional(number, 89)<br/> service_credentials_ttl = optional(string, "7776000") # 90 days<br/> service_credentials_source_service_crn = optional(string)<br/> service_credentials_source_service_role_crn = optional(string)<br/> })))<br/> }))</pre> | `[]` | no |
109+
| <a name="input_secrets"></a> [secrets](#input\_secrets) | Secret Manager secrets configurations. | <pre>list(object({<br/> secret_group_name = string<br/> secret_group_description = optional(string)<br/> existing_secret_group = optional(bool, false)<br/> create_access_group = optional(bool, false)<br/> access_group_name = optional(string)<br/> access_group_roles = optional(list(string))<br/> access_group_tags = optional(list(string))<br/> secrets = optional(list(object({<br/> secret_name = string<br/> secret_description = optional(string)<br/> secret_type = optional(string)<br/> imported_cert_certificate = optional(string)<br/> imported_cert_private_key = optional(string)<br/> imported_cert_intermediate = optional(string)<br/> secret_username = optional(string)<br/> secret_labels = optional(list(string), [])<br/> secret_payload_password = optional(string, "")<br/> secret_auto_rotation = optional(bool, true)<br/> secret_auto_rotation_unit = optional(string, "day")<br/> secret_auto_rotation_interval = optional(number, 89)<br/> service_credentials_ttl = optional(string, "7776000") # 90 days<br/> service_credentials_source_service_crn = optional(string)<br/> service_credentials_source_service_role_crn = optional(string)<br/> custom_credentials_configurations = optional(string)<br/> custom_credentials_parameters = optional(bool, false)<br/> job_parameters = optional(object({<br/> integer_values = optional(map(number))<br/> string_values = optional(map(string))<br/> boolean_values = optional(map(bool))<br/> }), {})<br/> })))<br/> }))</pre> | `[]` | no |
110110
| <a name="input_secrets_manager_name"></a> [secrets\_manager\_name](#input\_secrets\_manager\_name) | The name of the Secrets Manager instance to create | `string` | n/a | yes |
111111
| <a name="input_skip_en_iam_authorization_policy"></a> [skip\_en\_iam\_authorization\_policy](#input\_skip\_en\_iam\_authorization\_policy) | Set to true to skip creating 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. No policy is created if `enable_event_notification` is set to `false`. | `bool` | `false` | no |
112112
| <a name="input_skip_iam_authorization_policy"></a> [skip\_iam\_authorization\_policy](#input\_skip\_iam\_authorization\_policy) | Whether to skip creating the IAM authorization policies that are required to enable the IAM credentials engine. If set to `false`, policies are created that grant the Secrets Manager instance 'Operator' access to the IAM identity service, and 'Groups Service Member Manager' access to the IAM groups service. | `bool` | `false` | no |

examples/complete/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,33 @@ This examples handles the provisioning of a new Secrets Manager instance.
88
| Name | Version |
99
|------|---------|
1010
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= v1.9.0 |
11+
| <a name="requirement_http"></a> [http](#requirement\_http) | 3.2.1 |
1112
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >=1.79.0 |
1213
| <a name="requirement_time"></a> [time](#requirement\_time) | 0.12.1 |
1314

1415
### Modules
1516

1617
| Name | Source | Version |
1718
|------|--------|---------|
19+
| <a name="module_code_engine_build"></a> [code\_engine\_build](#module\_code\_engine\_build) | terraform-ibm-modules/code-engine/ibm//modules/build | 4.5.8 |
20+
| <a name="module_code_engine_job"></a> [code\_engine\_job](#module\_code\_engine\_job) | terraform-ibm-modules/code-engine/ibm//modules/job | 4.5.8 |
21+
| <a name="module_code_engine_project"></a> [code\_engine\_project](#module\_code\_engine\_project) | terraform-ibm-modules/code-engine/ibm//modules/project | 4.5.8 |
22+
| <a name="module_code_engine_secret"></a> [code\_engine\_secret](#module\_code\_engine\_secret) | terraform-ibm-modules/code-engine/ibm//modules/secret | 4.5.8 |
23+
| <a name="module_custom_credential_engine"></a> [custom\_credential\_engine](#module\_custom\_credential\_engine) | terraform-ibm-modules/secrets-manager-custom-credentials-engine/ibm | 1.0.0 |
1824
| <a name="module_event_notification"></a> [event\_notification](#module\_event\_notification) | terraform-ibm-modules/event-notifications/ibm | 2.6.24 |
1925
| <a name="module_key_protect"></a> [key\_protect](#module\_key\_protect) | terraform-ibm-modules/kms-all-inclusive/ibm | 5.1.24 |
2026
| <a name="module_resource_group"></a> [resource\_group](#module\_resource\_group) | terraform-ibm-modules/resource-group/ibm | 1.3.0 |
27+
| <a name="module_secret_manager_custom_credential"></a> [secret\_manager\_custom\_credential](#module\_secret\_manager\_custom\_credential) | terraform-ibm-modules/secrets-manager-secret/ibm | 1.9.0 |
2128
| <a name="module_secrets_manager"></a> [secrets\_manager](#module\_secrets\_manager) | ../.. | n/a |
2229

2330
### Resources
2431

2532
| Name | Type |
2633
|------|------|
34+
| [ibm_cr_namespace.rg_namespace](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/cr_namespace) | resource |
2735
| [ibm_iam_authorization_policy.en_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource |
2836
| [time_sleep.wait_for_en_policy](https://registry.terraform.io/providers/hashicorp/time/0.12.1/docs/resources/sleep) | resource |
37+
| [http_http.job_config](https://registry.terraform.io/providers/hashicorp/http/3.2.1/docs/data-sources/http) | data source |
2938

3039
### Inputs
3140

examples/complete/main.tf

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ module "secrets_manager" {
8181
secret_description = "Created by secrets-manager-module complete example"
8282
service_credentials_source_service_crn = module.event_notification.crn
8383
service_credentials_source_service_role_crn = "crn:v1:bluemix:public:event-notifications::::serviceRole:Event-Notification-Publisher"
84+
},
85+
{
86+
secret_name = "${var.prefix}-custom-service-credential"
87+
secret_type = "arbitrary"
88+
secret_payload_password = var.ibmcloud_api_key
8489
}
8590
]
8691
},
@@ -96,3 +101,135 @@ module "secrets_manager" {
96101
}
97102
]
98103
}
104+
105+
##############################################################################
106+
# Code Engine Project
107+
##############################################################################
108+
module "code_engine_project" {
109+
source = "terraform-ibm-modules/code-engine/ibm//modules/project"
110+
version = "4.5.8"
111+
name = "${var.prefix}-project"
112+
resource_group_id = module.resource_group.resource_group_id
113+
}
114+
115+
##############################################################################
116+
# Code Engine Secret
117+
##############################################################################
118+
locals {
119+
registry_hostname = "private.de.icr.io"
120+
output_image = "${local.registry_hostname}/${resource.ibm_cr_namespace.rg_namespace.name}/custom-engine-job"
121+
}
122+
123+
module "code_engine_secret" {
124+
source = "terraform-ibm-modules/code-engine/ibm//modules/secret"
125+
version = "4.5.8"
126+
name = "${var.prefix}-rs"
127+
project_id = module.code_engine_project.id
128+
format = "registry"
129+
data = {
130+
"server" = local.registry_hostname,
131+
"username" = "iamapikey",
132+
"password" = var.ibmcloud_api_key,
133+
}
134+
}
135+
136+
##############################################################################
137+
# Container Registry Namespace
138+
##############################################################################
139+
resource "ibm_cr_namespace" "rg_namespace" {
140+
name = "${var.prefix}-crn"
141+
resource_group_id = module.resource_group.resource_group_id
142+
}
143+
144+
##############################################################################
145+
# Code Engine Build
146+
##############################################################################
147+
148+
# For example the region is hardcoded to us-south in order to hardcode the output image and region for creating Code Engine Project and build
149+
module "code_engine_build" {
150+
source = "terraform-ibm-modules/code-engine/ibm//modules/build"
151+
version = "4.5.8"
152+
name = "${var.prefix}-build"
153+
region = var.region
154+
ibmcloud_api_key = var.ibmcloud_api_key
155+
project_id = module.code_engine_project.id
156+
existing_resource_group_id = module.resource_group.resource_group_id
157+
source_url = "https://github.com/IBM/secrets-manager-custom-credentials-providers"
158+
source_context_dir = "ibmcloud-iam-user-apikey-provider-go"
159+
strategy_type = "dockerfile"
160+
output_secret = module.code_engine_secret.name
161+
output_image = local.output_image
162+
}
163+
164+
##############################################################################
165+
# Code Engine Job
166+
##############################################################################
167+
168+
data "http" "job_config" {
169+
url = "https://raw.githubusercontent.com/IBM/secrets-manager-custom-credentials-providers/refs/heads/main/ibmcloud-iam-user-apikey-provider-go/job_config.json"
170+
request_headers = {
171+
Accept = "application/json"
172+
}
173+
}
174+
175+
locals {
176+
job_env_variables = jsondecode(data.http.job_config.response_body).job_env_variables
177+
}
178+
179+
module "code_engine_job" {
180+
depends_on = [module.code_engine_build]
181+
source = "terraform-ibm-modules/code-engine/ibm//modules/job"
182+
version = "4.5.8"
183+
name = "${var.prefix}-job"
184+
image_reference = local.output_image
185+
image_secret = module.code_engine_secret.name
186+
project_id = module.code_engine_project.id
187+
run_env_variables = [
188+
for env_var in local.job_env_variables : {
189+
type = "literal"
190+
name = env_var.name
191+
value = tostring(env_var.value)
192+
}
193+
]
194+
}
195+
196+
##############################################################################
197+
# Custom Credential Engine and secret
198+
##############################################################################
199+
200+
module "custom_credential_engine" {
201+
depends_on = [module.secrets_manager, module.code_engine_job]
202+
source = "terraform-ibm-modules/secrets-manager-custom-credentials-engine/ibm"
203+
version = "1.0.0"
204+
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
205+
secrets_manager_region = module.secrets_manager.secrets_manager_region
206+
custom_credential_engine_name = "${var.prefix}-test-custom-engine"
207+
endpoint_type = "public"
208+
code_engine_project_id = module.code_engine_project.project_id
209+
code_engine_job_name = module.code_engine_job.name
210+
code_engine_region = var.region
211+
task_timeout = "10m"
212+
service_id_name = "${var.prefix}-test-service-id"
213+
iam_credential_secret_name = "${var.prefix}-test-iam-secret"
214+
}
215+
216+
# Currently the main module cannot be called again as some of the count for resources depends on a computable input existing_en_instance_crn which will give error if the value is not available during planning
217+
# As a workaround the secret manager secret is directly being created via module call
218+
module "secret_manager_custom_credential" {
219+
depends_on = [module.secrets_manager, module.custom_credential_engine]
220+
source = "terraform-ibm-modules/secrets-manager-secret/ibm"
221+
version = "1.9.0"
222+
secret_type = "custom_credentials" #checkov:skip=CKV_SECRET_6
223+
region = module.secrets_manager.secrets_manager_region
224+
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
225+
secret_name = "${var.prefix}-custom-credentials"
226+
secret_description = "created by secrets-manager module complete example"
227+
custom_credentials_configurations = module.custom_credential_engine.custom_config_engine_name
228+
custom_metadata = { "metadata_custom_key" : "metadata_custom_value" } # can add any custom metadata here
229+
custom_credentials_parameters = true
230+
job_parameters = {
231+
string_values = {
232+
apikey_secret_id = module.secrets_manager.secrets["${var.prefix}-custom-service-credential"].secret_id
233+
}
234+
}
235+
}

examples/complete/variables.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ variable "sm_service_plan" {
1818
variable "region" {
1919
type = string
2020
description = "Region where resources will be created"
21-
default = "eu-de"
21+
default = "eu-de" # Region is defaulted to eu-de in order to restrict the code engine project and build creation with a hardcoded output image `private.de`
2222
}
2323

2424
variable "resource_group" {

examples/complete/version.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@ terraform {
99
source = "hashicorp/time"
1010
version = "0.12.1"
1111
}
12+
http = {
13+
source = "hashicorp/http"
14+
version = "3.2.1"
15+
}
1216
}
1317
}

0 commit comments

Comments
 (0)