Skip to content

Commit d929569

Browse files
feat: allow creation of the key_value secret type (#338)
* add: kv (key_value) secret type
1 parent 6a98e85 commit d929569

File tree

8 files changed

+161
-11
lines changed

8 files changed

+161
-11
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ The module supports the following secret types:
1414
- [User credentials](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-user-credentials&interface=ui)
1515
- [Imported Certificate](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-certificates&interface=api#import-certificates)
1616
- [Service Credentials](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-service-credentials&interface=api)
17+
- [Key Value](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-key-value&interface=ui)
1718

1819
The following attributes and parameters are supported for all secret types:
1920

@@ -49,6 +50,11 @@ The following attributes and parameters are supported when creating service cred
4950
- `secret_auto_rotation_unit`: Specifies the unit type for the secret rotation. Accepted values are `day` or `month`. Default is `day`.
5051
- `secret_auto_rotation_interval`: Specifies the rotation interval for the rotation unit. Default is `89`.
5152

53+
The following attributes and parameters are supported when creating Key Value secrets:
54+
55+
- `secret_kv_data`: key-value secret data.
56+
57+
5258
<!-- Below content is automatically populated via pre-commit hook -->
5359
<!-- BEGIN OVERVIEW HOOK -->
5460
## Overview
@@ -140,6 +146,23 @@ module "secret_manager_service_credential" {
140146
}
141147
```
142148

149+
```hcl
150+
##############################################################################
151+
# Create Key Value Secret
152+
##############################################################################
153+
154+
module "secrets_manager_key_value_secret" {
155+
source = "terraform-ibm-modules/secrets-manager-secret/ibm"
156+
version = "latest" # Replace "latest" with a release version to lock into a specific release
157+
region = "us-south"
158+
secrets_manager_guid = "42454b3b-5b06-407b-a4b3-34d9ef323901"
159+
secret_group_id = "432b91f1-ff6d-4b47-9f06-82debc236d90"
160+
secret_name = "example-kv-secret"
161+
secret_description = "Extended description for the key-value secret."
162+
secret_type = "key_value"
163+
secret_kv_data = {"key1":"value"} #pragma: allowlist secret
164+
}
165+
```
143166
### Required IAM access policies
144167
You need the following permissions to run this module.
145168

@@ -169,6 +192,7 @@ No modules.
169192
|------|------|
170193
| [ibm_sm_arbitrary_secret.arbitrary_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_arbitrary_secret) | resource |
171194
| [ibm_sm_imported_certificate.imported_cert](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_imported_certificate) | resource |
195+
| [ibm_sm_kv_secret.kv_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_kv_secret) | resource |
172196
| [ibm_sm_service_credentials_secret.service_credentials_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_service_credentials_secret) | resource |
173197
| [ibm_sm_username_password_secret.username_password_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_username_password_secret) | resource |
174198

@@ -187,6 +211,7 @@ No modules.
187211
| <a name="input_secret_auto_rotation_unit"></a> [secret\_auto\_rotation\_unit](#input\_secret\_auto\_rotation\_unit) | Specifies the unit of time for rotation of a username\_password secret. Acceptable values are `day` or `month`. | `string` | `"day"` | no |
188212
| <a name="input_secret_description"></a> [secret\_description](#input\_secret\_description) | Description of the secret to create. | `string` | n/a | yes |
189213
| <a name="input_secret_group_id"></a> [secret\_group\_id](#input\_secret\_group\_id) | The ID of the secret group for the secret. If `null`, the `default` secret group is used. | `string` | `"default"` | no |
214+
| <a name="input_secret_kv_data"></a> [secret\_kv\_data](#input\_secret\_kv\_data) | key-value secret data | `map(string)` | `null` | no |
190215
| <a name="input_secret_labels"></a> [secret\_labels](#input\_secret\_labels) | 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 (\|). | `list(string)` | `[]` | no |
191216
| <a name="input_secret_name"></a> [secret\_name](#input\_secret\_name) | Name of the secret to create. | `string` | n/a | yes |
192217
| <a name="input_secret_payload_password"></a> [secret\_payload\_password](#input\_secret\_payload\_password) | The payload (for arbitrary secrets) or password (for username and password credentials) of the secret. | `string` | `""` | no |

examples/complete/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- Creates new secrets-manager instance (if existing instance GUID not passed in)
44
- Creates new secret group
55
- Creates an arbitrary type secret in the secret group
6+
- Creates an key-value type secret in the secret group
67
- Creates a username_password type secret in the secret group
78
- Creates a TLS cert, and adds it to secrets manager as an imported_cert secret type in the secret group
89
- Retrieves metadata for all the secrets created

examples/complete/main.tf

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
locals {
66
payload = sensitive("secret-payload-example")
7+
kv_data = { "key1" : "value", "key2" : true, "key3" : 4 }
78

89
sm_guid = var.existing_sm_instance_guid == null ? module.secrets_manager[0].secrets_manager_guid : var.existing_sm_instance_guid
910
sm_region = var.existing_sm_instance_region == null ? var.region : var.existing_sm_instance_region
@@ -234,3 +235,28 @@ module "secret_manager_service_credential" {
234235
service_credentials_parameters = { "service-endpoints" : "public" }
235236
custom_metadata = { "metadata_custom_key" : "metadata_custom_value" } # can add any custom metadata here
236237
}
238+
239+
##############################################################################
240+
# Example working with key-value secret
241+
##############################################################################
242+
243+
# create key-value secret
244+
module "secrets_manager_key_value_secret" {
245+
source = "../.."
246+
region = local.sm_region
247+
secrets_manager_guid = local.sm_guid
248+
secret_group_id = module.secrets_manager_group.secret_group_id
249+
secret_name = "${var.prefix}-key-value-secret"
250+
secret_description = "created by secrets-manager-secret-module complete example"
251+
secret_type = "key_value"
252+
secret_kv_data = local.kv_data
253+
secret_labels = local.secret_labels
254+
custom_metadata = { "metadata_custom_key" : "metadata_custom_value" } # can add any custom metadata here
255+
}
256+
257+
# retrieving information about the key-value secret
258+
data "ibm_sm_kv_secret" "kv_secret" {
259+
instance_id = local.sm_guid
260+
region = local.sm_region
261+
secret_id = module.secrets_manager_key_value_secret.secret_id
262+
}

examples/complete/outputs.tf

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,25 @@ output "service_credential_secret_crn" {
8383
description = "CRN of the created service_credential secret"
8484
value = module.secret_manager_service_credential.secret_crn
8585
}
86+
87+
output "kv_secret_id" {
88+
description = "ID of the created kv_secret_id secret"
89+
value = module.secrets_manager_key_value_secret.secret_id
90+
}
91+
92+
output "kv_secret_crn" {
93+
description = "CRN of the created kv_secret_id secret"
94+
value = module.secrets_manager_key_value_secret.secret_crn
95+
}
96+
97+
output "kv_secret_nonsensitive_payload" {
98+
value = nonsensitive(data.ibm_sm_kv_secret.kv_secret.data)
99+
description = "accessing key value secret"
100+
sensitive = false
101+
}
102+
103+
output "kv_secret_payload" {
104+
value = data.ibm_sm_kv_secret.kv_secret.data
105+
sensitive = true
106+
description = "accessing key value secret"
107+
}

examples/private/main.tf

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
##############################################################################
44

55
locals {
6-
payload = sensitive("secret-payload-example")
6+
payload = sensitive("secret-payload-example")
7+
kv_data = { "key1" : "value", "key2" : true, "key3" : 4 }
8+
79
secret_labels = [var.prefix, var.region]
810
sm_region = var.existing_sm_instance_region == null ? var.region : var.existing_sm_instance_region
911
}
@@ -48,7 +50,7 @@ module "secrets_manager_group" {
4850
region = local.sm_region
4951
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
5052
secret_group_name = "${var.prefix}-group"
51-
secret_group_description = "created by secrets-manager-secret-module complete example"
53+
secret_group_description = "created by secrets-manager-secret-module private example"
5254
endpoint_type = "private"
5355
}
5456

@@ -63,7 +65,7 @@ module "secrets_manager_arbitrary_secret" {
6365
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
6466
secret_group_id = module.secrets_manager_group.secret_group_id
6567
secret_name = "${var.prefix}-arbitrary-secret"
66-
secret_description = "created by secrets-manager-secret-module complete example"
68+
secret_description = "created by secrets-manager-secret-module private example"
6769
secret_type = "arbitrary" #checkov:skip=CKV_SECRET_6
6870
secret_payload_password = local.payload
6971
secret_labels = local.secret_labels
@@ -89,7 +91,7 @@ module "secrets_manager_user_pass_secret" {
8991
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
9092
secret_group_id = module.secrets_manager_group.secret_group_id
9193
secret_name = "${var.prefix}-user-pass-secret"
92-
secret_description = "created by secrets-manager-secret-module complete example"
94+
secret_description = "created by secrets-manager-secret-module private example"
9395
secret_type = "username_password" #checkov:skip=CKV_SECRET_6
9496
secret_payload_password = local.payload
9597
secret_username = "terraform-user" #checkov:skip=CKV_SECRET_6
@@ -116,7 +118,7 @@ module "secrets_manager_user_pass_no_rotate_secret" {
116118
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
117119
secret_group_id = module.secrets_manager_group.secret_group_id
118120
secret_name = "${var.prefix}-user-pass-no-rotate-secret"
119-
secret_description = "created by secrets-manager-secret-module complete example"
121+
secret_description = "created by secrets-manager-secret-module private example"
120122
secret_type = "username_password" #checkov:skip=CKV_SECRET_6
121123
secret_payload_password = local.payload
122124
secret_username = "terraform-user" #checkov:skip=CKV_SECRET_6
@@ -183,7 +185,7 @@ module "secret_manager_imported_cert" {
183185
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
184186
secret_name = "${var.prefix}-imported-cert"
185187
secret_group_id = module.secrets_manager_group.secret_group_id
186-
secret_description = "created by secrets-manager-secret-module complete example"
188+
secret_description = "created by secrets-manager-secret-module private example"
187189
secret_type = "imported_cert" #checkov:skip=CKV_SECRET_6
188190
imported_cert_certificate = resource.tls_locally_signed_cert.cert.cert_pem
189191
imported_cert_private_key = resource.tls_private_key.key.private_key_pem
@@ -231,9 +233,34 @@ module "secret_manager_service_credential" {
231233
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
232234
secret_name = "${var.prefix}-service-credentials"
233235
secret_group_id = module.secrets_manager_group.secret_group_id
234-
secret_description = "created by secrets-manager-secret-module complete example"
236+
secret_description = "created by secrets-manager-secret-module private example"
235237
secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6
236238
service_credentials_source_service_crn = module.cloud_object_storage.cos_instance_id
237239
service_credentials_source_service_role_crn = "crn:v1:bluemix:public:iam::::serviceRole:Writer"
238240
endpoint_type = "private"
239241
}
242+
##############################################################################
243+
# Example working with key-value secret
244+
##############################################################################
245+
246+
# create key-value secret
247+
module "secrets_manager_key_value_secret" {
248+
source = "../.."
249+
region = local.sm_region
250+
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
251+
secret_group_id = module.secrets_manager_group.secret_group_id
252+
secret_name = "${var.prefix}-key-value-secret"
253+
secret_description = "created by secrets-manager-secret-module private example"
254+
secret_type = "key_value"
255+
secret_kv_data = local.kv_data
256+
secret_labels = local.secret_labels
257+
endpoint_type = "private"
258+
}
259+
260+
# retrieving information about the key-value secret
261+
data "ibm_sm_kv_secret" "kv_secret" {
262+
instance_id = module.secrets_manager.secrets_manager_guid
263+
region = local.sm_region
264+
secret_id = module.secrets_manager_key_value_secret.secret_id
265+
endpoint_type = "private"
266+
}

examples/private/outputs.tf

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,25 @@ output "service_credential_secret_crn" {
8383
description = "CRN of the created service_credential secret"
8484
value = module.secret_manager_service_credential.secret_crn
8585
}
86+
87+
output "kv_secret_id" {
88+
description = "ID of the created kv_secret_id secret"
89+
value = module.secrets_manager_key_value_secret.secret_id
90+
}
91+
92+
output "kv_secret_crn" {
93+
description = "CRN of the created kv_secret_id secret"
94+
value = module.secrets_manager_key_value_secret.secret_crn
95+
}
96+
97+
output "kv_secret_nonsensitive_payload" {
98+
value = nonsensitive(data.ibm_sm_kv_secret.kv_secret.data)
99+
description = "accessing key value secret"
100+
sensitive = false
101+
}
102+
103+
output "kv_secret_payload" {
104+
value = data.ibm_sm_kv_secret.kv_secret.data
105+
sensitive = true
106+
description = "accessing key value secret"
107+
}

main.tf

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,34 @@ resource "ibm_sm_service_credentials_secret" "service_credentials_secret" {
116116
}
117117
}
118118

119+
resource "ibm_sm_kv_secret" "kv_secret" {
120+
count = var.secret_type == "key_value" ? 1 : 0
121+
region = var.region
122+
instance_id = var.secrets_manager_guid
123+
secret_group_id = var.secret_group_id
124+
name = var.secret_name
125+
description = var.secret_description
126+
labels = var.secret_labels
127+
data = var.secret_kv_data
128+
endpoint_type = var.endpoint_type
129+
custom_metadata = var.custom_metadata
130+
}
131+
119132
# Parse secret ID and generate data header for secrets
120133
locals {
121134
secret_id = (
122135
var.secret_type == "username_password" ? ibm_sm_username_password_secret.username_password_secret[0].secret_id :
123136
var.secret_type == "imported_cert" ? ibm_sm_imported_certificate.imported_cert[0].secret_id :
124137
var.secret_type == "service_credentials" ? ibm_sm_service_credentials_secret.service_credentials_secret[0].secret_id :
125-
var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].secret_id : null
138+
var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].secret_id :
139+
var.secret_type == "key_value" ? ibm_sm_kv_secret.kv_secret[0].secret_id : null
126140
)
127141
secret_crn = (
128142
var.secret_type == "username_password" ? ibm_sm_username_password_secret.username_password_secret[0].crn :
129143
var.secret_type == "imported_cert" ? ibm_sm_imported_certificate.imported_cert[0].crn :
130144
var.secret_type == "service_credentials" ? ibm_sm_service_credentials_secret.service_credentials_secret[0].crn :
131-
var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].crn : null
145+
var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].crn :
146+
var.secret_type == "key_value" ? ibm_sm_kv_secret.kv_secret[0].crn : null
132147
)
133148
#tfsec:ignore:general-secrets-no-plaintext-exposure
134149
secret_auto_rotation_frequency = var.secret_auto_rotation == true ? "${var.secret_auto_rotation_interval} ${var.secret_auto_rotation_unit}(s)" : null #tfsec:ignore:general-secrets-no-plaintext-exposure

variables.tf

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,20 @@ variable "secret_type" {
2323
description = "Type of secret to create, must be one of: arbitrary, username_password, imported_cert, service_credentials"
2424

2525
validation {
26-
condition = contains(["arbitrary", "username_password", "imported_cert", "service_credentials"], var.secret_type) #checkov:skip=CKV_SECRET_6
27-
error_message = "Only supported secrets types are arbitrary, username_password, imported_cert, or service_credentials"
26+
condition = contains(["arbitrary", "username_password", "imported_cert", "key_value", "service_credentials"], var.secret_type) #checkov:skip=CKV_SECRET_6
27+
error_message = "Only supported secrets types are arbitrary, username_password, key_value , imported_cert, or service_credentials"
2828
}
2929

3030
validation {
3131
condition = (var.secret_type == "username_password" || var.secret_type == "arbitrary") ? var.secret_payload_password != "" : true
3232
error_message = "When creating a username_password or arbitrary secret, a value for `secret_payload_password` is required."
3333
}
3434

35+
validation {
36+
condition = var.secret_type == "key_value" ? var.secret_kv_data != null : true
37+
error_message = "When creating a key_value secret, a value for `secret_kv_data` is required."
38+
}
39+
3540
validation {
3641
condition = var.secret_type == "imported_cert" ? var.imported_cert_certificate != null : true
3742
error_message = "When creating an imported_cert secret, value for `imported_cert_certificate` cannot be null."
@@ -96,6 +101,13 @@ variable "secret_payload_password" {
96101
default = "" #tfsec:ignore:general-secrets-no-plaintext-exposure
97102
}
98103

104+
variable "secret_kv_data" {
105+
type = map(string)
106+
description = "key-value secret data"
107+
sensitive = true
108+
default = null
109+
}
110+
99111
variable "secret_auto_rotation" {
100112
type = bool
101113
description = "Whether to configure automatic rotation. Applies only to the `username_password` and `service_credentials` secret types."

0 commit comments

Comments
 (0)