diff --git a/README.md b/README.md index 41a97fbe..58e06de9 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ You need the following permissions to run this module. | [kms\_key\_crn](#input\_kms\_key\_crn) | The root key CRN of a Key Management Service like Key Protect or Hyper Protect Crypto Services (HPCS) that you want to use for encryption. Only used if `kms_encryption_enabled` is set to true. | `string` | `null` | no | | [region](#input\_region) | The region where the resource will be provisioned.Its not required if passing a value for `existing_sm_instance_crn`. | `string` | `null` | no | | [resource\_group\_id](#input\_resource\_group\_id) | The ID of the resource group | `string` | n/a | yes | -| [secrets](#input\_secrets) | Secret Manager secrets configurations. |
list(object({
secret_group_name = string
secret_group_description = optional(string)
existing_secret_group = optional(bool, false)
secrets = optional(list(object({
secret_name = string
secret_description = optional(string)
secret_type = optional(string)
imported_cert_certificate = optional(string)
imported_cert_private_key = optional(string)
imported_cert_intermediate = optional(string)
secret_username = optional(string)
secret_labels = optional(list(string), [])
secret_payload_password = optional(string, "")
secret_auto_rotation = optional(bool, true)
secret_auto_rotation_unit = optional(string, "day")
secret_auto_rotation_interval = optional(number, 89)
service_credentials_ttl = optional(string, "7776000") # 90 days
service_credentials_source_service_crn = optional(string)
service_credentials_source_service_role_crn = optional(string)
})))
})) | `[]` | no |
+| [secrets](#input\_secrets) | Secret Manager secrets configurations. | list(object({
secret_group_name = string
secret_group_description = optional(string)
existing_secret_group = optional(bool, false)
secrets = optional(list(object({
secret_name = string
secret_description = optional(string)
secret_type = optional(string)
imported_cert_certificate = optional(string)
imported_cert_private_key = optional(string)
imported_cert_intermediate = optional(string)
secret_username = optional(string)
secret_labels = optional(list(string), [])
secret_payload_password = optional(string, "")
secret_auto_rotation = optional(bool, true)
secret_auto_rotation_unit = optional(string, "day")
secret_auto_rotation_interval = optional(number, 89)
service_credentials_ttl = optional(string, "7776000") # 90 days
service_credentials_source_service_crn = optional(string)
service_credentials_source_service_role_crn = optional(string)
})))
access_group_configuration = optional(object({
name = optional(string)
roles = list(string)
tags = optional(set(string), [])
}))
})) | `[]` | no |
| [secrets\_manager\_name](#input\_secrets\_manager\_name) | The name of the Secrets Manager instance to create | `string` | n/a | yes |
| [skip\_en\_iam\_authorization\_policy](#input\_skip\_en\_iam\_authorization\_policy) | Set to true to skip the creation of 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. In addition, no policy is created if `enable_event_notification` is set to false. | `bool` | `false` | no |
| [skip\_iam\_authorization\_policy](#input\_skip\_iam\_authorization\_policy) | Whether to skip the creation of the IAM authorization policies required to enable the IAM credentials engine. If set to false, policies will be created that grants the Secrets Manager instance 'Operator' access to the IAM identity service, and 'Groups Service Member Manage' access to the IAM groups service. | `bool` | `false` | no |
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
index 0238d975..c309ebf2 100644
--- a/examples/complete/main.tf
+++ b/examples/complete/main.tf
@@ -84,6 +84,9 @@ module "secrets_manager" {
service_credentials_source_service_role_crn = "crn:v1:bluemix:public:event-notifications::::serviceRole:Event-Notification-Publisher"
}
]
+ access_group_configuration = {
+ roles = ["SecretsReader"]
+ }
},
{
secret_group_name = "default"
@@ -94,6 +97,9 @@ module "secrets_manager" {
secret_payload_password = module.key_protect.keys["${var.prefix}-sm.${var.prefix}-sm-key"].key_id
}
]
+ access_group_configuration = {
+ roles = ["SecretsReader"]
+ }
}
]
}
diff --git a/modules/secrets/README.md b/modules/secrets/README.md
index 5b478975..ca5daa52 100644
--- a/modules/secrets/README.md
+++ b/modules/secrets/README.md
@@ -33,6 +33,9 @@ module "secrets_manager" {
secret_payload_password = "test"
}
]
+ access_group_configuration = {
+ roles = ["SecretsReader]
+ }
}
]
}
@@ -50,6 +53,7 @@ module "secrets_manager" {
| Name | Source | Version |
|------|--------|---------|
+| [iam\_access\_groups](#module\_iam\_access\_groups) | terraform-ibm-modules/iam-access-group/ibm | 1.4.6 |
| [secret\_groups](#module\_secret\_groups) | terraform-ibm-modules/secrets-manager-secret-group/ibm | 1.2.2 |
| [secrets](#module\_secrets) | terraform-ibm-modules/secrets-manager-secret/ibm | 1.7.0 |
@@ -66,12 +70,13 @@ module "secrets_manager" {
| [endpoint\_type](#input\_endpoint\_type) | The service endpoint type to communicate with the provided secrets manager instance. Possible values are `public` or `private` | `string` | `"public"` | no |
| [existing\_sm\_instance\_guid](#input\_existing\_sm\_instance\_guid) | Instance ID of Secrets Manager instance in which the Secret will be added. | `string` | n/a | yes |
| [existing\_sm\_instance\_region](#input\_existing\_sm\_instance\_region) | Region which the Secret Manager is deployed. | `string` | n/a | yes |
-| [secrets](#input\_secrets) | Secret Manager secrets configurations. | list(object({
secret_group_name = string
secret_group_description = optional(string)
existing_secret_group = optional(bool, false)
secrets = optional(list(object({
secret_name = string
secret_description = optional(string)
secret_type = optional(string)
imported_cert_certificate = optional(string)
imported_cert_private_key = optional(string)
imported_cert_intermediate = optional(string)
secret_username = optional(string)
secret_labels = optional(list(string), [])
secret_payload_password = optional(string, "")
secret_auto_rotation = optional(bool, true)
secret_auto_rotation_unit = optional(string, "day")
secret_auto_rotation_interval = optional(number, 89)
service_credentials_ttl = optional(string, "7776000") # 90 days
service_credentials_source_service_crn = optional(string)
service_credentials_source_service_role_crn = optional(string)
service_credentials_source_service_hmac = optional(bool, false)
})))
})) | `[]` | no |
+| [secrets](#input\_secrets) | Secret Manager secrets configurations. | list(object({
secret_group_name = string
secret_group_description = optional(string)
existing_secret_group = optional(bool, false)
secrets = optional(list(object({
secret_name = string
secret_description = optional(string)
secret_type = optional(string)
imported_cert_certificate = optional(string)
imported_cert_private_key = optional(string)
imported_cert_intermediate = optional(string)
secret_username = optional(string)
secret_labels = optional(list(string), [])
secret_payload_password = optional(string, "")
secret_auto_rotation = optional(bool, true)
secret_auto_rotation_unit = optional(string, "day")
secret_auto_rotation_interval = optional(number, 89)
service_credentials_ttl = optional(string, "7776000") # 90 days
service_credentials_source_service_crn = optional(string)
service_credentials_source_service_role_crn = optional(string)
service_credentials_source_service_hmac = optional(bool, false)
})))
access_group_configuration = optional(object({
name = optional(string)
roles = list(string)
tags = optional(set(string), [])
}))
})) | `[]` | no |
### Outputs
| Name | Description |
|------|-------------|
+| [access\_groups](#output\_access\_groups) | List of created access groups for secrets groups |
| [secret\_groups](#output\_secret\_groups) | IDs of the created Secret Group |
| [secrets](#output\_secrets) | List of secret mananger secret config data |
diff --git a/modules/secrets/main.tf b/modules/secrets/main.tf
index f3f5bf18..ab304d1c 100644
--- a/modules/secrets/main.tf
+++ b/modules/secrets/main.tf
@@ -29,6 +29,38 @@ module "secret_groups" {
endpoint_type = var.endpoint_type
}
+locals {
+ access_groups = flatten([
+ for secret_group in var.secrets :
+ secret_group.access_group_configuration == null ? [] : [{
+ access_group_name = coalesce(secret_group.access_group_configuration.name, "${secret_group.secret_group_name}-access-group")
+ access_group_roles = secret_group.access_group_configuration.roles
+ access_group_tags = secret_group.access_group_configuration.tags
+ secrets_manager_group_guid = secret_group.existing_secret_group ? data.ibm_sm_secret_groups.existing_secret_groups.secret_groups[index(data.ibm_sm_secret_groups.existing_secret_groups.secret_groups[*].name, secret_group.secret_group_name)].id : module.secret_groups[secret_group.secret_group_name].secret_group_id
+ }]
+ ])
+}
+module "iam_access_groups" {
+ for_each = { for obj in local.access_groups : obj.access_group_name => obj }
+ source = "terraform-ibm-modules/iam-access-group/ibm"
+ version = "1.4.6"
+ access_group_name = each.value.access_group_name
+ dynamic_rules = {}
+ add_members = false
+ policies = {
+ sm_policy = {
+ roles = each.value.access_group_roles
+ tags = each.value.access_group_tags
+ resources = [{
+ service = "secrets-manager"
+ instance_id = var.existing_sm_instance_guid
+ resource_type = "secret-group"
+ resource = each.value.secrets_manager_group_guid
+ }]
+ }
+ }
+}
+
##############################################################################
# Secrets
##############################################################################
diff --git a/modules/secrets/outputs.tf b/modules/secrets/outputs.tf
index 8e08adb6..45b8a50d 100644
--- a/modules/secrets/outputs.tf
+++ b/modules/secrets/outputs.tf
@@ -11,3 +11,8 @@ output "secrets" {
description = "List of secret mananger secret config data"
value = module.secrets
}
+
+output "access_groups" {
+ description = "List of created access groups for secrets groups"
+ value = module.iam_access_groups
+}
diff --git a/modules/secrets/variables.tf b/modules/secrets/variables.tf
index 80a4d0ba..287ee56a 100644
--- a/modules/secrets/variables.tf
+++ b/modules/secrets/variables.tf
@@ -41,6 +41,11 @@ variable "secrets" {
service_credentials_source_service_role_crn = optional(string)
service_credentials_source_service_hmac = optional(bool, false)
})))
+ access_group_configuration = optional(object({
+ name = optional(string)
+ roles = list(string)
+ tags = optional(set(string), [])
+ }))
}))
description = "Secret Manager secrets configurations."
default = []
@@ -58,4 +63,11 @@ variable "secrets" {
true if(secret.secret_group_name == "default" && secret.existing_secret_group == false)
]) == 0
}
+ validation {
+ error_message = "Invalid role set for the access group, all roles must be one of: Reader, Writer, Manager, SecretsReader, Viewer, Operator, Editor, Administrator, Service Configuration Reader, Key Manager"
+ condition = length([
+ for secret in var.secrets :
+ true if((secret.access_group_configuration != null) && (length(setintersection(secret.access_group_configuration.roles, ["Reader", "Writer", "Manager", "SecretsReader", "Viewer", "Operator", "Editor", "Administrator", "Service Configuration Reader", "Key Manager"])) == 0))
+ ]) == 0
+ }
}
diff --git a/variables.tf b/variables.tf
index 3bb88f14..f3081378 100644
--- a/variables.tf
+++ b/variables.tf
@@ -162,6 +162,11 @@ variable "secrets" {
service_credentials_source_service_crn = optional(string)
service_credentials_source_service_role_crn = optional(string)
})))
+ access_group_configuration = optional(object({
+ name = optional(string)
+ roles = list(string)
+ tags = optional(set(string), [])
+ }))
}))
description = "Secret Manager secrets configurations."
default = []