Skip to content

Commit 70a0338

Browse files
authored
feat: added support to the Observability DA instances variation to create COS resources in a different account to the Observability resources (#175)
1 parent 2a5a804 commit 70a0338

File tree

5 files changed

+149
-21
lines changed

5 files changed

+149
-21
lines changed

cra-tf-validate-ignore-rules.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
11
{
2-
"scc_rules": []
2+
"scc_rules": [
3+
{
4+
"scc_rule_id": "rule-4d86c074-097e-4ff3-a763-ccff128388e2",
5+
"description": "Check whether multifactor authentication (MFA) is enabled at the account level",
6+
"ignore_reason": "We have added an account level data lookup. Since we do not create any account setting in this DA, it can be ignored",
7+
"is_valid": true
8+
},
9+
{
10+
"scc_rule_id": "rule-0704e840-e443-4781-b9be-ec57469d09c1",
11+
"description": "Check whether permissions for API key creation are limited and configured in IAM settings for the account owner",
12+
"ignore_reason": "We have added an account level data lookup. Since we do not create any account setting in this DA, it can be ignored",
13+
"is_valid": true
14+
},
15+
{
16+
"scc_rule_id": "rule-0244c010-fde6-4db3-95aa-8952bd292ac3",
17+
"description": "Check whether permissions for service ID creation are limited and configured in IAM settings for the account owner",
18+
"ignore_reason": "We have added an account level data lookup. Since we do not create any account setting in this DA, it can be ignored",
19+
"is_valid": true
20+
}
21+
]
322
}

ibm_catalog.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,12 @@
496496
{
497497
"key": "skip_cos_kms_auth_policy"
498498
},
499+
{
500+
"key": "skip_cloud_logs_cos_auth_policy"
501+
},
502+
{
503+
"key": "skip_at_cos_auth_policy"
504+
},
499505
{
500506
"key": "existing_cos_kms_key_crn",
501507
"required": true

solutions/instances/main.tf

Lines changed: 94 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ locals {
88
validate_log_analysis_provision = var.enable_at_event_routing_to_log_analysis && var.log_analysis_provision == false ? tobool("log_analysis_provision can't be false if enable_at_event_routing_to_log_analysis is true") : true
99
# tflint-ignore: terraform_unused_declarations
1010
validate_existing_cloud_monitoring = var.cloud_monitoring_provision && var.existing_cloud_monitoring_crn != null ? tobool("if cloud_monitoring_provision is set to true, then existing_cloud_monitoring_crn should be null and vice versa") : true
11+
# tflint-ignore: terraform_unused_declarations
12+
validate_cos_resource_group = var.existing_cos_instance_crn == null ? var.ibmcloud_cos_api_key != null && var.cos_resource_group_name == null ? tobool("if value for `ibmcloud_cos_api_key` is set, then `cos_resource_group_name` cannot be null") : true : true
1113

1214
archive_api_key = var.log_archive_api_key == null ? var.ibmcloud_api_key : var.log_archive_api_key
1315
default_cos_region = var.cos_region != null ? var.cos_region : var.region
@@ -22,9 +24,10 @@ locals {
2224
cos_instance_guid = var.existing_cos_instance_crn == null ? length(module.cos_instance) != 0 ? module.cos_instance[0].cos_instance_guid : null : element(split(":", var.existing_cos_instance_crn), length(split(":", var.existing_cos_instance_crn)) - 3)
2325
archive_cos_bucket_name = var.existing_log_archive_cos_bucket_name != null ? var.existing_log_archive_cos_bucket_name : var.log_analysis_provision ? module.cos_bucket[0].buckets[local.log_archive_cos_bucket_name].bucket_name : null
2426
archive_cos_bucket_endpoint = var.existing_log_archive_cos_bucket_endpoint != null ? var.existing_log_archive_cos_bucket_endpoint : var.log_analysis_provision ? module.cos_bucket[0].buckets[local.log_archive_cos_bucket_name].s3_endpoint_private : null
25-
cos_kms_key_crn = ((var.existing_cloud_logs_metrics_bucket_crn != null && var.existing_cloud_logs_data_bucket_crn != null && var.existing_log_archive_cos_bucket_name != null && var.existing_at_cos_target_bucket_name != null) || (!var.log_analysis_provision && !var.enable_at_event_routing_to_cos_bucket && !var.cloud_logs_provision)) ? null : var.existing_cos_kms_key_crn != null ? var.existing_cos_kms_key_crn : module.kms[0].keys[format("%s.%s", local.cos_key_ring_name, local.cos_key_name)].crn
27+
cos_kms_key_crn = var.existing_cos_kms_key_crn != null ? var.existing_cos_kms_key_crn : length(coalesce(local.buckets_config, [])) != 0 ? module.kms[0].keys[format("%s.%s", local.cos_key_ring_name, local.cos_key_name)].crn : null
2628

2729
cos_target_bucket_name = var.existing_at_cos_target_bucket_name != null ? var.existing_at_cos_target_bucket_name : var.enable_at_event_routing_to_cos_bucket ? module.cos_bucket[0].buckets[local.at_cos_target_bucket_name].bucket_name : null
30+
cos_resource_group_id = var.cos_resource_group_name != null ? module.cos_resource_group[0].resource_group_id : module.resource_group.resource_group_id
2831
cos_target_bucket_endpoint = var.existing_at_cos_target_bucket_endpoint != null ? var.existing_at_cos_target_bucket_endpoint : var.enable_at_event_routing_to_cos_bucket ? module.cos_bucket[0].buckets[local.at_cos_target_bucket_name].s3_endpoint_private : null
2932
cos_target_name = var.prefix != null ? "${var.prefix}-cos-target" : "cos-target"
3033
log_analysis_target_name = var.prefix != null ? "${var.prefix}-log-analysis-target" : "log-analysis-target"
@@ -100,10 +103,9 @@ locals {
100103
locations = ["*", "global"]
101104
target_ids = [module.observability_instance.activity_tracker_targets[local.cloud_logs_target_name].id]
102105
}] : []
103-
104-
at_routes = concat(local.at_cos_route, local.at_log_analysis_route, local.at_cloud_logs_route)
105-
106106
apply_auth_policy = (var.skip_cos_kms_auth_policy || (length(coalesce(local.buckets_config, [])) == 0)) ? 0 : 1
107+
at_routes = concat(local.at_cos_route, local.at_log_analysis_route, local.at_cloud_logs_route)
108+
107109

108110
# Cloud Logs data bucket
109111
cloud_log_data_bucket = var.prefix != null ? "${var.prefix}-${var.cloud_log_data_bucket_name}" : var.cloud_log_data_bucket_name
@@ -136,6 +138,16 @@ module "resource_group" {
136138
existing_resource_group_name = var.use_existing_resource_group == true ? var.resource_group_name : null
137139
}
138140

141+
module "cos_resource_group" {
142+
count = var.cos_resource_group_name != null ? 1 : 0
143+
providers = {
144+
ibm = ibm.cos
145+
}
146+
source = "terraform-ibm-modules/resource-group/ibm"
147+
version = "1.1.6"
148+
resource_group_name = var.prefix != null ? "${var.prefix}-${var.cos_resource_group_name}" : var.cos_resource_group_name
149+
}
150+
139151
#######################################################################################################################
140152
# Observability Instance
141153
#######################################################################################################################
@@ -147,11 +159,57 @@ locals {
147159
log_analysis_instance_name = var.prefix != null ? "${var.prefix}-${var.log_analysis_instance_name}" : var.log_analysis_instance_name
148160
cloud_monitoring_instance_name = var.prefix != null ? "${var.prefix}-${var.cloud_monitoring_instance_name}" : var.cloud_monitoring_instance_name
149161
cloud_logs_instance_name = var.prefix != null ? "${var.prefix}-cloud-logs" : var.cloud_logs_instance_name
162+
cloud_logs_data_bucket_crn = var.existing_cloud_logs_data_bucket_crn != null ? var.existing_cloud_logs_data_bucket_crn : module.cos_bucket[0].buckets[local.cloud_log_data_bucket].bucket_crn
163+
cloud_log_metrics_bucket_crn = var.existing_cloud_logs_metrics_bucket_crn != null ? var.existing_cloud_logs_metrics_bucket_crn : module.cos_bucket[0].buckets[local.cloud_log_metrics_bucket].bucket_crn
164+
cloud_logs_buckets = [local.cloud_logs_data_bucket_crn, local.cloud_log_metrics_bucket_crn]
165+
}
166+
167+
data "ibm_iam_account_settings" "iam_account_settings" {
168+
}
169+
170+
resource "ibm_iam_authorization_policy" "cos_policy" {
171+
provider = ibm.cos
172+
count = var.ibmcloud_cos_api_key != null && !var.skip_cloud_logs_cos_auth_policy ? length(local.cloud_logs_buckets) : 0
173+
source_service_account = data.ibm_iam_account_settings.iam_account_settings.account_id
174+
source_service_name = "logs"
175+
roles = ["Writer"]
176+
description = "Allow Cloud logs instances `Writer` access to the COS bucket with ID ${regex("bucket:(.*)", local.cloud_logs_buckets[count.index])[0]}, in the COS instance with ID ${regex(".*:(.*):bucket:.*", local.cloud_logs_buckets[count.index])[0]}."
177+
178+
resource_attributes {
179+
name = "serviceName"
180+
operator = "stringEquals"
181+
value = "cloud-object-storage"
182+
}
183+
184+
resource_attributes {
185+
name = "accountId"
186+
operator = "stringEquals"
187+
value = data.ibm_iam_account_settings.iam_cos_account_settings[0].account_id
188+
}
189+
190+
resource_attributes {
191+
name = "serviceInstance"
192+
operator = "stringEquals"
193+
value = regex(".*:(.*):bucket:.*", local.cloud_logs_buckets[count.index])[0]
194+
}
195+
196+
resource_attributes {
197+
name = "resourceType"
198+
operator = "stringEquals"
199+
value = "bucket"
200+
}
201+
202+
resource_attributes {
203+
name = "resource"
204+
operator = "stringEquals"
205+
value = regex("bucket:(.*)", local.cloud_logs_buckets[count.index])[0]
206+
}
150207
}
151208

152209
module "observability_instance" {
153-
source = "terraform-ibm-modules/observability-instances/ibm"
154-
version = "2.19.1"
210+
depends_on = [time_sleep.wait_for_atracker_cos_authorization_policy]
211+
source = "terraform-ibm-modules/observability-instances/ibm"
212+
version = "2.19.1"
155213
providers = {
156214
logdna.at = logdna.at
157215
logdna.ld = logdna.ld
@@ -188,14 +246,16 @@ module "observability_instance" {
188246
cloud_logs_retention_period = var.cloud_logs_retention_period
189247
cloud_logs_data_storage = var.cloud_logs_provision ? {
190248
logs_data = {
191-
enabled = true
192-
bucket_crn = var.existing_cloud_logs_data_bucket_crn != null ? var.existing_cloud_logs_data_bucket_crn : module.cos_bucket[0].buckets[local.cloud_log_data_bucket].bucket_crn
193-
bucket_endpoint = var.existing_cloud_logs_data_bucket_endpoint != null ? var.existing_cloud_logs_data_bucket_endpoint : module.cos_bucket[0].buckets[local.cloud_log_data_bucket].s3_endpoint_direct
249+
enabled = true
250+
bucket_crn = local.cloud_logs_data_bucket_crn
251+
bucket_endpoint = var.existing_cloud_logs_data_bucket_endpoint != null ? var.existing_cloud_logs_data_bucket_endpoint : module.cos_bucket[0].buckets[local.cloud_log_data_bucket].s3_endpoint_direct
252+
skip_cos_auth_policy = var.ibmcloud_cos_api_key != null ? true : var.skip_cloud_logs_cos_auth_policy
194253
},
195254
metrics_data = {
196-
enabled = true # Support of routing config is tracked in https://github.com/terraform-ibm-modules/terraform-ibm-observability-da/issues/170
197-
bucket_crn = var.existing_cloud_logs_metrics_bucket_crn != null ? var.existing_cloud_logs_metrics_bucket_crn : module.cos_bucket[0].buckets[local.cloud_log_metrics_bucket].bucket_crn
198-
bucket_endpoint = var.existing_cloud_logs_metrics_bucket_endpoint != null ? var.existing_cloud_logs_metrics_bucket_endpoint : module.cos_bucket[0].buckets[local.cloud_log_metrics_bucket].s3_endpoint_direct
255+
enabled = true # Support of routing config is tracked in https://github.com/terraform-ibm-modules/terraform-ibm-observability-da/issues/170
256+
bucket_crn = local.cloud_log_metrics_bucket_crn
257+
bucket_endpoint = var.existing_cloud_logs_metrics_bucket_endpoint != null ? var.existing_cloud_logs_metrics_bucket_endpoint : module.cos_bucket[0].buckets[local.cloud_log_metrics_bucket].s3_endpoint_direct
258+
skip_cos_auth_policy = var.ibmcloud_cos_api_key != null ? true : var.skip_cloud_logs_cos_auth_policy
199259
}
200260
} : null
201261
cloud_logs_existing_en_instances = var.existing_en_instance_crn != null ? [{
@@ -216,11 +276,10 @@ module "observability_instance" {
216276
instance_id = local.cos_instance_crn
217277
target_region = local.default_cos_region
218278
target_name = local.cos_target_name
219-
skip_atracker_cos_iam_auth_policy = false
279+
skip_atracker_cos_iam_auth_policy = var.ibmcloud_cos_api_key != null ? true : var.skip_at_cos_auth_policy
220280
service_to_service_enabled = true
221281
}
222282
] : []
223-
224283
at_log_analysis_targets = var.enable_at_event_routing_to_log_analysis ? [
225284
{
226285
instance_id = module.observability_instance.log_analysis_crn
@@ -242,6 +301,22 @@ module "observability_instance" {
242301
activity_tracker_routes = local.at_routes
243302
}
244303

304+
resource "time_sleep" "wait_for_atracker_cos_authorization_policy" {
305+
count = var.ibmcloud_cos_api_key == null ? 0 : 1
306+
depends_on = [ibm_iam_authorization_policy.atracker_cos]
307+
create_duration = "30s"
308+
}
309+
resource "ibm_iam_authorization_policy" "atracker_cos" {
310+
count = var.ibmcloud_cos_api_key != null && !var.skip_at_cos_auth_policy ? 1 : 0
311+
provider = ibm.cos
312+
source_service_account = data.ibm_iam_account_settings.iam_account_settings.account_id
313+
source_service_name = "atracker"
314+
target_service_name = "cloud-object-storage"
315+
target_resource_instance_id = regex(".*:(.*)::", local.cos_instance_crn)[0]
316+
roles = ["Object Writer"]
317+
description = "Permit AT service Object Writer access to COS instance ${local.cos_instance_crn}"
318+
}
319+
245320
#######################################################################################################################
246321
# KMS Key
247322
#######################################################################################################################
@@ -288,8 +363,9 @@ resource "time_sleep" "wait_for_authorization_policy" {
288363
}
289364

290365
# Data source to account settings for retrieving cross account id
291-
data "ibm_iam_account_settings" "iam_account_settings" {
292-
count = local.apply_auth_policy
366+
data "ibm_iam_account_settings" "iam_cos_account_settings" {
367+
count = local.apply_auth_policy
368+
provider = ibm.cos
293369
}
294370

295371
# The auth policy is being created here instead of in COS module because of this limitation: https://github.com/terraform-ibm-modules/terraform-ibm-observability-da/issues/8
@@ -299,7 +375,7 @@ resource "ibm_iam_authorization_policy" "policy" {
299375
count = (var.skip_cos_kms_auth_policy || (length(coalesce(local.buckets_config, [])) == 0)) ? 0 : 1
300376
# Conditionals with providers aren't possible, using ibm.kms as provider incase cross account is enabled
301377
provider = ibm.kms
302-
source_service_account = data.ibm_iam_account_settings.iam_account_settings[0].account_id
378+
source_service_account = data.ibm_iam_account_settings.iam_cos_account_settings[0].account_id
303379
source_service_name = "cloud-object-storage"
304380
source_resource_instance_id = local.cos_instance_guid
305381
target_service_name = local.kms_service
@@ -315,7 +391,7 @@ module "cos_instance" {
315391
count = var.existing_cos_instance_crn == null && length(coalesce(local.buckets_config, [])) != 0 ? 1 : 0 # no need to call COS module if consumer is using existing COS instance
316392
source = "terraform-ibm-modules/cos/ibm//modules/fscloud"
317393
version = "8.11.11"
318-
resource_group_id = module.resource_group.resource_group_id
394+
resource_group_id = local.cos_resource_group_id
319395
create_cos_instance = true
320396
cos_instance_name = var.prefix != null ? "${var.prefix}-${var.cos_instance_name}" : var.cos_instance_name
321397
cos_tags = var.cos_instance_tags

solutions/instances/provider.tf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ provider "logdna" {
2525

2626
provider "ibm" {
2727
alias = "cos"
28-
ibmcloud_api_key = var.ibmcloud_api_key
28+
ibmcloud_api_key = var.ibmcloud_cos_api_key != null ? var.ibmcloud_cos_api_key : var.ibmcloud_api_key
2929
region = local.default_cos_region
3030
}
3131

32+
3233
provider "ibm" {
3334
alias = "kms"
3435
ibmcloud_api_key = var.ibmcloud_kms_api_key != null ? var.ibmcloud_kms_api_key : var.ibmcloud_api_key

solutions/instances/variables.tf

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,19 @@ variable "ibmcloud_api_key" {
1010

1111
variable "ibmcloud_kms_api_key" {
1212
type = string
13-
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 Object Storage instance. Leave empty if the same account owns both instances."
13+
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 Observability resources. Leave empty if the same account owns all the instances."
1414
sensitive = true
1515
default = null
1616
}
1717

18+
variable "ibmcloud_cos_api_key" {
19+
type = string
20+
description = "The IBM Cloud API key that can create a Cloud Object Storage (COS) instance. If not specified, the 'ibmcloud_api_key' variable is used. Specify this key if the COS instance is in an account that's different from the one associated Observability resources. Leave empty if the same account owns all the instances."
21+
sensitive = true
22+
default = null
23+
}
24+
25+
1826
variable "use_existing_resource_group" {
1927
type = bool
2028
description = "Whether to use an existing resource group."
@@ -26,6 +34,12 @@ variable "resource_group_name" {
2634
description = "The name of a new or existing resource group to provision resources in."
2735
}
2836

37+
variable "cos_resource_group_name" {
38+
type = string
39+
description = "The name of a new or existing resource group to provision COS instance in. If not specified, the 'resource_group_name' variable is used. Specify this if the COS instance is in an account that's different from the one associated Observability resources."
40+
default = null
41+
}
42+
2943
variable "region" {
3044
description = "The region where observability resources are created."
3145
type = string
@@ -439,6 +453,18 @@ variable "skip_cos_kms_auth_policy" {
439453
default = false
440454
}
441455

456+
variable "skip_cloud_logs_cos_auth_policy" {
457+
type = bool
458+
description = "To skip creating an IAM authorization policy that allows the IBM Cloud logs to write to the Cloud Object Storage bucket, set this variable to `true`."
459+
default = false
460+
}
461+
462+
variable "skip_at_cos_auth_policy" {
463+
type = bool
464+
description = "To skip creating an IAM authorization policy that allows the Activity Traker to write to the Cloud Object Storage instance, set this variable to `true`."
465+
default = false
466+
}
467+
442468
variable "management_endpoint_type_for_bucket" {
443469
description = "The type of endpoint for the IBM Terraform provider to use to manage Cloud Object Storage buckets (`public`, `private`, or `direct`). If you are using a private endpoint, make sure that you enable virtual routing and forwarding (VRF) in your account, and that the Terraform runtime can access the IBM Cloud Private network."
444470
type = string

0 commit comments

Comments
 (0)