diff --git a/.secrets.baseline b/.secrets.baseline index ccf9bcfc..822da937 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2023-07-20T09:57:54Z", + "generated_at": "2023-07-20T10:57:54Z", "plugins_used": [ { "name": "AWSKeyDetector" diff --git a/README.md b/README.md index e28fe750..9d12f0c9 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ You need the following permissions to run this module. ## Examples -- [ End to end example with default values](examples/default) +- [ End to end basic example](examples/basic) - [ Financial Services Cloud profile example](examples/fscloud) diff --git a/cra-config.yaml b/cra-config.yaml index 06cab5ac..c929dc5f 100644 --- a/cra-config.yaml +++ b/cra-config.yaml @@ -1,6 +1,9 @@ # More info about this file at https://github.com/terraform-ibm-modules/common-pipeline-assets/blob/main/.github/workflows/terraform-test-pipeline.md#cra-config-yaml version: "v1" CRA_TARGETS: - - CRA_TARGET: "examples/default" # Target directory for CRA scan. If not provided, the CRA Scan will not be run. + - CRA_TARGET: "examples/fscloud" # Target directory for CRA scan. If not provided, the CRA Scan will not be run. CRA_IGNORE_RULES_FILE: "cra-tf-validate-ignore-rules.json" # CRA Ignore file to use. If not provided, it checks the repo root directory for `cra-tf-validate-ignore-rules.json` - PROFILE_ID: "262b5a6d-9dea-400e-b61f-0fbd63883f78" # SCC profile ID (currently set to the FSCloud 1.3.0 profile). + PROFILE_ID: "0e6e7b5a-817d-4344-ab6f-e5d7a9c49520" # SCC profile ID (currently set to the FSCloud 1.4.0 profile). + CRA_ENVIRONMENT_VARIABLES: # An optional map of environment variables for CRA, where the key is the variable name and value is the value. Useful for providing TF_VARs. + TF_VAR_boot_volume_encryption_key: "crn:v1:bluemix:public:hs-crypto:us-south:a/abac0df06b644a9cabc6e44f55b3880e:e6dce284-e80f-46e1-a3c1-830f7adff7a9:key:76170fae-4e0c-48c3-8ebe-326059ebb533" + TF_VAR_existing_kms_instance_guid: "e6dce284-e80f-46e1-a3c1-830f7adff7a9" diff --git a/examples/basic/README.md b/examples/basic/README.md new file mode 100644 index 00000000..c94209b4 --- /dev/null +++ b/examples/basic/README.md @@ -0,0 +1,8 @@ +# End to end basic example + +An end-to-end basic example that will provision the following: + +- A new resource group if one is not passed in. +- A new public SSH key if one is not passed in. +- A new VPC with 3 subnets +- A VSI in each subnet diff --git a/examples/default/main.tf b/examples/basic/main.tf similarity index 99% rename from examples/default/main.tf rename to examples/basic/main.tf index 4c34ecdb..b68387b6 100644 --- a/examples/default/main.tf +++ b/examples/basic/main.tf @@ -26,6 +26,7 @@ data "ibm_resource_group" "existing_resource_group" { ############################################################################## # Create new SSH key ############################################################################## + resource "tls_private_key" "tls_key" { count = var.ssh_key != null ? 0 : 1 algorithm = "RSA" diff --git a/examples/default/outputs.tf b/examples/basic/outputs.tf similarity index 100% rename from examples/default/outputs.tf rename to examples/basic/outputs.tf diff --git a/examples/default/provider.tf b/examples/basic/provider.tf similarity index 100% rename from examples/default/provider.tf rename to examples/basic/provider.tf diff --git a/examples/default/variables.tf b/examples/basic/variables.tf similarity index 100% rename from examples/default/variables.tf rename to examples/basic/variables.tf diff --git a/examples/default/version.tf b/examples/basic/version.tf similarity index 100% rename from examples/default/version.tf rename to examples/basic/version.tf diff --git a/examples/default/README.md b/examples/default/README.md deleted file mode 100644 index 306cf984..00000000 --- a/examples/default/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# End to end example with default values - -An end to end example using the module's default variable values. diff --git a/examples/fscloud/README.md b/examples/fscloud/README.md index 7e6808da..4308d14d 100644 --- a/examples/fscloud/README.md +++ b/examples/fscloud/README.md @@ -7,6 +7,7 @@ The example uses the IBM Cloud Terraform provider to create the following infras * An SSH Key, if one is not passed in. * A Secure Landing Zone virtual private cloud (VPC). * An IBM Cloud VSI instance with Hyper Protect Crypto Services root key that is passed in for encrypting block storage. +* Additional data volumes on each VSI :exclamation: **Important:** In this example, only the VSI instance complies with the IBM Cloud Framework for Financial Services. Other parts of the infrastructure do not necessarily comply. diff --git a/examples/fscloud/main.tf b/examples/fscloud/main.tf index f8a32849..e8ea61c5 100644 --- a/examples/fscloud/main.tf +++ b/examples/fscloud/main.tf @@ -77,4 +77,11 @@ module "slz_vsi" { existing_kms_instance_guid = var.existing_kms_instance_guid vsi_per_subnet = var.vsi_per_subnet ssh_key_ids = [local.ssh_key_id] + access_tags = var.access_tags + # Add 1 additional data volume to each VSI + block_storage_volumes = [ + { + name = var.prefix + profile = "10iops-tier" + }] } diff --git a/examples/fscloud/variables.tf b/examples/fscloud/variables.tf index f175ec1f..68d4c71e 100644 --- a/examples/fscloud/variables.tf +++ b/examples/fscloud/variables.tf @@ -112,3 +112,16 @@ variable "existing_kms_instance_guid" { description = "The GUID of the Hyper Protect Crypto Services or Key Protect instance in which the key specified in var.kms_key_crn and var.backup_encryption_key_crn is coming from. Required only if var.kms_encryption_enabled is set to true, var.skip_iam_authorization_policy is set to false, and you pass a value for var.kms_key_crn, var.backup_encryption_key_crn, or both." type = string } + +variable "access_tags" { + type = list(string) + description = "A list of access tags to apply to the VSI resources created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." + default = [] + + validation { + condition = alltrue([ + for tag in var.access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\". For more information, see https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits." + } +} diff --git a/profiles/fscloud/README.md b/profiles/fscloud/README.md index c3a98eb3..3a1768ef 100644 --- a/profiles/fscloud/README.md +++ b/profiles/fscloud/README.md @@ -25,12 +25,13 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [access\_tags](#input\_access\_tags) | A list of access tags to apply to the VSI resources created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial. | `list(string)` | `[]` | no | | [allow\_ip\_spoofing](#input\_allow\_ip\_spoofing) | Allow IP spoofing on the primary network interface | `bool` | `false` | no | | [block\_storage\_volumes](#input\_block\_storage\_volumes) | List describing the block storage volumes that will be attached to each vsi |
list(| `[]` | no | | [boot\_volume\_encryption\_key](#input\_boot\_volume\_encryption\_key) | CRN of boot volume encryption key | `string` | n/a | yes | | [create\_security\_group](#input\_create\_security\_group) | Create security group for VSI. If this is passed as false, the default will be used | `bool` | n/a | yes | | [enable\_floating\_ip](#input\_enable\_floating\_ip) | Create a floating IP for each virtual server created | `bool` | `false` | no | -| [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 var.kms\_key\_crn and var.backup\_encryption\_key\_crn is coming from. Required only if var.kms\_encryption\_enabled is set to true, var.skip\_iam\_authorization\_policy is set to false, and you pass a value for var.kms\_key\_crn, var.backup\_encryption\_key\_crn, or both. | `string` | n/a | yes | +| [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 var.kms\_key\_crn and var.backup\_encryption\_key\_crn is coming from. Required only if var.skip\_iam\_authorization\_policy is set to false. | `string` | `null` | no | | [image\_id](#input\_image\_id) | Image ID used for VSI. Run 'ibmcloud is images' to find available images in a region | `string` | n/a | yes | | [load\_balancers](#input\_load\_balancers) | Load balancers to add to VSI |
object({
name = string
profile = string
capacity = optional(number)
iops = optional(number)
encryption_key = optional(string)
})
)
list(| `[]` | no | | [machine\_type](#input\_machine\_type) | VSI machine type. Run 'ibmcloud is instance-profiles' to get a list of regional profiles | `string` | n/a | yes | @@ -38,7 +39,7 @@ No resources. | [resource\_group\_id](#input\_resource\_group\_id) | ID of resource group to create VSI and block storage volumes. If you wish to create the block storage volumes in a different resource group, you can optionally set that directly in the 'block\_storage\_volumes' variable. | `string` | n/a | yes | | [security\_group](#input\_security\_group) | Security group created for VSI |
object({
name = string
type = string
listener_port = number
listener_protocol = string
connection_limit = number
algorithm = string
protocol = string
health_delay = number
health_retries = number
health_timeout = number
health_type = string
pool_member_port = string
security_group = optional(
object({
name = string
rules = list(
object({
name = string
direction = string
source = string
tcp = optional(
object({
port_max = number
port_min = number
})
)
udp = optional(
object({
port_max = number
port_min = number
})
)
icmp = optional(
object({
type = number
code = number
})
)
})
)
})
)
})
)
object({| n/a | yes | | [security\_group\_ids](#input\_security\_group\_ids) | IDs of additional security groups to be added to VSI deployment primary interface. A VSI interface can have a maximum of 5 security groups. | `list(string)` | `[]` | no | -| [skip\_iam\_authorization\_policy](#input\_skip\_iam\_authorization\_policy) | Set to true to skip the creation of an IAM authorization policy that permits all Storage Blocks 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\_guid variable. In addition, no policy is created if var.kms\_encryption\_enabled is set to false. | `bool` | `false` | no | +| [skip\_iam\_authorization\_policy](#input\_skip\_iam\_authorization\_policy) | Set to true to skip the creation of an IAM authorization policy that permits all Storage Blocks 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\_guid variable. | `bool` | `false` | no | | [ssh\_key\_ids](#input\_ssh\_key\_ids) | ssh key ids to use in creating vsi | `list(string)` | n/a | yes | | [subnets](#input\_subnets) | A list of subnet IDs where VSI will be deployed |
name = string
rules = list(
object({
name = string
direction = string
source = string
tcp = optional(
object({
port_max = number
port_min = number
})
)
udp = optional(
object({
port_max = number
port_min = number
})
)
icmp = optional(
object({
type = number
code = number
})
)
})
)
})
list(| n/a | yes | | [tags](#input\_tags) | List of tags to apply to resources created by this module. | `list(string)` | `[]` | no | diff --git a/profiles/fscloud/main.tf b/profiles/fscloud/main.tf index c4218fa5..a43868bf 100644 --- a/profiles/fscloud/main.tf +++ b/profiles/fscloud/main.tf @@ -21,4 +21,5 @@ module "fscloud_vsi" { security_group_ids = var.security_group_ids block_storage_volumes = var.block_storage_volumes load_balancers = var.load_balancers + access_tags = var.access_tags } diff --git a/profiles/fscloud/variables.tf b/profiles/fscloud/variables.tf index 9f497b9b..050309ca 100644 --- a/profiles/fscloud/variables.tf +++ b/profiles/fscloud/variables.tf @@ -299,14 +299,28 @@ variable "load_balancers" { } variable "existing_kms_instance_guid" { - description = "The GUID of the Hyper Protect Crypto Services or Key Protect instance in which the key specified in var.kms_key_crn and var.backup_encryption_key_crn is coming from. Required only if var.kms_encryption_enabled is set to true, var.skip_iam_authorization_policy is set to false, and you pass a value for var.kms_key_crn, var.backup_encryption_key_crn, or both." + description = "The GUID of the Hyper Protect Crypto Services or Key Protect instance in which the key specified in var.kms_key_crn and var.backup_encryption_key_crn is coming from. Required only if var.skip_iam_authorization_policy is set to false." type = string + default = null } variable "skip_iam_authorization_policy" { type = bool - description = "Set to true to skip the creation of an IAM authorization policy that permits all Storage Blocks 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_guid variable. In addition, no policy is created if var.kms_encryption_enabled is set to false." + description = "Set to true to skip the creation of an IAM authorization policy that permits all Storage Blocks 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_guid variable." default = false } +variable "access_tags" { + type = list(string) + description = "A list of access tags to apply to the VSI resources created by the module. For more information, see https://cloud.ibm.com/docs/account?topic=account-access-tags-tutorial." + default = [] + + validation { + condition = alltrue([ + for tag in var.access_tags : can(regex("[\\w\\-_\\.]+:[\\w\\-_\\.]+", tag)) && length(tag) <= 128 + ]) + error_message = "Tags must match the regular expression \"[\\w\\-_\\.]+:[\\w\\-_\\.]+\". For more information, see https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#limits." + } +} + ############################################################################## diff --git a/tests/other_test.go b/tests/other_test.go index dad41ace..93199816 100644 --- a/tests/other_test.go +++ b/tests/other_test.go @@ -9,7 +9,16 @@ import ( func TestRunBasicExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "slz-vsi") + options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ + Testing: t, + TerraformDir: fsCloudExampleTerraformDir, + Prefix: "slz-vsi-basic", + ResourceGroup: resourceGroup, + Region: region, + TerraformVars: map[string]interface{}{ + "access_tags": permanentResources["accessTags"], + }, + }) output, err := options.RunTestConsistency() assert.Nil(t, err, "This should not have errored") diff --git a/tests/pr_test.go b/tests/pr_test.go index 5db78e19..cfb24bfc 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -10,7 +10,7 @@ import ( "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" ) -const defaultExampleTerraformDir = "examples/default" +const basicExampleTerraformDir = "examples/basic" const fsCloudExampleTerraformDir = "examples/fscloud" const resourceGroup = "geretain-test-resources" @@ -33,25 +33,27 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } -func setupOptions(t *testing.T, prefix string) *testhelper.TestOptions { +func setupFSCloudOptions(t *testing.T, prefix string) *testhelper.TestOptions { options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ Testing: t, - TerraformDir: defaultExampleTerraformDir, + TerraformDir: fsCloudExampleTerraformDir, Prefix: prefix, ResourceGroup: resourceGroup, Region: region, TerraformVars: map[string]interface{}{ - "access_tags": permanentResources["accessTags"], + "existing_kms_instance_guid": permanentResources["hpcs_south"], + "boot_volume_encryption_key": permanentResources["hpcs_south_root_key_crn"], + "access_tags": permanentResources["accessTags"], }, }) return options } -func TestRunUpgradeBasicExample(t *testing.T) { +func TestRunUpgradeFSCloudExample(t *testing.T) { t.Parallel() - options := setupOptions(t, "slz-vsi-upg") + options := setupFSCloudOptions(t, "slz-vsi-upg") output, err := options.RunTestUpgrade() if !options.UpgradeTestSkipped { @@ -63,17 +65,7 @@ func TestRunUpgradeBasicExample(t *testing.T) { func TestRunFSCloudExample(t *testing.T) { t.Parallel() - options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{ - Testing: t, - TerraformDir: fsCloudExampleTerraformDir, - Prefix: "slz-fs-vsi", - ResourceGroup: resourceGroup, - Region: region, - TerraformVars: map[string]interface{}{ - "existing_kms_instance_guid": permanentResources["hpcs_south"], - "boot_volume_encryption_key": permanentResources["hpcs_south_root_key_crn"], - }, - }) + options := setupFSCloudOptions(t, "slz-vsi-fscloud") output, err := options.RunTestConsistency() assert.Nil(t, err, "This should not have errored")
object({
name = string
id = string
zone = string
cidr = string
})
)