Skip to content

Commit 19bcf33

Browse files
authored
feat: added support to create a root key in a KMS instance that exists in a different account using the option variable ibmcloud_kms_api_key (#230)
1 parent d322563 commit 19bcf33

File tree

5 files changed

+64
-12
lines changed

5 files changed

+64
-12
lines changed

solutions/standard/main.tf

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,53 @@ locals {
1919
parsed_existing_kms_instance_crn = var.existing_kms_instance_crn != null ? split(":", var.existing_kms_instance_crn) : []
2020
kms_region = length(local.parsed_existing_kms_instance_crn) > 0 ? local.parsed_existing_kms_instance_crn[5] : null
2121
kms_instance_guid = var.existing_kms_instance_crn != null ? element(split(":", var.existing_kms_instance_crn), length(split(":", var.existing_kms_instance_crn)) - 3) : module.kms[0].kms_instance_guid
22+
create_cross_account_auth_policy = (!var.skip_en_kms_auth_policy || !var.skip_cos_kms_auth_policy) && var.ibmcloud_kms_api_key != null
23+
existing_kms_guid = var.existing_kms_instance_crn != null ? element(split(":", var.existing_kms_instance_crn), length(split(":", var.existing_kms_instance_crn)) - 3) : tobool("The CRN of the existing KMS is not provided.")
2224
en_key_name = var.prefix != null ? "${var.prefix}-${var.en_key_name}" : var.en_key_name
2325
en_key_ring_name = var.prefix != null ? "${var.prefix}-${var.en_key_ring_name}" : var.en_key_ring_name
2426
en_kms_key_id = local.existing_kms_root_key_id != null ? local.existing_kms_root_key_id : module.kms[0].keys[format("%s.%s", local.en_key_ring_name, local.en_key_name)].key_id
2527
cos_key_name = var.prefix != null ? "${var.prefix}-${var.cos_key_name}" : var.cos_key_name
2628
cos_key_ring_name = var.prefix != null ? "${var.prefix}-${var.cos_key_ring_name}" : var.cos_key_ring_name
29+
cos_instance_guid = var.existing_cos_instance_crn != null ? element(split(":", var.existing_cos_instance_crn), length(split(":", var.existing_cos_instance_crn)) - 3) : null
2730
cos_kms_key_crn = var.existing_cos_bucket_name != null ? null : var.existing_kms_root_key_crn != null ? var.existing_kms_root_key_crn : module.kms[0].keys[format("%s.%s", local.cos_key_ring_name, local.cos_key_name)].crn
31+
32+
kms_service_name = var.existing_kms_instance_crn != null ? (
33+
can(regex(".*kms.*", var.existing_kms_instance_crn)) ? "kms" : (
34+
can(regex(".*hs-crypto.*", var.existing_kms_instance_crn)) ? "hs-crypto" : null
35+
)
36+
) : null
37+
}
38+
39+
# Data source to account settings for retrieving cross account id
40+
data "ibm_iam_account_settings" "iam_account_settings" {
41+
count = local.create_cross_account_auth_policy ? 1 : 0
42+
}
43+
44+
# Create IAM Authorization Policy to allow COS to access KMS for the encryption key
45+
resource "ibm_iam_authorization_policy" "cos_kms_policy" {
46+
count = local.create_cross_account_auth_policy ? 1 : 0
47+
provider = ibm.kms
48+
source_service_account = data.ibm_iam_account_settings.iam_account_settings[0].account_id
49+
source_service_name = "cloud-object-storage"
50+
source_resource_instance_id = local.cos_instance_guid
51+
target_service_name = local.kms_service_name
52+
target_resource_instance_id = local.existing_kms_guid
53+
roles = ["Reader"]
54+
description = "Allow the COS instance with GUID ${local.cos_instance_guid} to read from the ${local.kms_service_name} instance GUID ${local.existing_kms_guid}"
55+
}
56+
57+
# Create IAM Authorization Policy to allow EN to access KMS for the encryption key
58+
resource "ibm_iam_authorization_policy" "en_kms_policy" {
59+
count = local.create_cross_account_auth_policy ? 1 : 0
60+
provider = ibm.kms
61+
source_service_account = data.ibm_iam_account_settings.iam_account_settings[0].account_id
62+
source_service_name = "event-notifications"
63+
source_resource_instance_id = module.event_notifications[0].guid
64+
target_service_name = local.kms_service_name
65+
target_resource_instance_id = local.existing_kms_guid
66+
roles = ["Reader"]
67+
description = "Allow the EN instance with GUID ${module.event_notifications[0].guid} reader access to the ${local.kms_service_name} instance GUID ${local.existing_kms_guid}"
68+
2869
}
2970

3071
# KMS root key for Event Notifications
@@ -92,7 +133,7 @@ module "cos" {
92133
create_cos_instance = var.existing_cos_instance_crn == null ? true : false
93134
create_cos_bucket = var.existing_cos_bucket_name == null ? true : false
94135
existing_cos_instance_id = var.existing_cos_instance_crn
95-
skip_iam_authorization_policy = var.skip_cos_kms_auth_policy
136+
skip_iam_authorization_policy = local.create_cross_account_auth_policy || var.skip_cos_kms_auth_policy
96137
add_bucket_name_suffix = var.add_bucket_name_suffix
97138
resource_group_id = module.resource_group.resource_group_id
98139
region = local.cos_bucket_region
@@ -145,7 +186,7 @@ module "event_notifications" {
145186
kms_endpoint_url = var.kms_endpoint_url
146187
existing_kms_instance_crn = local.existing_kms_instance_crn
147188
root_key_id = local.en_kms_key_id
148-
skip_en_kms_auth_policy = var.skip_en_kms_auth_policy
189+
skip_en_kms_auth_policy = local.create_cross_account_auth_policy || var.skip_en_kms_auth_policy
149190
# COS Related
150191
cos_integration_enabled = true
151192
cos_bucket_name = local.cos_bucket_name_with_suffix

solutions/standard/provider.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ provider "ibm" {
55

66
provider "ibm" {
77
alias = "kms"
8-
ibmcloud_api_key = var.ibmcloud_api_key
8+
ibmcloud_api_key = var.ibmcloud_kms_api_key != null ? var.ibmcloud_kms_api_key : var.ibmcloud_api_key
99
region = local.kms_region
1010
}

solutions/standard/variables.tf

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ variable "existing_en_instance_crn" {
9898

9999
variable "existing_kms_instance_crn" {
100100
type = string
101-
description = "The CRN of the Hyper Protect Crypto Services or Key Protect instance."
101+
description = "The CRN of the KMS instance (Hyper Protect Crypto Services or Key Protect instance). If the KMS instance is in different account you must also provide a value for `ibmcloud_kms_api_key`."
102102
}
103103

104104
variable "existing_kms_root_key_crn" {
@@ -148,10 +148,17 @@ variable "cos_key_name" {
148148

149149
variable "skip_en_kms_auth_policy" {
150150
type = bool
151-
description = "Whether an IAM authorization policy is created that permits all Event Notifications instances in the resource group to read the encryption key from the KMS instance. Set to `true` to use an existing policy."
151+
description = "Set to true to skip the creation of an IAM authorization policy that permits the Event Notification instance to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account."
152152
default = false
153153
}
154154

155+
variable "ibmcloud_kms_api_key" {
156+
type = string
157+
description = "The IBM Cloud API key that can create a root key and key ring in the key management service (KMS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the instance in `existing_kms_instance_crn` is in an account that's different from the Event Notifications instance. Leave this input empty if the same account owns both instances."
158+
sensitive = true
159+
default = null
160+
}
161+
155162
########################################################################################################################
156163
# COS
157164
########################################################################################################################
@@ -184,7 +191,7 @@ variable "skip_en_cos_auth_policy" {
184191

185192
variable "skip_cos_kms_auth_policy" {
186193
type = bool
187-
description = "Whether an IAM authorization policy is created for your Cloud Object Storage instance to read the encryption key from the KMS instance. Set to `true` to use an existing policy."
194+
description = "Set to true to skip the creation of an IAM authorization policy that permits the COS instance to read the encryption key from the KMS instance. If set to false, pass in a value for the KMS instance in the `existing_kms_instance_crn` variable. If a value is specified for `ibmcloud_kms_api_key`, the policy is created in the KMS account."
188195
default = false
189196
}
190197

tests/other_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const basicExampleDir = "examples/basic"
1212
func TestRunBasicExample(t *testing.T) {
1313
t.Parallel()
1414

15-
options := setupOptions(t, "event-notification-basic", basicExampleDir)
15+
options := setupOptions(t, "en-basic", basicExampleDir)
1616

1717
output, err := options.RunTestConsistency()
1818
assert.Nil(t, err, "This should not have errored")

tests/pr_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ func TestMain(m *testing.M) {
4848
func setupOptions(t *testing.T, prefix string, dir string) *testhelper.TestOptions {
4949

5050
options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{
51-
Testing: t,
52-
TerraformDir: dir,
53-
Prefix: prefix,
54-
ResourceGroup: resourceGroup,
55-
Region: validRegions[rand.Intn(len(validRegions))],
51+
Testing: t,
52+
TerraformDir: dir,
53+
Prefix: prefix,
54+
/*
55+
Comment out the 'ResourceGroup' input to force this tests to create a unique resource group. This is because
56+
there is a restriction with the Event Notification service, which allows only one Lite plan instance per resource group.
57+
*/
58+
// ResourceGroup: resourceGroup,
59+
Region: validRegions[rand.Intn(len(validRegions))],
5660
})
5761

5862
return options

0 commit comments

Comments
 (0)