diff --git a/README.md b/README.md
index cfd28aa..94f19c3 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,7 @@ The module supports the following secret types:
- [User credentials](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-user-credentials&interface=ui)
- [Imported Certificate](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-certificates&interface=api#import-certificates)
- [Service Credentials](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-service-credentials&interface=api)
+- [Key Value](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-key-value&interface=ui)
The following attributes and parameters are supported for all secret types:
@@ -49,6 +50,11 @@ The following attributes and parameters are supported when creating service cred
- `secret_auto_rotation_unit`: Specifies the unit type for the secret rotation. Accepted values are `day` or `month`. Default is `day`.
- `secret_auto_rotation_interval`: Specifies the rotation interval for the rotation unit. Default is `89`.
+The following attributes and parameters are supported when creating Key Value secrets:
+
+- `secret_kv_data`: key-value secret data.
+
+
## Overview
@@ -140,6 +146,23 @@ module "secret_manager_service_credential" {
}
```
+```hcl
+##############################################################################
+# Create Key Value Secret
+##############################################################################
+
+module "secrets_manager_key_value_secret" {
+ source = "terraform-ibm-modules/secrets-manager-secret/ibm"
+ version = "latest" # Replace "latest" with a release version to lock into a specific release
+ region = "us-south"
+ secrets_manager_guid = "42454b3b-5b06-407b-a4b3-34d9ef323901"
+ secret_group_id = "432b91f1-ff6d-4b47-9f06-82debc236d90"
+ secret_name = "example-kv-secret"
+ secret_description = "Extended description for the key-value secret."
+ secret_type = "key_value"
+ secret_kv_data = {"key1":"value"} #pragma: allowlist secret
+}
+```
### Required IAM access policies
You need the following permissions to run this module.
@@ -169,6 +192,7 @@ No modules.
|------|------|
| [ibm_sm_arbitrary_secret.arbitrary_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_arbitrary_secret) | resource |
| [ibm_sm_imported_certificate.imported_cert](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_imported_certificate) | resource |
+| [ibm_sm_kv_secret.kv_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_kv_secret) | resource |
| [ibm_sm_service_credentials_secret.service_credentials_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_service_credentials_secret) | resource |
| [ibm_sm_username_password_secret.username_password_secret](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_username_password_secret) | resource |
@@ -187,6 +211,7 @@ No modules.
| [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 |
| [secret\_description](#input\_secret\_description) | Description of the secret to create. | `string` | n/a | yes |
| [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 |
+| [secret\_kv\_data](#input\_secret\_kv\_data) | key-value secret data | `map(string)` | `null` | no |
| [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 |
| [secret\_name](#input\_secret\_name) | Name of the secret to create. | `string` | n/a | yes |
| [secret\_payload\_password](#input\_secret\_payload\_password) | The payload (for arbitrary secrets) or password (for username and password credentials) of the secret. | `string` | `""` | no |
diff --git a/examples/complete/README.md b/examples/complete/README.md
index 0d020ed..9cf8c8c 100644
--- a/examples/complete/README.md
+++ b/examples/complete/README.md
@@ -3,6 +3,7 @@
- Creates new secrets-manager instance (if existing instance GUID not passed in)
- Creates new secret group
- Creates an arbitrary type secret in the secret group
+- Creates an key-value type secret in the secret group
- Creates a username_password type secret in the secret group
- Creates a TLS cert, and adds it to secrets manager as an imported_cert secret type in the secret group
- Retrieves metadata for all the secrets created
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
index c2eb6dd..a480729 100644
--- a/examples/complete/main.tf
+++ b/examples/complete/main.tf
@@ -4,6 +4,7 @@
locals {
payload = sensitive("secret-payload-example")
+ kv_data = { "key1" : "value", "key2" : true, "key3" : 4 }
sm_guid = var.existing_sm_instance_guid == null ? module.secrets_manager[0].secrets_manager_guid : var.existing_sm_instance_guid
sm_region = var.existing_sm_instance_region == null ? var.region : var.existing_sm_instance_region
@@ -234,3 +235,28 @@ module "secret_manager_service_credential" {
service_credentials_parameters = { "service-endpoints" : "public" }
custom_metadata = { "metadata_custom_key" : "metadata_custom_value" } # can add any custom metadata here
}
+
+##############################################################################
+# Example working with key-value secret
+##############################################################################
+
+# create key-value secret
+module "secrets_manager_key_value_secret" {
+ source = "../.."
+ region = local.sm_region
+ secrets_manager_guid = local.sm_guid
+ secret_group_id = module.secrets_manager_group.secret_group_id
+ secret_name = "${var.prefix}-key-value-secret"
+ secret_description = "created by secrets-manager-secret-module complete example"
+ secret_type = "key_value"
+ secret_kv_data = local.kv_data
+ secret_labels = local.secret_labels
+ custom_metadata = { "metadata_custom_key" : "metadata_custom_value" } # can add any custom metadata here
+}
+
+# retrieving information about the key-value secret
+data "ibm_sm_kv_secret" "kv_secret" {
+ instance_id = local.sm_guid
+ region = local.sm_region
+ secret_id = module.secrets_manager_key_value_secret.secret_id
+}
diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf
index 8b04181..b669c54 100644
--- a/examples/complete/outputs.tf
+++ b/examples/complete/outputs.tf
@@ -83,3 +83,25 @@ output "service_credential_secret_crn" {
description = "CRN of the created service_credential secret"
value = module.secret_manager_service_credential.secret_crn
}
+
+output "kv_secret_id" {
+ description = "ID of the created kv_secret_id secret"
+ value = module.secrets_manager_key_value_secret.secret_id
+}
+
+output "kv_secret_crn" {
+ description = "CRN of the created kv_secret_id secret"
+ value = module.secrets_manager_key_value_secret.secret_crn
+}
+
+output "kv_secret_nonsensitive_payload" {
+ value = nonsensitive(data.ibm_sm_kv_secret.kv_secret.data)
+ description = "accessing key value secret"
+ sensitive = false
+}
+
+output "kv_secret_payload" {
+ value = data.ibm_sm_kv_secret.kv_secret.data
+ sensitive = true
+ description = "accessing key value secret"
+}
diff --git a/examples/private/main.tf b/examples/private/main.tf
index c21589b..c52f2f9 100644
--- a/examples/private/main.tf
+++ b/examples/private/main.tf
@@ -3,7 +3,9 @@
##############################################################################
locals {
- payload = sensitive("secret-payload-example")
+ payload = sensitive("secret-payload-example")
+ kv_data = { "key1" : "value", "key2" : true, "key3" : 4 }
+
secret_labels = [var.prefix, var.region]
sm_region = var.existing_sm_instance_region == null ? var.region : var.existing_sm_instance_region
}
@@ -48,7 +50,7 @@ module "secrets_manager_group" {
region = local.sm_region
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
secret_group_name = "${var.prefix}-group"
- secret_group_description = "created by secrets-manager-secret-module complete example"
+ secret_group_description = "created by secrets-manager-secret-module private example"
endpoint_type = "private"
}
@@ -63,7 +65,7 @@ module "secrets_manager_arbitrary_secret" {
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
secret_group_id = module.secrets_manager_group.secret_group_id
secret_name = "${var.prefix}-arbitrary-secret"
- secret_description = "created by secrets-manager-secret-module complete example"
+ secret_description = "created by secrets-manager-secret-module private example"
secret_type = "arbitrary" #checkov:skip=CKV_SECRET_6
secret_payload_password = local.payload
secret_labels = local.secret_labels
@@ -89,7 +91,7 @@ module "secrets_manager_user_pass_secret" {
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
secret_group_id = module.secrets_manager_group.secret_group_id
secret_name = "${var.prefix}-user-pass-secret"
- secret_description = "created by secrets-manager-secret-module complete example"
+ secret_description = "created by secrets-manager-secret-module private example"
secret_type = "username_password" #checkov:skip=CKV_SECRET_6
secret_payload_password = local.payload
secret_username = "terraform-user" #checkov:skip=CKV_SECRET_6
@@ -116,7 +118,7 @@ module "secrets_manager_user_pass_no_rotate_secret" {
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
secret_group_id = module.secrets_manager_group.secret_group_id
secret_name = "${var.prefix}-user-pass-no-rotate-secret"
- secret_description = "created by secrets-manager-secret-module complete example"
+ secret_description = "created by secrets-manager-secret-module private example"
secret_type = "username_password" #checkov:skip=CKV_SECRET_6
secret_payload_password = local.payload
secret_username = "terraform-user" #checkov:skip=CKV_SECRET_6
@@ -183,7 +185,7 @@ module "secret_manager_imported_cert" {
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
secret_name = "${var.prefix}-imported-cert"
secret_group_id = module.secrets_manager_group.secret_group_id
- secret_description = "created by secrets-manager-secret-module complete example"
+ secret_description = "created by secrets-manager-secret-module private example"
secret_type = "imported_cert" #checkov:skip=CKV_SECRET_6
imported_cert_certificate = resource.tls_locally_signed_cert.cert.cert_pem
imported_cert_private_key = resource.tls_private_key.key.private_key_pem
@@ -231,9 +233,34 @@ module "secret_manager_service_credential" {
secrets_manager_guid = module.secrets_manager.secrets_manager_guid
secret_name = "${var.prefix}-service-credentials"
secret_group_id = module.secrets_manager_group.secret_group_id
- secret_description = "created by secrets-manager-secret-module complete example"
+ secret_description = "created by secrets-manager-secret-module private example"
secret_type = "service_credentials" #checkov:skip=CKV_SECRET_6
service_credentials_source_service_crn = module.cloud_object_storage.cos_instance_id
service_credentials_source_service_role_crn = "crn:v1:bluemix:public:iam::::serviceRole:Writer"
endpoint_type = "private"
}
+##############################################################################
+# Example working with key-value secret
+##############################################################################
+
+# create key-value secret
+module "secrets_manager_key_value_secret" {
+ source = "../.."
+ region = local.sm_region
+ secrets_manager_guid = module.secrets_manager.secrets_manager_guid
+ secret_group_id = module.secrets_manager_group.secret_group_id
+ secret_name = "${var.prefix}-key-value-secret"
+ secret_description = "created by secrets-manager-secret-module private example"
+ secret_type = "key_value"
+ secret_kv_data = local.kv_data
+ secret_labels = local.secret_labels
+ endpoint_type = "private"
+}
+
+# retrieving information about the key-value secret
+data "ibm_sm_kv_secret" "kv_secret" {
+ instance_id = module.secrets_manager.secrets_manager_guid
+ region = local.sm_region
+ secret_id = module.secrets_manager_key_value_secret.secret_id
+ endpoint_type = "private"
+}
diff --git a/examples/private/outputs.tf b/examples/private/outputs.tf
index 8b04181..b669c54 100644
--- a/examples/private/outputs.tf
+++ b/examples/private/outputs.tf
@@ -83,3 +83,25 @@ output "service_credential_secret_crn" {
description = "CRN of the created service_credential secret"
value = module.secret_manager_service_credential.secret_crn
}
+
+output "kv_secret_id" {
+ description = "ID of the created kv_secret_id secret"
+ value = module.secrets_manager_key_value_secret.secret_id
+}
+
+output "kv_secret_crn" {
+ description = "CRN of the created kv_secret_id secret"
+ value = module.secrets_manager_key_value_secret.secret_crn
+}
+
+output "kv_secret_nonsensitive_payload" {
+ value = nonsensitive(data.ibm_sm_kv_secret.kv_secret.data)
+ description = "accessing key value secret"
+ sensitive = false
+}
+
+output "kv_secret_payload" {
+ value = data.ibm_sm_kv_secret.kv_secret.data
+ sensitive = true
+ description = "accessing key value secret"
+}
diff --git a/main.tf b/main.tf
index fa761c2..d1a3dcc 100644
--- a/main.tf
+++ b/main.tf
@@ -116,19 +116,34 @@ resource "ibm_sm_service_credentials_secret" "service_credentials_secret" {
}
}
+resource "ibm_sm_kv_secret" "kv_secret" {
+ count = var.secret_type == "key_value" ? 1 : 0
+ region = var.region
+ instance_id = var.secrets_manager_guid
+ secret_group_id = var.secret_group_id
+ name = var.secret_name
+ description = var.secret_description
+ labels = var.secret_labels
+ data = var.secret_kv_data
+ endpoint_type = var.endpoint_type
+ custom_metadata = var.custom_metadata
+}
+
# Parse secret ID and generate data header for secrets
locals {
secret_id = (
var.secret_type == "username_password" ? ibm_sm_username_password_secret.username_password_secret[0].secret_id :
var.secret_type == "imported_cert" ? ibm_sm_imported_certificate.imported_cert[0].secret_id :
var.secret_type == "service_credentials" ? ibm_sm_service_credentials_secret.service_credentials_secret[0].secret_id :
- var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].secret_id : null
+ var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].secret_id :
+ var.secret_type == "key_value" ? ibm_sm_kv_secret.kv_secret[0].secret_id : null
)
secret_crn = (
var.secret_type == "username_password" ? ibm_sm_username_password_secret.username_password_secret[0].crn :
var.secret_type == "imported_cert" ? ibm_sm_imported_certificate.imported_cert[0].crn :
var.secret_type == "service_credentials" ? ibm_sm_service_credentials_secret.service_credentials_secret[0].crn :
- var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].crn : null
+ var.secret_type == "arbitrary" ? ibm_sm_arbitrary_secret.arbitrary_secret[0].crn :
+ var.secret_type == "key_value" ? ibm_sm_kv_secret.kv_secret[0].crn : null
)
#tfsec:ignore:general-secrets-no-plaintext-exposure
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
diff --git a/variables.tf b/variables.tf
index 6c7e3ad..3592d82 100644
--- a/variables.tf
+++ b/variables.tf
@@ -23,8 +23,8 @@ variable "secret_type" {
description = "Type of secret to create, must be one of: arbitrary, username_password, imported_cert, service_credentials"
validation {
- condition = contains(["arbitrary", "username_password", "imported_cert", "service_credentials"], var.secret_type) #checkov:skip=CKV_SECRET_6
- error_message = "Only supported secrets types are arbitrary, username_password, imported_cert, or service_credentials"
+ condition = contains(["arbitrary", "username_password", "imported_cert", "key_value", "service_credentials"], var.secret_type) #checkov:skip=CKV_SECRET_6
+ error_message = "Only supported secrets types are arbitrary, username_password, key_value , imported_cert, or service_credentials"
}
validation {
@@ -32,6 +32,11 @@ variable "secret_type" {
error_message = "When creating a username_password or arbitrary secret, a value for `secret_payload_password` is required."
}
+ validation {
+ condition = var.secret_type == "key_value" ? var.secret_kv_data != null : true
+ error_message = "When creating a key_value secret, a value for `secret_kv_data` is required."
+ }
+
validation {
condition = var.secret_type == "imported_cert" ? var.imported_cert_certificate != null : true
error_message = "When creating an imported_cert secret, value for `imported_cert_certificate` cannot be null."
@@ -96,6 +101,13 @@ variable "secret_payload_password" {
default = "" #tfsec:ignore:general-secrets-no-plaintext-exposure
}
+variable "secret_kv_data" {
+ type = map(string)
+ description = "key-value secret data"
+ sensitive = true
+ default = null
+}
+
variable "secret_auto_rotation" {
type = bool
description = "Whether to configure automatic rotation. Applies only to the `username_password` and `service_credentials` secret types."