diff --git a/README.md b/README.md index b2023bc..d8ccc56 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ A module for provisioning an [IBM Cloud Security and Compliance Center Workload ## Overview * [terraform-ibm-scc-workload-protection](#terraform-ibm-scc-workload-protection) +* [Submodules](./modules) + * [account_check](./modules/account_check) * [Examples](./examples) * [Advanced example](./examples/advanced) * [Basic example](./examples/basic) @@ -114,6 +116,7 @@ statement instead the previous block. | Name | Source | Version | |------|--------|---------| +| [account\_type\_check](#module\_account\_type\_check) | ./modules/account_check | n/a | | [cbr\_rule](#module\_cbr\_rule) | terraform-ibm-modules/cbr/ibm//modules/cbr-rule-module | 1.33.6 | | [trusted\_profile\_scc\_wp](#module\_trusted\_profile\_scc\_wp) | terraform-ibm-modules/trusted-profile/ibm | 3.1.1 | @@ -135,6 +138,7 @@ statement instead the previous block. | [cbr\_rules](#input\_cbr\_rules) | The list of context-based restriction rules to create. |
list(object({
description = string
account_id = string
tags = optional(list(object({
name = string
value = string
})), [])
rule_contexts = list(object({
attributes = optional(list(object({
name = string
value = string
}))) }))
enforcement_mode = string
}))
| `[]` | no | | [cloud\_monitoring\_instance\_crn](#input\_cloud\_monitoring\_instance\_crn) | To collect and analyze metrics and security data on hosts using both Monitoring and Workload Protection, pass the CRN of an existing IBM Cloud Monitoring instance to create a connection between instances. Both instances must be in the same region. | `string` | `null` | no | | [cspm\_enabled](#input\_cspm\_enabled) | Enable Cloud Security Posture Management (CSPM) for the Workload Protection instance. This will create a trusted profile associated with the SCC Workload Protection instance that has viewer / reader access to the App Config service and viewer access to the Enterprise service. [Learn more](https://cloud.ibm.com/docs/workload-protection?topic=workload-protection-about). | `bool` | `true` | no | +| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The IBM Cloud platform API key needed to deploy IAM enabled resources. | `string` | n/a | yes | | [name](#input\_name) | The name to give the SCC Workload Protection instance that will be provisioned by this module. | `string` | n/a | yes | | [region](#input\_region) | IBM Cloud region where all resources will be deployed | `string` | `"us-south"` | no | | [resource\_group\_id](#input\_resource\_group\_id) | The resource group ID where resources will be provisioned. | `string` | n/a | yes | @@ -150,6 +154,7 @@ statement instead the previous block. |------|-------------| | [access\_key](#output\_access\_key) | Workload Protection instance access key. | | [account\_id](#output\_account\_id) | Account ID of created SCC WP instance. | +| [account\_type](#output\_account\_type) | The determined type of the IBM Cloud account. | | [api\_endpoint](#output\_api\_endpoint) | API endpoint. | | [crn](#output\_crn) | CRN of created SCC WP instance. | | [guid](#output\_guid) | GUID of created SCC WP instance. | diff --git a/examples/advanced/main.tf b/examples/advanced/main.tf index 2c0d408..1055a76 100644 --- a/examples/advanced/main.tf +++ b/examples/advanced/main.tf @@ -110,4 +110,5 @@ module "scc_wp" { }] } ] + ibmcloud_api_key = var.ibmcloud_api_key } diff --git a/examples/basic/main.tf b/examples/basic/main.tf index 31152cd..eedcf84 100644 --- a/examples/basic/main.tf +++ b/examples/basic/main.tf @@ -22,4 +22,5 @@ module "scc_wp" { resource_tags = var.resource_tags access_tags = var.access_tags cspm_enabled = false + ibmcloud_api_key = var.ibmcloud_api_key } diff --git a/examples/basic/outputs.tf b/examples/basic/outputs.tf index b210f3f..c06f16d 100644 --- a/examples/basic/outputs.tf +++ b/examples/basic/outputs.tf @@ -39,3 +39,8 @@ output "access_key" { value = module.scc_wp.access_key sensitive = true } + +output "account_type" { + description = "The determined type of the IBM Cloud account." + value = module.scc_wp.account_type +} diff --git a/examples/basic/variables.tf b/examples/basic/variables.tf index a372112..c1b5946 100644 --- a/examples/basic/variables.tf +++ b/examples/basic/variables.tf @@ -11,7 +11,7 @@ variable "ibmcloud_api_key" { variable "prefix" { description = "Display name of the prefix for related resources" type = string - default = "scc-wp" + default = "scc-wp-new" } variable "region" { diff --git a/examples/enterprise/main.tf b/examples/enterprise/main.tf index fe84360..9e31402 100644 --- a/examples/enterprise/main.tf +++ b/examples/enterprise/main.tf @@ -47,4 +47,5 @@ module "scc_wp" { cspm_enabled = true app_config_crn = module.app_config.app_config_crn scc_workload_protection_trusted_profile_name = "${var.prefix}-scc-wp-tp" + ibmcloud_api_key = var.ibmcloud_api_key } diff --git a/main.tf b/main.tf index 48b2828..17535b5 100644 --- a/main.tf +++ b/main.tf @@ -8,6 +8,10 @@ # SCC WP ############################################################################## +locals { + target_account_id = ibm_resource_instance.scc_wp.account_id +} + resource "ibm_resource_instance" "scc_wp" { name = var.name resource_group_id = var.resource_group_id @@ -20,6 +24,18 @@ resource "ibm_resource_instance" "scc_wp" { } } +############################################################################## +# Check Account Type +############################################################################## + + +module "account_type_check" { + source = "./modules/account_check" + target_account_id = local.target_account_id + ibmcloud_api_key = var.ibmcloud_api_key +} + + ############################################################################## # SCC WP Instance Key ############################################################################## diff --git a/modules/account_check/README.md b/modules/account_check/README.md new file mode 100644 index 0000000..fb7055e --- /dev/null +++ b/modules/account_check/README.md @@ -0,0 +1,36 @@ +# Account Check + +This module determines whether a given IBM Cloud account is part of an `Enterprise` or is a `Standalone (Normal)` account. +It uses the IBM Cloud Enterprise Management API and can be easily integrated into Terraform configurations via the external data source. + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.9.0 | +| [external](#requirement\_external) | 2.3.5 | + +### Modules + +No modules. + +### Resources + +| Name | Type | +|------|------| +| [external_external.account_check](https://registry.terraform.io/providers/hashicorp/external/2.3.5/docs/data-sources/external) | data source | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [ibmcloud\_api\_key](#input\_ibmcloud\_api\_key) | The IBM Cloud platform API key needed to deploy IAM enabled resources. | `string` | n/a | yes | +| [target\_account\_id](#input\_target\_account\_id) | The ID of the target account to check for type. | `string` | n/a | yes | + +### Outputs + +| Name | Description | +|------|-------------| +| [account\_type](#output\_account\_type) | The determined type of the IBM Cloud account. | + diff --git a/modules/account_check/main.tf b/modules/account_check/main.tf new file mode 100644 index 0000000..df03fec --- /dev/null +++ b/modules/account_check/main.tf @@ -0,0 +1,12 @@ +locals { + # Set account_type variable from the external data source's JSON output. + account_type = data.external.account_check.result.account_type +} + +data "external" "account_check" { + program = ["/bin/bash", "${path.module}/../scripts/account-check.sh"] + query = { + account_id = var.target_account_id + api_key = var.ibmcloud_api_key + } +} diff --git a/modules/account_check/outputs.tf b/modules/account_check/outputs.tf new file mode 100644 index 0000000..81079b8 --- /dev/null +++ b/modules/account_check/outputs.tf @@ -0,0 +1,4 @@ +output "account_type" { + description = "The determined type of the IBM Cloud account." + value = local.account_type +} diff --git a/modules/account_check/variables.tf b/modules/account_check/variables.tf new file mode 100644 index 0000000..768438e --- /dev/null +++ b/modules/account_check/variables.tf @@ -0,0 +1,10 @@ +variable "ibmcloud_api_key" { + description = "The IBM Cloud platform API key needed to deploy IAM enabled resources." + type = string + sensitive = true +} + +variable "target_account_id" { + description = "The ID of the target account to check for type." + type = string +} diff --git a/modules/account_check/version.tf b/modules/account_check/version.tf new file mode 100644 index 0000000..4f743a1 --- /dev/null +++ b/modules/account_check/version.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + external = { + source = "hashicorp/external" + version = "2.3.5" + } + } +} diff --git a/modules/scripts/account-check.sh b/modules/scripts/account-check.sh new file mode 100755 index 0000000..49b960f --- /dev/null +++ b/modules/scripts/account-check.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +read -r TF_INPUT +ACCOUNT_ID=$(echo "$TF_INPUT" | jq -r '.account_id') +IBM_CLOUD_API_KEY=$(echo "$TF_INPUT" | jq -r '.api_key') + +# --- Obtain IAM Token --- +IAM_TOKEN=$(curl -s -X POST "https://iam.cloud.ibm.com/identity/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey=${IBM_CLOUD_API_KEY}" \ + | jq -r '.access_token') + +# --- Query Enterprise API --- +HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/account.json \ + -X GET "https://enterprise.cloud.ibm.com/v1/accounts/${ACCOUNT_ID}" \ + -H "Authorization: Bearer ${IAM_TOKEN}") + +# --- Determine Account Type --- +ACCOUNT_TYPE="NORMAL" +if [ "$HTTP_CODE" == "200" ] && grep -q '"enterprise_id"' /tmp/account.json; then + ACCOUNT_TYPE="ENTERPRISE" +fi + +# --- Output for Terraform --- +echo "{\"account_type\": \"${ACCOUNT_TYPE}\"}" +exit 0 diff --git a/outputs.tf b/outputs.tf index d580b14..06518fc 100644 --- a/outputs.tf +++ b/outputs.tf @@ -44,3 +44,8 @@ output "access_key" { value = ibm_resource_key.scc_wp_resource_key.credentials["Sysdig Access Key"] sensitive = true } + +output "account_type" { + description = "The determined type of the IBM Cloud account." + value = module.account_type_check.account_type +} diff --git a/solutions/fully-configurable/main.tf b/solutions/fully-configurable/main.tf index a931eb1..cf8b7cb 100644 --- a/solutions/fully-configurable/main.tf +++ b/solutions/fully-configurable/main.tf @@ -40,4 +40,5 @@ module "scc_wp" { cspm_enabled = var.cspm_enabled app_config_crn = var.app_config_crn scc_workload_protection_trusted_profile_name = local.scc_workload_protection_trusted_profile_name + ibmcloud_api_key = var.ibmcloud_api_key } diff --git a/tests/pr_test.go b/tests/pr_test.go index 2ef7cba..1796d65 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -103,6 +103,8 @@ func TestFullyConfigurable(t *testing.T) { Prefix: "wp-da", TarIncludePatterns: []string{ "*.tf", + "modules/*/*.tf", + "modules/*/*.sh", fullyConfigurableDADir + "/*.tf", }, ResourceGroup: resourceGroup, @@ -192,6 +194,8 @@ func TestFullyConfigurableUpgrade(t *testing.T) { Prefix: "wp-da", TarIncludePatterns: []string{ "*.tf", + "modules/*/*.tf", + "modules/*/*.sh", fullyConfigurableDADir + "/*.tf", }, ResourceGroup: resourceGroup, diff --git a/variables.tf b/variables.tf index 839ff92..565d602 100644 --- a/variables.tf +++ b/variables.tf @@ -3,6 +3,12 @@ # Input Variables ############################################################################## +variable "ibmcloud_api_key" { + description = "The IBM Cloud platform API key needed to deploy IAM enabled resources." + type = string + sensitive = true +} + variable "region" { description = "IBM Cloud region where all resources will be deployed" type = string