From 604970a408d7ce20b2bf4a3e12af8fca96bc0c50 Mon Sep 17 00:00:00 2001 From: Chris Waddington <104161708+chrisw-ibm@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:55:46 -0500 Subject: [PATCH] feat: Add CBR's to COS bucket --- README.md | 13 +- ibm_catalog.json | 96 ++++++++++- main.tf | 190 +++++++++++++++++++++- modules/encrypted_cos_bucket/README.md | 4 +- modules/encrypted_cos_bucket/main.tf | 41 +++++ modules/encrypted_cos_bucket/outputs.tf | 12 +- modules/encrypted_cos_bucket/variables.tf | 27 ++- variables.tf | 143 ++++++++++------ 8 files changed, 467 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 2870d8f..4af4e03 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,11 @@ statement instead the previous block. | Name | Source | Version | |------|--------|---------| | [billing\_exports](#module\_billing\_exports) | ./modules/billing-exports | n/a | +| [cbr\_zone\_additional](#module\_cbr\_zone\_additional) | terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module | 1.29.0 | +| [cbr\_zone\_cloudability](#module\_cbr\_zone\_cloudability) | terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module | 1.29.0 | +| [cbr\_zone\_cos](#module\_cbr\_zone\_cos) | terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module | 1.29.0 | +| [cbr\_zone\_ibmcloud\_billing](#module\_cbr\_zone\_ibmcloud\_billing) | terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module | 1.29.0 | +| [cbr\_zone\_schematics](#module\_cbr\_zone\_schematics) | terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module | 1.29.0 | | [cloudability\_bucket\_access](#module\_cloudability\_bucket\_access) | ./modules/cloudability-bucket-access | n/a | | [cloudability\_enterprise\_access](#module\_cloudability\_enterprise\_access) | ./modules/cloudability-enterprise-access | n/a | | [cloudability\_onboarding](#module\_cloudability\_onboarding) | ./modules/cloudability-onboarding | n/a | @@ -130,11 +135,17 @@ statement instead the previous block. | [activity\_tracker\_read\_data\_events](#input\_activity\_tracker\_read\_data\_events) | If set to true, all Object Storage bucket read events (downloads) will be sent to Activity Tracker. | `bool` | `true` | no | | [activity\_tracker\_write\_data\_events](#input\_activity\_tracker\_write\_data\_events) | If set to true, all Object Storage bucket read events (downloads) will be sent to Activity Tracker. | `bool` | `true` | no | | [add\_bucket\_name\_suffix](#input\_add\_bucket\_name\_suffix) | Add random generated suffix (4 characters long) to the newly provisioned Object Storage bucket name (Optional). | `bool` | `true` | no | +| [additional\_allowed\_cbr\_bucket\_ip\_addresses](#input\_additional\_allowed\_cbr\_bucket\_ip\_addresses) | A list of CBR zone IP addresses, which are permitted to access the bucket. This zone typically represents the IP addresses for your company or workstation to allow access to view the contents of the bucket. | `list(string)` | `[]` | no | | [archive\_days](#input\_archive\_days) | Specifies the number of days when the archive rule action takes effect. A value of `null` disables archiving. A value of `0` immediately archives uploaded objects to the bucket. | `number` | `null` | no | | [archive\_type](#input\_archive\_type) | Specifies the storage class or archive type to which you want the object to transition. | `string` | `"Glacier"` | no | -| [bucket\_cbr\_rules](#input\_bucket\_cbr\_rules) | (Optional, list) List of CBR rules to create for the bucket |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | | [bucket\_name](#input\_bucket\_name) | The name to give the newly provisioned Object Storage bucket. | `string` | `"billing-reports"` | no | | [bucket\_storage\_class](#input\_bucket\_storage\_class) | The storage class of the newly provisioned Object Storage bucket. Supported values are 'standard', 'vault', 'cold', 'smart' and `onerate_active`. | `string` | `"standard"` | no | +| [cbr\_additional\_zone\_name](#input\_cbr\_additional\_zone\_name) | Name of the CBR zone that corresponds to the ip address range set in `additional_allowed_cbr_bucket_ip_addresses`. | `string` | `"company-billing-reports-bucket-access"` | no | +| [cbr\_billing\_zone\_name](#input\_cbr\_billing\_zone\_name) | Name of the CBR zone which represents IBM Cloud billing. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis) | `string` | `"ibmcloud-billing-reports-bucket-writer"` | no | +| [cbr\_cloudability\_zone\_name](#input\_cbr\_cloudability\_zone\_name) | Name of the CBR zone which represents IBM Cloudability. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis) | `string` | `"cldy-billing-reports-bucket-reader"` | no | +| [cbr\_cos\_zone\_name](#input\_cbr\_cos\_zone\_name) | Name of the CBR zone which represents Cloud Object Storage service. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis) | `string` | `"cldy-billing-reports-object-storage"` | no | +| [cbr\_enforcement\_mode](#input\_cbr\_enforcement\_mode) | The rule enforcement mode: * enabled - The restrictions are enforced and reported. This is the default. * disabled - The restrictions are disabled. Nothing is enforced or reported. * report - The restrictions are evaluated and reported, but not enforced. | `string` | `"enabled"` | no | +| [cbr\_schematics\_zone\_name](#input\_cbr\_schematics\_zone\_name) | Name of the CBR zone which represents Schematics. The schematics zone allows Projects to access and manage the Object Storage bucket. | `string` | `"schematics-billing-reports-bucket-management"` | no | | [cloudability\_api\_key](#input\_cloudability\_api\_key) | Cloudability API Key. Retrieve your Api Key from https://app.apptio.com/cloudability#/settings/preferences under the section **Cloudability API** select **Enable API** which will generate an api key. Setting this value to __NULL__ will skip adding the IBM Cloud account to Cloudability and only configure IBM Cloud so that the IBM Cloud Account can be added to Cloudability manually | `string` | `null` | no | | [cloudability\_auth\_type](#input\_cloudability\_auth\_type) | Select Cloudability authentication mode. Options are:

