Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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.


<!-- Below content is automatically populated via pre-commit hook -->
<!-- BEGIN OVERVIEW HOOK -->
## Overview
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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 |

Expand All @@ -187,6 +211,7 @@ No modules.
| <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 |
| <a name="input_secret_description"></a> [secret\_description](#input\_secret\_description) | Description of the secret to create. | `string` | n/a | yes |
| <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 |
| <a name="input_secret_kv_data"></a> [secret\_kv\_data](#input\_secret\_kv\_data) | key-value secret data | `map(string)` | `null` | no |
| <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 |
| <a name="input_secret_name"></a> [secret\_name](#input\_secret\_name) | Name of the secret to create. | `string` | n/a | yes |
| <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 |
Expand Down
1 change: 1 addition & 0 deletions examples/complete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
26 changes: 26 additions & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
22 changes: 22 additions & 0 deletions examples/complete/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
41 changes: 34 additions & 7 deletions examples/private/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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"
}

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
}
22 changes: 22 additions & 0 deletions examples/private/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
19 changes: 17 additions & 2 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 14 additions & 2 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,20 @@ 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 {
condition = (var.secret_type == "username_password" || var.secret_type == "arbitrary") ? var.secret_payload_password != "" : true
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."
Expand Down Expand Up @@ -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."
Expand Down