Skip to content

Commit a0cab06

Browse files
feat: The KMS auth policy has been updated so its now scoped to the exact KMS key. If upgrading from an older version this will recreate the auth policy, however it will create the new one before destroying the old one so there is no disruption to every day services.<br> The kms_instance_guid input has been removed from the module. It is now programmticallty determined from the value of kms_key_crn<br>- A new boolean input is_hpcs_key has been added to the module and should be set to true if the key specified in kms_key_crn is from a Hyper Protect instance. Leave it at flase if using Key Protect. If set to true, a second auth policy is created which allows the Secrets Manager instance Viewer access to the HPCS instance. (#295)
1 parent 1a9b567 commit a0cab06

File tree

12 files changed

+223
-75
lines changed

12 files changed

+223
-75
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ You need the following permissions to run this module.
7676
| Name | Source | Version |
7777
|------|--------|---------|
7878
| <a name="module_cbr_rule"></a> [cbr\_rule](#module\_cbr\_rule) | terraform-ibm-modules/cbr/ibm//modules/cbr-rule-module | 1.29.0 |
79+
| <a name="module_kms_key_crn_parser"></a> [kms\_key\_crn\_parser](#module\_kms\_key\_crn\_parser) | terraform-ibm-modules/common-utilities/ibm//modules/crn-parser | 1.1.0 |
7980
| <a name="module_secrets"></a> [secrets](#module\_secrets) | ./modules/secrets | n/a |
8081

8182
### Resources
@@ -86,9 +87,11 @@ You need the following permissions to run this module.
8687
| [ibm_iam_authorization_policy.iam_groups_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource |
8788
| [ibm_iam_authorization_policy.iam_identity_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource |
8889
| [ibm_iam_authorization_policy.kms_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource |
90+
| [ibm_iam_authorization_policy.secrets_manager_hpcs_policy](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/iam_authorization_policy) | resource |
8991
| [ibm_resource_instance.secrets_manager_instance](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/resource_instance) | resource |
9092
| [ibm_sm_en_registration.sm_en_registration](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/sm_en_registration) | resource |
9193
| [time_sleep.wait_for_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
94+
| [time_sleep.wait_for_sm_hpcs_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
9295
| [ibm_resource_instance.sm_instance](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/resource_instance) | data source |
9396

9497
### Inputs
@@ -100,8 +103,8 @@ You need the following permissions to run this module.
100103
| <a name="input_enable_event_notification"></a> [enable\_event\_notification](#input\_enable\_event\_notification) | Set this to true to enable lifecycle notifications for your Secrets Manager instance by connecting an Event Notifications service. When setting this to true, a value must be passed for `existing_en_instance_crn` and `existing_sm_instance_crn` must be null. | `bool` | `false` | no |
101104
| <a name="input_endpoint_type"></a> [endpoint\_type](#input\_endpoint\_type) | The type of endpoint (public or private) to connect to the Secrets Manager API. The Terraform provider uses this endpoint type to interact with the Secrets Manager API and configure Event Notifications. | `string` | `"public"` | no |
102105
| <a name="input_existing_en_instance_crn"></a> [existing\_en\_instance\_crn](#input\_existing\_en\_instance\_crn) | The CRN of the Event Notifications service to enable lifecycle notifications for your Secrets Manager instance. | `string` | `null` | no |
103-
| <a name="input_existing_kms_instance_guid"></a> [existing\_kms\_instance\_guid](#input\_existing\_kms\_instance\_guid) | The GUID of the Hyper Protect Crypto Services or Key Protect instance in which the key specified in `kms_key_crn` is coming from. Required only if `kms_encryption_enabled` is set to true, and `skip_kms_iam_authorization_policy` is set to false. | `string` | `null` | no |
104106
| <a name="input_existing_sm_instance_crn"></a> [existing\_sm\_instance\_crn](#input\_existing\_sm\_instance\_crn) | An existing Secrets Manager instance CRN. If not provided an new instance will be provisioned. | `string` | `null` | no |
107+
| <a name="input_is_hpcs_key"></a> [is\_hpcs\_key](#input\_is\_hpcs\_key) | Set it to true if the key provided through the `kms_key_crn` is Hyper Protect Crypto Services key. | `bool` | `false` | no |
105108
| <a name="input_kms_encryption_enabled"></a> [kms\_encryption\_enabled](#input\_kms\_encryption\_enabled) | Set this to true to control the encryption keys used to encrypt the data that you store in Secrets Manager. If set to false, the data that you store is encrypted at rest by using envelope encryption. For more details, see https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-mng-data&interface=ui#about-encryption. | `bool` | `false` | no |
106109
| <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 (HPCS) that you want to use for encryption. Only used if `kms_encryption_enabled` is set to true. | `string` | `null` | no |
107110
| <a name="input_region"></a> [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 |

examples/complete/main.tf

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ module "event_notification" {
3232
name = "${var.prefix}-en"
3333
tags = var.resource_tags
3434
plan = "lite"
35-
service_endpoints = "public"
3635
region = var.en_region
3736
}
3837

@@ -55,18 +54,18 @@ resource "time_sleep" "wait_for_en_policy" {
5554
}
5655

5756
module "secrets_manager" {
58-
depends_on = [time_sleep.wait_for_en_policy]
59-
source = "../.."
60-
resource_group_id = module.resource_group.resource_group_id
61-
region = var.region
62-
secrets_manager_name = "${var.prefix}-secrets-manager" #tfsec:ignore:general-secrets-no-plaintext-exposure
63-
sm_service_plan = var.sm_service_plan
64-
sm_tags = var.resource_tags
65-
kms_encryption_enabled = true
66-
existing_kms_instance_guid = module.key_protect.kms_guid
67-
kms_key_crn = module.key_protect.keys["${var.prefix}-sm.${var.prefix}-sm-key"].crn
68-
enable_event_notification = true
69-
existing_en_instance_crn = module.event_notification.crn
57+
depends_on = [time_sleep.wait_for_en_policy]
58+
source = "../.."
59+
resource_group_id = module.resource_group.resource_group_id
60+
region = var.region
61+
secrets_manager_name = "${var.prefix}-secrets-manager" #tfsec:ignore:general-secrets-no-plaintext-exposure
62+
sm_service_plan = var.sm_service_plan
63+
sm_tags = var.resource_tags
64+
kms_encryption_enabled = true
65+
is_hpcs_key = false
66+
kms_key_crn = module.key_protect.keys["${var.prefix}-sm.${var.prefix}-sm-key"].crn
67+
enable_event_notification = true
68+
existing_en_instance_crn = module.event_notification.crn
7069
secrets = [
7170
{
7271
secret_group_name = "${var.prefix}-secret-group"

examples/fscloud/main.tf

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,29 @@ module "event_notification" {
5151
region = var.region
5252
}
5353

54+
##############################################################################
55+
# Parse info from KMS key crn
56+
##############################################################################
57+
58+
module "kms_key_crn_parser" {
59+
source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
60+
version = "1.1.0"
61+
crn = var.kms_key_crn
62+
}
63+
64+
locals {
65+
kms_service = module.kms_key_crn_parser.service_name
66+
}
67+
5468
module "secrets_manager" {
55-
source = "../../modules/fscloud"
56-
resource_group_id = module.resource_group.resource_group_id
57-
region = var.region
58-
secrets_manager_name = "${var.prefix}-secrets-manager" #tfsec:ignore:general-secrets-no-plaintext-exposure
59-
sm_tags = var.resource_tags
60-
existing_kms_instance_guid = var.existing_kms_instance_guid
61-
kms_key_crn = var.kms_key_crn
62-
existing_en_instance_crn = module.event_notification.crn
69+
source = "../../modules/fscloud"
70+
resource_group_id = module.resource_group.resource_group_id
71+
region = var.region
72+
secrets_manager_name = "${var.prefix}-secrets-manager" #tfsec:ignore:general-secrets-no-plaintext-exposure
73+
sm_tags = var.resource_tags
74+
is_hpcs_key = local.kms_service == "hs-crypto" ? true : false
75+
kms_key_crn = var.kms_key_crn
76+
existing_en_instance_crn = module.event_notification.crn
6377
cbr_rules = [
6478
{
6579
description = "${var.prefix}-secrets-manager access only from vpc"

examples/fscloud/variables.tf

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ variable "resource_tags" {
3232
# Key Management Service (KMS)
3333
##############################################################################
3434

35-
variable "existing_kms_instance_guid" {
36-
type = string
37-
description = "The GUID of the Hyper Protect Crypto Services instance in which the key specified in `kms_key_crn` is coming from."
38-
}
39-
4035
variable "kms_key_crn" {
4136
type = string
4237
description = "The root key CRN of Hyper Protect Crypto Services (HPCS) that you want to use for encryption."

main.tf

Lines changed: 82 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@
66
locals {
77
# Validation (approach based on https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400)
88
# tflint-ignore: terraform_unused_declarations
9-
validate_kms_values = (!var.kms_encryption_enabled && var.kms_key_crn != null && var.existing_sm_instance_crn == null) ? tobool("When passing values for var.kms_key_crn, you must set 'kms_encryption_enabled' to true. Otherwise set 'kms_encryption_enabled' to false to use default encryption") : (!var.kms_encryption_enabled && var.existing_kms_instance_guid != null) ? tobool("When passing values for var.existing_kms_instance_guid, you must set var.kms_encryption_enabled to true. Otherwise unset them to use default encryption") : true
9+
validate_kms_values = (!var.kms_encryption_enabled && var.kms_key_crn != null && var.existing_sm_instance_crn == null) ? tobool("When passing values for var.kms_key_crn, you must set 'kms_encryption_enabled' to true. Otherwise set 'kms_encryption_enabled' to false to use default encryption") : true
1010
# tflint-ignore: terraform_unused_declarations
1111
validate_kms_vars = var.kms_encryption_enabled && var.kms_key_crn == null && var.existing_sm_instance_crn == null ? tobool("When setting var.kms_encryption_enabled to true, a value must be passed for var.kms_key_crn") : true
1212
# tflint-ignore: terraform_unused_declarations
13-
validate_auth_policy = var.kms_encryption_enabled && var.skip_kms_iam_authorization_policy == false && var.existing_kms_instance_guid == null && var.existing_sm_instance_crn == null ? tobool("When var.skip_kms_iam_authorization_policy is set to false, and var.kms_encryption_enabled to true, a value must be passed for var.existing_kms_instance_guid in order to create the auth policy.") : true
13+
validate_auth_policy = var.kms_encryption_enabled && var.skip_kms_iam_authorization_policy == false && var.kms_key_crn == null && var.existing_sm_instance_crn == null ? tobool("When var.skip_kms_iam_authorization_policy is set to false, and var.kms_encryption_enabled to true, a value must be passed for var.kms_key_crn in order to create the auth policy.") : true
1414
# tflint-ignore: terraform_unused_declarations
1515
validate_event_notification = var.enable_event_notification && var.existing_en_instance_crn == null ? tobool("When setting var.enable_event_notification to true, a value must be passed for var.existing_en_instance_crn") : true
1616
# tflint-ignore: terraform_unused_declarations
1717
validate_endpoint = var.endpoint_type == "public" && var.allowed_network == "private-only" && var.existing_sm_instance_crn == null ? tobool("It is not allowed to have conflicting var.endpoint_type and var.allowed_network values.") : true
1818
# tflint-ignore: terraform_unused_declarations
1919
validate_region = var.existing_sm_instance_crn == null && var.region == null ? tobool("When existing_sm_instance_crn is null, a value must be passed for var.region") : true
20+
# tflint-ignore: terraform_unused_declarations
21+
validate_is_hpcs_key = var.is_hpcs_key && local.kms_service_name != "hs-crypto" ? tobool("When is_hpcs_key is set to true then the key provided through kms_key_crn must be a Hyper Protect Crypto Services key") : true
2022
}
2123

2224
locals {
@@ -34,7 +36,7 @@ data "ibm_resource_instance" "sm_instance" {
3436
# Create Secrets Manager Instance
3537
resource "ibm_resource_instance" "secrets_manager_instance" {
3638
count = var.existing_sm_instance_crn == null ? 1 : 0
37-
depends_on = [time_sleep.wait_for_authorization_policy]
39+
depends_on = [time_sleep.wait_for_authorization_policy, time_sleep.wait_for_sm_hpcs_authorization_policy]
3840
name = var.secrets_manager_name
3941
service = "secrets-manager"
4042
plan = var.sm_service_plan
@@ -43,7 +45,7 @@ resource "ibm_resource_instance" "secrets_manager_instance" {
4345
tags = var.sm_tags
4446
parameters = {
4547
"allowed_network" = var.allowed_network
46-
"kms_instance" = var.existing_kms_instance_guid
48+
"kms_instance" = local.kms_instance_guid
4749
"kms_key" = var.kms_key_crn
4850
}
4951

@@ -71,23 +73,68 @@ resource "ibm_iam_authorization_policy" "iam_groups_policy" {
7173
description = "Allows Secrets Manager instance ${local.secrets_manager_guid} `Groups Service Member Manage` access to the IAM Groups service to enable creating IAM credentials."
7274
}
7375

76+
#######################################################################################################################
77+
# KMS Key
78+
#######################################################################################################################
7479
locals {
75-
# determine which service name to use for the policy
76-
kms_service_name = var.kms_encryption_enabled && var.kms_key_crn != null ? (
77-
can(regex(".*kms.*", var.kms_key_crn)) ? "kms" : (
78-
can(regex(".*hs-crypto.*", var.kms_key_crn)) ? "hs-crypto" : null
79-
)
80-
) : null
80+
create_kms_auth_policy = var.kms_encryption_enabled && !var.skip_kms_iam_authorization_policy && var.existing_sm_instance_crn == null
81+
create_hpcs_auth_policy = local.create_kms_auth_policy == true && var.is_hpcs_key ? 1 : 0
82+
83+
kms_service_name = var.kms_encryption_enabled && var.kms_key_crn != null ? module.kms_key_crn_parser[0].service_name : null
84+
kms_account_id = var.kms_encryption_enabled && var.kms_key_crn != null ? module.kms_key_crn_parser[0].account_id : null
85+
kms_key_id = var.kms_encryption_enabled && var.kms_key_crn != null ? module.kms_key_crn_parser[0].resource : null
86+
kms_instance_guid = var.kms_encryption_enabled && var.kms_key_crn != null ? module.kms_key_crn_parser[0].service_instance : null
87+
}
88+
89+
########################################################################################################################
90+
# Parse KMS info from CRN
91+
########################################################################################################################
92+
93+
module "kms_key_crn_parser" {
94+
count = local.create_kms_auth_policy ? 1 : 0
95+
source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
96+
version = "1.1.0"
97+
crn = var.kms_key_crn
8198
}
8299

100+
# Create auth policy (scoped to exact KMS key)
83101
resource "ibm_iam_authorization_policy" "kms_policy" {
84-
count = var.kms_encryption_enabled && !var.skip_kms_iam_authorization_policy && var.existing_sm_instance_crn == null ? 1 : 0
85-
source_service_name = "secrets-manager"
86-
source_resource_group_id = var.resource_group_id
87-
target_service_name = local.kms_service_name
88-
target_resource_instance_id = var.existing_kms_instance_guid
89-
roles = ["Reader"]
90-
description = "Allow all Secrets Manager instances in the resource group ${var.resource_group_id} to read from the ${local.kms_service_name} instance GUID ${var.existing_kms_instance_guid}"
102+
count = local.create_kms_auth_policy ? 1 : 0
103+
source_service_name = "secrets-manager"
104+
source_resource_group_id = var.resource_group_id
105+
roles = ["Reader"]
106+
description = "Allow all Secrets Manager instances in the resource group ${var.resource_group_id} to read the ${local.kms_service_name} key ${local.kms_key_id} from the instance GUID ${local.kms_instance_guid}."
107+
resource_attributes {
108+
name = "serviceName"
109+
operator = "stringEquals"
110+
value = local.kms_service_name
111+
}
112+
resource_attributes {
113+
name = "accountId"
114+
operator = "stringEquals"
115+
value = local.kms_account_id
116+
}
117+
resource_attributes {
118+
name = "serviceInstance"
119+
operator = "stringEquals"
120+
value = local.kms_instance_guid
121+
}
122+
resource_attributes {
123+
name = "resourceType"
124+
operator = "stringEquals"
125+
value = "key"
126+
}
127+
resource_attributes {
128+
name = "resource"
129+
operator = "stringEquals"
130+
value = local.kms_key_id
131+
}
132+
# Scope of policy now includes the key, so ensure to create new policy before
133+
# destroying old one to prevent any disruption to every day services.
134+
lifecycle {
135+
create_before_destroy = true
136+
}
137+
91138
}
92139

93140
# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478
@@ -98,6 +145,24 @@ resource "time_sleep" "wait_for_authorization_policy" {
98145
create_duration = "30s"
99146
}
100147

148+
# if using HPCS ,create a second IAM authorization that assigns the Viewer platform access in Hyper Protect Crypto Services .[Learn more](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-mng-data#using-byok)
149+
resource "ibm_iam_authorization_policy" "secrets_manager_hpcs_policy" {
150+
count = local.create_hpcs_auth_policy
151+
source_service_name = "secrets-manager"
152+
source_resource_group_id = var.resource_group_id
153+
target_service_name = local.kms_service_name
154+
target_resource_instance_id = local.kms_instance_guid
155+
roles = ["Viewer"]
156+
description = "Allow all Secrets Manager instances in the resource group ${var.resource_group_id} viewer access to the ${local.kms_service_name} instance GUID ${local.kms_instance_guid}."
157+
}
158+
159+
# workaround for https://github.com/IBM-Cloud/terraform-provider-ibm/issues/4478
160+
resource "time_sleep" "wait_for_sm_hpcs_authorization_policy" {
161+
count = local.create_hpcs_auth_policy
162+
depends_on = [ibm_iam_authorization_policy.secrets_manager_hpcs_policy]
163+
164+
create_duration = "30s"
165+
}
101166

102167
locals {
103168
secrets_manager_guid = var.existing_sm_instance_crn != null ? local.existing_sm_guid : tolist(ibm_resource_instance.secrets_manager_instance[*].guid)[0]

0 commit comments

Comments
 (0)