* `none`: no connection to Cloudability
* `manual`: manually enter in the credentials in the Cloudability UI
* `api_key`: use Cloudability API Keys
* `frontdoor`: Frontdoor Access Administration | `string` | `"api_key"` | no | | [cloudability\_environment\_id](#input\_cloudability\_environment\_id) | An ID corresponding to your FrontDoor environment. Required if `cloudability_auth_type` = `frontdoor` | `string` | `null` | no | diff --git a/ibm_catalog.json b/ibm_catalog.json index 024dad6..b401a64 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -31,6 +31,10 @@ "title": "Secured with Key Protect", "description": "Your Object Storage bucket containing billing reports is encrypted with a Key Protect encryption key with automated rotation. See [encrypting a bucket with Key Protect](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-tutorial-kp-encrypt-bucket) for more details." }, + { + "title": "Context-Based Restrictions", + "description": "Access to your Object Storage bucket is restricted to IBM Cloud Billing, IBM Cloudability, and Schematics (for provisioning) by using [context-based restrictions](/docs/account?topic=account-context-restrictions-whatis)." + }, { "title": "Least Privileged Operations to Cloudability", "description": "Custom IAM access roles are used so that Cloudability is granted the minimal required access to integrate with your IBM Cloud Account." @@ -83,6 +87,18 @@ "crn:v1:bluemix:public:iam::::role:Administrator" ] }, + { + "service_name": "cbr", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Viewer" + ] + }, + { + "service_name": "schematics", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Administrator" + ] + }, { "service_name": "cloud-object-storage", "role_crns": [ @@ -478,10 +494,80 @@ } ] }, + { + "key": "cbr_enforcement_mode", + "type": "string", + "default_value": "enabled", + "description": "The rule enforcement mode: \n* enabled - The restrictions are enforced and reported.\n* disabled - The restrictions are disabled. Nothing is enforced or reported.\n* report - The restrictions are evaluated and reported, but not enforced.", + "required": false, + "options": [ + { + "displayname": "Enabled (Restrict access to bucket)", + "value": "enabled" + }, + { + "displayname": "Disabled (No access restrictions or audit logging)", + "value": "disabled" + }, + { + "displayname": "Report-Only (No access restrictions, but audit logs are still enabled)", + "value": "report" + } + ] + }, + { + "key": "additional_allowed_cbr_bucket_ip_addresses", + "type": "array", + "default_value": "[]", + "description": "A list of CBR zone address which are permitted to access the bucket. This zone typically represents the IP addresses for your company or workstation to allow access to view the contents of the bucket.", + "required": false + }, + { + "key": "existing_allowed_cbr_bucket_zone_id", + "type": "string", + "default_value": "[]", + "description": "A list of CBR zone address which are permitted to access the bucket. This zone typically represents the IP addresses for your company or workstation to allow access to view the contents of the bucket.", + "required": false + }, + { + "key": "cbr_additional_zone_name", + "type": "string", + "default_value": "__NULL__", + "description": "An extra CBR zone ID which is permitted to access the bucket. This zone typically represents the IP addresses for your company or workstation to allow access to view the contents of the bucket. It can be used as an alternative to `additional_allowed_cbr_bucket_ip_addresses` in the case that a zone exists.", + "required": false + }, + { + "key": "cbr_billing_zone_name", + "type": "string", + "default_value": "ibmcloud-billing-reports-bucket-writer", + "description": "Name of the cbr zone which represents IBM Cloud billing", + "required": false + }, + { + "key": "cbr_cloudability_zone_name", + "type": "string", + "default_value": "cldy-billing-reports-bucket-reader", + "description": "Name of the CBR zone which represents IBM Cloudability. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis)", + "required": false + }, + { + "key": "cbr_cos_zone_name", + "type": "string", + "default_value": "cldy-billing-reports-object-storage", + "description": "Name of the CBR zone which represents Cloud Object Storage service. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis)", + "required": false + }, + { + "key": "cbr_schematics_zone_name", + "type": "string", + "default_value": "schematics-billing-reports-bucket-management", + "description": "Name of the CBR zone which represents Schematics. The schematics zone allows Projects to access and manage the Object Storage bucket.", + "required": false + }, { "key": "existing_kms_instance_crn", "type": "string", - "description": "The CRN of an existing Key Protect or Hyper Protect Crypto Services instance to be used to create the Object Storage encryption key.", + "description": "The ID of an existing Key Protect or Hyper Protect Crypto Services instance to be used to create the object storage encryption key.", "default_value": "__NULL__", "required": false }, @@ -733,6 +819,14 @@ "key": "cos_instance_name", "description": "Name of the Object Storage Instance" }, + { + "key": "bucket_cbr_rule_ids", + "description": "Object Storage bucket rule ids" + }, + { + "key": "bucket_cbr_rules", + "description": "Object Storage bucket rules" + }, { "key": "key_protect_guid", "description": "ID of the Key Protect instance which contains the encryption key for the object storage bucket" diff --git a/main.tf b/main.tf index 0bf17ec..7459691 100644 --- a/main.tf +++ b/main.tf @@ -19,6 +19,7 @@ locals { bucket_storage_class = var.cos_plan == "cos-one-rate-plan" ? "onerate_active" : var.bucket_storage_class create_key_protect_instance = var.existing_kms_instance_crn == null create_cos_instance = var.existing_cos_instance_id == null + additional_zone_addresses = [for ip_addresses in var.additional_allowed_cbr_bucket_ip_addresses : length(regexall("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", ip_addresses)) > 0 ? { type = "ipAddress", value = ip_addresses } : { type = "ipRange", value = ip_addresses }] } module "resource_group" { @@ -29,6 +30,191 @@ module "resource_group" { existing_resource_group_name = var.use_existing_resource_group == true ? var.resource_group_name : null } +############################################################################## +# Create CBR Zone +############################################################################## + +module "cbr_zone_ibmcloud_billing" { + source = "terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module" + version = "1.29.0" + name = var.cbr_billing_zone_name + zone_description = "IBM Cloud Billing report exports to object storage. Managed by IBM Cloudability Enablement deployable architecture" + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + addresses = [ + { + type = "serviceRef", # to bind a schematics to the zone + ref = { + # Allow all schematics instances from all geographies + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + service_name = "billing" + } + } + # { + # type = "ipRange", + # value = "169.47.98.0-169.47.98.255" + # }, { + # type = "ipRange", + # value = "169.60.75.0-169.60.75.255" + # }, + # { + # type = "ipRange", + # value = "169.61.58.0-169.61.58.255" + # }, + # { + # type = "ipRange", + # value = "169.62.146.0-169.62.146.255" + # }, + # { + # type = "ipRange", + # value = "169.63.133.0-169.63.133.255" + # } + ] +} + +module "cbr_zone_cloudability" { + source = "terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module" + version = "1.29.0" + name = var.cbr_cloudability_zone_name + zone_description = "IBM Cloudability access to billing reports object storage bucket. Managed by IBM Cloudability Enablement deployable architecture" + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + addresses = [ + { + type = "serviceRef", + ref = { + # Allow all schematics instances from all geographies + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + service_name = "cloudability" + } + } + # { + # type = "ipRange", + # value = "103.195.128.0-103.195.128.255" + # }, + # { + # type = "ipRange", + # value = "103.195.130.0-103.195.130.255" + # } + ] +} + + +module "cbr_zone_additional" { + count = length(local.additional_zone_addresses) > 0 ? 1 : 0 + source = "terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module" + version = "1.29.0" + name = var.cbr_additional_zone_name + zone_description = "Additional IP Addresses allowed to access the billing reports bucket. Managed by IBM Cloudability Enablement deployable architecture" + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + addresses = local.additional_zone_addresses +} + +module "cbr_zone_schematics" { + source = "terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module" + version = "1.29.0" + name = var.cbr_schematics_zone_name + zone_description = "Schematics access to manage the Object storage bucket through Projects. Managed by IBM Cloudability Enablement deployable architecture" + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + addresses = [{ + type = "serviceRef", # to bind a schematics to the zone + ref = { + # Allow all schematics instances from all geographies + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + service_name = "schematics" + } + }] +} + +module "cbr_zone_cos" { + source = "terraform-ibm-modules/cbr/ibm//modules/cbr-zone-module" + version = "1.29.0" + name = var.cbr_cos_zone_name + zone_description = "Cloud Object storage can access the encryption key to manage the Object storage bucket. Managed by IBM Cloudability Enablement deployable architecture" + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + addresses = [{ + type = "serviceRef", # to bind a schematics to the zone + ref = { + # Allow cloud-object-storage instances from all geographies + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + service_name = "cloud-object-storage" + service_instance = module.cos_bucket.cos_instance_guid + } + }] +} + +locals { + cos_instance_rule_contexts = [{ + attributes = [ + { + name = "endpointType" + value = "public" + }, + { + name = "networkZoneId" + value = module.cbr_zone_cloudability.zone_id + } + ] + }, + { + attributes = [ + { + name = "networkZoneId" + value = module.cbr_zone_schematics.zone_id + } + ] + }, + { + attributes = [ + { + name = "networkZoneId" + value = module.cbr_zone_ibmcloud_billing.zone_id + } + ] + } + ] + kms_key_rule_contexts = [{ + attributes = [ + { + name = "networkZoneId" + value = module.cbr_zone_cos.zone_id + } + ] + }, + { + attributes = [ + { + name = "endpointType" + value = "private" + }, + { + name = "networkZoneId" + value = module.cbr_zone_schematics.zone_id + } + ] + } + ] + additional_rule_contexts = length(local.additional_zone_addresses) > 0 ? [{ attributes = [{ name = "networkZoneId", value = module.cbr_zone_additional[0].zone_id }] }] : [] + existing_allowed_cbr_bucket_zone_id = var.existing_allowed_cbr_bucket_zone_id != null ? [{ attributes = [{ name = "networkZoneId", value = var.existing_allowed_cbr_bucket_zone_id }] }] : [] + all_rule_contexts = concat(local.cos_instance_rule_contexts, local.additional_rule_contexts, local.existing_allowed_cbr_bucket_zone_id) + + cos_bucket_cbr_rules = [ + { + description = "Access to the billing report exports bucket is limited to IBM Cloudability and IBM Cloud Billing. Managed by IBM Cloudability Enablement deployable architecture." + enforcement_mode = var.cbr_enforcement_mode + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + rule_contexts = local.all_rule_contexts + } + ] + all_kms_rule_contexts = concat(local.kms_key_rule_contexts, local.additional_rule_contexts, local.existing_allowed_cbr_bucket_zone_id) + kms_key_cbr_rules = [ + { + description = "Access to the kms encryption key is limited to being accessed by cloud object storage. Managed by IBM Cloudability Enablement deployable architecture." + enforcement_mode = var.cbr_enforcement_mode + account_id = data.ibm_iam_account_settings.billing_exports_account.account_id + rule_contexts = local.all_kms_rule_contexts + } + ] +} + module "cos_bucket" { providers = { ibm = ibm @@ -68,8 +254,8 @@ module "cos_bucket" { rotation_enabled = var.kms_rotation_enabled key_endpoint_type = var.kms_endpoint_type key_ring_endpoint_type = var.kms_endpoint_type - cos_bucket_cbr_rules = var.bucket_cbr_rules - cos_instance_cbr_rules = var.instance_cbr_rules + cos_bucket_cbr_rules = local.cos_bucket_cbr_rules + kms_key_cbr_rules = local.kms_key_cbr_rules skip_iam_authorization_policy = var.skip_iam_authorization_policy key_protect_allowed_network = var.key_protect_allowed_network } diff --git a/modules/encrypted_cos_bucket/README.md b/modules/encrypted_cos_bucket/README.md index b79c325..9ba6658 100644 --- a/modules/encrypted_cos_bucket/README.md +++ b/modules/encrypted_cos_bucket/README.md @@ -73,6 +73,7 @@ statement instead the previous block. |------|--------|---------| | [cos\_bucket](#module\_cos\_bucket) | terraform-ibm-modules/cos/ibm | 8.16.4 | | [key\_protect\_all\_inclusive](#module\_key\_protect\_all\_inclusive) | terraform-ibm-modules/kms-all-inclusive/ibm | 4.19.1 | +| [key\_protect\_key\_cbr\_rule](#module\_key\_protect\_key\_cbr\_rule) | terraform-ibm-modules/cbr/ibm//modules/cbr-rule-module | 1.29.0 | ### Resources @@ -107,6 +108,7 @@ No resources. | [key\_protect\_instance\_name](#input\_key\_protect\_instance\_name) | Key Protect instance name | `string` | `null` | no | | [key\_ring\_endpoint\_type](#input\_key\_ring\_endpoint\_type) | The type of endpoint to be used for creating key rings. Accepts 'public' or 'private' | `string` | `"public"` | no | | [key\_ring\_name](#input\_key\_ring\_name) | Name of the key ring to group keys | `string` | `"bucket-encryption"` | no | +| [kms\_key\_cbr\_rules](#input\_kms\_key\_cbr\_rules) | (Optional, list) List of CBR rules to create for the instance |
list(object({
description = string
account_id = string
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
tags = optional(list(object({
name = string
value = string
})), [])
operations = optional(list(object({
api_types = list(object({
api_type_id = string
}))
})))
}))
| `[]` | no | | [management\_endpoint\_type\_for\_bucket](#input\_management\_endpoint\_type\_for\_bucket) | The type of endpoint for the IBM terraform provider to use to manage the bucket. (public, private, or direct) | `string` | `"public"` | no | | [monitoring\_crn](#input\_monitoring\_crn) | The CRN of an IBM Cloud Monitoring instance to send Object Storage bucket metrics to. If no value passed, metrics are sent to the instance associated to the container's location unless otherwise specified in the Metrics Router service configuration. | `string` | `null` | no | | [object\_versioning\_enabled](#input\_object\_versioning\_enabled) | Enable object versioning to keep multiple versions of an object in a bucket. | `bool` | `false` | no | @@ -129,13 +131,13 @@ No resources. | Name | Description | |------|-------------| +| [bucket\_cbr\_rule\_ids](#output\_bucket\_cbr\_rule\_ids) | Object Storage bucket rule ids | | [bucket\_cbr\_rules](#output\_bucket\_cbr\_rules) | Object Storage bucket rules | | [bucket\_crn](#output\_bucket\_crn) | Bucket CRN | | [bucket\_id](#output\_bucket\_id) | Bucket id | | [bucket\_name](#output\_bucket\_name) | Bucket name | | [bucket\_region](#output\_bucket\_region) | Bucket region if you create a regional bucket | | [bucket\_storage\_class](#output\_bucket\_storage\_class) | Bucket Storage Class | -| [cbr\_rule\_ids](#output\_cbr\_rule\_ids) | List of all rule ids | | [cos\_instance\_guid](#output\_cos\_instance\_guid) | The GUID of the Cloud Object Storage Instance where the buckets are created | | [cos\_instance\_id](#output\_cos\_instance\_id) | The ID of the Cloud Object Storage Instance where the buckets are created | | [instance\_cbr\_rules](#output\_instance\_cbr\_rules) | COS instance rules | diff --git a/modules/encrypted_cos_bucket/main.tf b/modules/encrypted_cos_bucket/main.tf index c24b421..0d7d105 100644 --- a/modules/encrypted_cos_bucket/main.tf +++ b/modules/encrypted_cos_bucket/main.tf @@ -66,6 +66,47 @@ module "key_protect_all_inclusive" { access_tags = var.access_tags } +locals { + default_operations = [{ + api_types = [{ + api_type_id = "crn:v1:bluemix:public:context-based-restrictions::::api-type:" + }] + }] +} + +module "key_protect_key_cbr_rule" { + count = length(var.kms_key_cbr_rules) > 0 ? length(var.kms_key_cbr_rules) : 0 + source = "terraform-ibm-modules/cbr/ibm//modules/cbr-rule-module" + version = "1.29.0" + rule_description = var.kms_key_cbr_rules[count.index].description + enforcement_mode = var.kms_key_cbr_rules[count.index].enforcement_mode + rule_contexts = var.kms_key_cbr_rules[count.index].rule_contexts + resources = [{ + attributes = [ + { + name = "accountId" + value = var.kms_key_cbr_rules[count.index].account_id + }, + { + name = "serviceInstance" + value = local.existing_kms_instance_guid + operator = "stringEquals" + }, + { + name = "serviceName" + value = "kms" + }, + { + name = "resource" + value = local.key_name + operator = "stringEquals" + } + ], + tags = var.kms_key_cbr_rules[count.index].tags + }] + operations = var.kms_key_cbr_rules[count.index].operations == null ? local.default_operations : var.kms_key_cbr_rules[count.index].operations +} + ############################################################################## # Get Cloud Account ID ############################################################################## diff --git a/modules/encrypted_cos_bucket/outputs.tf b/modules/encrypted_cos_bucket/outputs.tf index e486fe5..a621fba 100644 --- a/modules/encrypted_cos_bucket/outputs.tf +++ b/modules/encrypted_cos_bucket/outputs.tf @@ -57,8 +57,8 @@ output "instance_cbr_rules" { value = module.cos_bucket.instance_cbr_rules } -output "cbr_rule_ids" { - description = "List of all rule ids" +output "bucket_cbr_rule_ids" { + description = "Object Storage bucket rule ids" value = module.cos_bucket.cbr_rule_ids } output "bucket_cbr_rules" { @@ -88,20 +88,20 @@ output "key_protect_guid" { output "key_protect_name" { description = "Key Protect Name" - value = local.key_management_enabled ? module.key_protect_all_inclusive[0].key_protect_name : null + value = module.key_protect_all_inclusive.key_protect_name } output "key_protect_instance_policies" { description = "Instance Polices of the Key Protect instance" - value = local.key_management_enabled ? module.key_protect_all_inclusive[0].key_protect_instance_policies : null + value = module.key_protect_all_inclusive.key_protect_instance_policies } output "key_rings" { description = "IDs of new Key Rings created by the module" - value = local.key_management_enabled ? module.key_protect_all_inclusive[0].key_rings : null + value = module.key_protect_all_inclusive.key_rings } output "keys" { description = "IDs of new Keys created by the module" - value = local.key_management_enabled ? module.key_protect_all_inclusive[0].keys : null + value = module.key_protect_all_inclusive.keys } diff --git a/modules/encrypted_cos_bucket/variables.tf b/modules/encrypted_cos_bucket/variables.tf index 9915c88..2076d53 100644 --- a/modules/encrypted_cos_bucket/variables.tf +++ b/modules/encrypted_cos_bucket/variables.tf @@ -297,7 +297,7 @@ variable "cos_bucket_cbr_rules" { # Validation happens in the rule module } -variable "cos_instance_cbr_rules" { +variable "instance_cbr_rules" { type = list(object({ description = string account_id = string @@ -364,6 +364,31 @@ variable "rotation_interval_month" { default = 1 } +variable "kms_key_cbr_rules" { + type = list(object({ + description = string + account_id = string + rule_contexts = list(object({ + attributes = optional(list(object({ + name = string + value = string + }))) })) + enforcement_mode = string + tags = optional(list(object({ + name = string + value = string + })), []) + operations = optional(list(object({ + api_types = list(object({ + api_type_id = string + })) + }))) + })) + description = "(Optional, list) List of CBR rules to create for the instance" + default = [] + # Validation happens in the rule module +} + variable "skip_iam_authorization_policy" { type = bool description = "Set to true to skip the creation of an IAM authorization policy that permits the COS instance created to read the encryption key from the KMS instance in `existing_kms_instance_crn`. WARNING: An authorization policy must exist before an encrypted bucket can be created" diff --git a/variables.tf b/variables.tf index c5bf86f..e35c3a7 100644 --- a/variables.tf +++ b/variables.tf @@ -345,6 +345,7 @@ variable "existing_kms_instance_crn" { } } + variable "key_protect_allowed_network" { type = string description = "The type of the allowed network to be set for the Key Protect instance. Possible values are 'private-only', or 'public-and-private'. Only used if 'create_key_protect_instance' is true." @@ -355,59 +356,107 @@ variable "key_protect_allowed_network" { } } +variable "kms_endpoint_type" { + type = string + description = "The type of endpoint to be used for management of key protect." + default = "public" + validation { + condition = can(regex("public|private", var.kms_endpoint_type)) + error_message = "The endpoint_type value must be 'public' or 'private'." + } +} + +variable "kms_rotation_enabled" { + type = bool + description = "If set to true, Key Protect enables a rotation policy on the Key Protect instance. Only used if 'create_key_protect_instance' is true." + default = true +} + +variable "kms_rotation_interval_month" { + type = number + description = "Specifies the number of months for the encryption key to be rotated.. Must be between 1 and 12 inclusive." + default = 1 + validation { + condition = var.kms_rotation_interval_month >= 1 && var.kms_rotation_interval_month <= 12 + error_message = "The key rotation time interval must be greater than 0 and less than 13" + } +} + + ############################################################## # Context-based restriction (CBR) ############################################################## -variable "bucket_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - tags = optional(list(object({ - name = string - value = string - })), []) - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "(Optional, list) List of CBR rules to create for the bucket" - default = [] - # Validation happens in the rule module -} - -variable "instance_cbr_rules" { - type = list(object({ - description = string - account_id = string - rule_contexts = list(object({ - attributes = optional(list(object({ - name = string - value = string - }))) })) - enforcement_mode = string - tags = optional(list(object({ - name = string - value = string - })), []) - operations = optional(list(object({ - api_types = list(object({ - api_type_id = string - })) - }))) - })) - description = "(Optional, list) List of CBR rules to create for the instance" +variable "cbr_enforcement_mode" { + type = string + description = "The rule enforcement mode: * enabled - The restrictions are enforced and reported. This is the default. * disabled - The restrictions are disabled. Nothing is enforced or reported. * report - The restrictions are evaluated and reported, but not enforced." + default = "enabled" + validation { + condition = contains(["enabled", "disabled", "report"], var.cbr_enforcement_mode) + error_message = "Invalid cbr_enforcement_mode: use one of \"enabled\", \"disabled\", or \"report\". See CBR Rule Enforcement docs for more details: https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis&interface=ui#rule-enforcement" + } +} +variable "cbr_billing_zone_name" { + type = string + description = "Name of the CBR zone which represents IBM Cloud billing. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis)" + default = "ibmcloud-billing-reports-bucket-writer" + validation { + condition = can(regex("^[a-zA-Z0-9 -_]{1,128}$", var.cbr_billing_zone_name)) + error_message = "Invalid `cbr_billing_zone_name`: value must meet the following regular expression /^[a-zA-Z0-9 -_]+$/ and have length > 1 and < 128" + } +} + +variable "cbr_cloudability_zone_name" { + type = string + description = "Name of the CBR zone which represents IBM Cloudability. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis)" + default = "cldy-billing-reports-bucket-reader" + validation { + condition = can(regex("^[a-zA-Z0-9 -_]{1,128}$", var.cbr_cloudability_zone_name)) + error_message = "Invalid `cbr_cloudability_zone_name`: value must meet the following regular expression /^[a-zA-Z0-9 -_]+$/ and have length > 1 and < 128" + } +} + +variable "cbr_cos_zone_name" { + type = string + description = "Name of the CBR zone which represents Cloud Object Storage service. See [What are CBRs?](https://cloud.ibm.com/docs/account?topic=account-context-restrictions-whatis)" + default = "cldy-billing-reports-object-storage" + validation { + condition = can(regex("^[a-zA-Z0-9 -_]{1,128}$", var.cbr_cos_zone_name)) + error_message = "Invalid `cbr_cloudability_zone_name`: value must meet the following regular expression /^[a-zA-Z0-9 -_]+$/ and have length > 1 and < 128" + } +} + +variable "cbr_schematics_zone_name" { + type = string + description = "Name of the CBR zone which represents Schematics. The schematics zone allows Projects to access and manage the Object Storage bucket." + default = "schematics-billing-reports-bucket-management" + validation { + condition = can(regex("^[a-zA-Z0-9 -_]{1,128}$", var.cbr_schematics_zone_name)) + error_message = "Invalid `cbr_schematics_zone_name`: value must meet the following regular expression /^[a-zA-Z0-9 -_]+$/ and have length > 1 and < 128" + } +} + +variable "cbr_additional_zone_name" { + type = string + description = "Name of the CBR zone that corresponds to the ip address range set in `additional_allowed_cbr_bucket_ip_addresses`." + default = "company-billing-reports-bucket-access" + validation { + condition = can(regex("^[a-zA-Z0-9 -_]{1,128}$", var.cbr_additional_zone_name)) + error_message = "Invalid `cbr_additional_zone_name`: value must meet the following regular expression /^[a-zA-Z0-9 -_]+$/ and have length > 1 and < 128" + } +} + +variable "additional_allowed_cbr_bucket_ip_addresses" { + type = list(string) + description = "A list of CBR zone IP addresses, which are permitted to access the bucket. This zone typically represents the IP addresses for your company or workstation to allow access to view the contents of the bucket." default = [] - # Validation happens in the rule module +} + +variable "existing_allowed_cbr_bucket_zone_id" { + type = string + description = "An extra CBR zone ID which is permitted to access the bucket. This zone typically represents the ip addresses for your company or workstation to allow access to view the contents of the bucket. It can be used as an alternative to `additional_allowed_cbr_bucket_ip_addresses` in the case that a zone exists." + default = null }