At this point, API access to AutoCloud is configured, a test workspace has been bootstrapped, two Terraform modules have been linked with AutoCloud, and stub variable configurations have been defined. Next, the source module variables need to be examined, categorized, and defined in the blueprint.
Inspect Module Variables
AutoCloud Blueprints generate Terraform code invoking the modules, passing appropriate values to the module arguments defined by the module's variable definitions. The values for these arguments can be omitted to use the default values, statically defined, provided as references to another modules outputs, or collected as a part of the wizard form by defining a form field display element. In order to configured the module variables, it is necessary to review the variables defined for the component modules, and determine how best to provide values.
CloudPosse's modules make use of their label module to aid in name and tag convention enforcement. Both the KMS key module and S3 bucket module utilize this module as a common dependency. In the asset modules, variables are stored in two required files and one optional file. The context.tf file defines the input variables for the label module, and are common to both modules. The variables.tf file contains the variables that are specific to the particular module, and the optional file variables-deprecated.tf file contains previously supported variables that are depreciated and will be removed in future versions.
Global Variables
First, handle global variables common to both modules, which come from the label module. These can be viewed in the module source repository. For this exercise, we will only gather the enabled,namespace, environment, name, and tags variables. For all others, the defaults are satisfactory, and the variables can be excluded from the consumer form entirely.
Omit Variables to Use Default Values
Update the omit_variables element of the for the global blueprint config to hide the unneeded variables from the user:
Terraform
##### Create Blueprint Config## Combine resources into the final config
data "autocloud_blueprint_config""global"{source={
kms = data.autocloud_blueprint_config.kms_key_processor.blueprint_config,
s3 = data.autocloud_blueprint_config.s3_bucket_processor.blueprint_config
}#### Hide variables from user
omit_variables =[# Global# Use defaults in the module (don't collect)"context",
"tenant",
"stage",
"delimiter",
"attributes",
"labels_as_tags",
"additional_tag_map",
"label_order",
"regex_replace_chars",
"id_length_limit",
"label_key_case",
"label_value_case",
"descriptor_formats",
# Hard Coded values "enabled",
]}
ο»Ώ
If these values aren't defined, in the variable blocks that follow, they will be omitted from the module declaration that is generated entirely.
Hard Code Static Value that is Invisible to Consumer
It is sometimes preferable to specify a static value that is explicitly passed to the module, but not shown to the user. In this example, the enabled variable should always be set to true, explicitly enabling the asset creation. Blow the omit_variable definition, add a variable block to define that value:
Terraform
#### Hard code `enabled` to true to create all assets
variable {
name ="enabled"
value =true}
ο»Ώ
Hard Code Static Value that is Visible to Consumer
It is also sometimes preferable to specify a static value that is explicitly passed to the module, and shown to the user to inform them of the value that is set. In this example, the namespace variable should always be set to unstyl, explicitly defining the cost center that these assets belong to. Blow the enabled variable definition, add a variable block to define that value:
Terraform
#### Set the namespace
variable {
name ="namespace"
display_name ="Namespace"
helper_text ="The organization namespace the assets will be deployed in"type="shortText"
value ="unstyl"}
ο»Ώ
Note that for this value, the variable name namespace is not included in the omit_variables block, and has been given a display name and some helper text to improve the readability and context for the consumer.
Allow Consumer to Choose Between Set Values
In some circumstances, the value of a field is not static, but must be chosen from a collection of set values. For example, the unstyl cloud footprint has two environments, nonprod, and production. Allow the consumer to choose between these target environments. Add the environment variable block to the blueprint configuration:
Terraform
#### Choose the environment
variable {
name ="environment"
display_name ="Environment"
helper_text ="The environment the assets will be deployed in"type="radio"
options {
option {
label ="Nonprod"
value ="nonprod"
checked =true}
option {
label ="Production"
value ="production"}}}
ο»Ώ
Note that this variable has a radio type, which will create a radio button element in the form, and defaults to nonprod value with the checked = true definition.
Require Input from Consumer
Most Terraform blueprints will require input from the consumer deploying them, frequently textual information. In this encrypted S3 bucket example, the consumer will need to provide a name for the assets, which will be used along with the namespace and environment variables above to construct the S3 bucket name and the KMS key alias. Add the name variable declaration block below:
Terraform
#### Collect the name of the asset group
variable {
name ="name"
display_name ="Name"
helper_text ="The name of the encrypted S3 bucket"type="shortText"
validation_rule {
rule ="isRequired"
error_message ="You must provide a name for the encrypted S3 bucket"}}
ο»Ώ
In this block we've introduced the isRequired validation rule, which will force the consumer to provide a value before continuing with the deployment, displaying the given error message if they fail to do so.
Allow Consumer to Provide Optional Key-Value Pairs
A collection of key-value pairs from the user is another common use case. In this example, the consumer can optionally provide a collection of tags that will be applied to all the assets deployed. Add the tags variable to theglobal blueprint configuration:ο»Ώ
Terraform
#### Collect tags to apply to assets
variable {
name ="tags"
display_name ="Tags"
helper_text ="A map of tags to apply to the deployed assets"type="map"}
ο»Ώ
The map type will display the key/value collection element on the form.
Review
The global variable configuration is now complete. The completed global blueprint configuration should look like this:
Terraform
##### Create Blueprint Config## Combine resources into the final config
data "autocloud_blueprint_config""global"{source={
kms = data.autocloud_blueprint_config.kms_key_processor.blueprint_config,
s3 = data.autocloud_blueprint_config.s3_bucket_processor.blueprint_config
}#### Hide variables from user
omit_variables =[# Global# Use defaults in the module (don't collect)"context",
"tenant",
"stage",
"delimiter",
"attributes",
"labels_as_tags",
"additional_tag_map",
"label_order",
"regex_replace_chars",
"id_length_limit",
"label_key_case",
"label_value_case",
"descriptor_formats",
# Hard Coded values "enabled",
]#### Hard code `enabled` to true to create all assets
variable {
name ="enabled"
value =true}#### Set the namespace
variable {
name ="namespace"
display_name ="Namespace"
helper_text ="The organization namespace the assets will be deployed in"type="shortText"
value ="unstyl"}#### Choose the environment
variable {
name ="environment"
display_name ="Environment"
helper_text ="The environment the assets will be deployed in"type="radio"
options {
option {
label ="Nonprod"
value ="nonprod"
checked =true}
option {
label ="Production"
value ="production"}}}#### Collect the name of the asset group
variable {
name ="name"
display_name ="Name"
helper_text ="The name of the encrypted S3 bucket"type="shortText"
validation_rule {
rule ="isRequired"
error_message ="You must provide a name for the encrypted S3 bucket"}}#### Collect tags to apply to assets
variable {
name ="tags"
display_name ="Tags"
helper_text ="A map of tags to apply to the deployed assets"type="map"}}
ο»Ώ
Next, it's time to configure the variables for the component KMS key and S3 bucket modules.
KMS Key Variables
Next, configure the module-specific variables for the KMS key module. These variable definitions can be viewed in the module source repository. There are several configuration options, but for most, the defaults will be acceptable, and for the rest, static values will be used. Follow the same steps as for the global variables.
Omit Variables to Use Default Values
Update the omit_variables block of the kms_key_processor resource to omit the variables from display to the user:
Terraform
#### Hide variables from user
omit_variables =[# Global"context",
"tenant",
"stage",
"delimiter",
"attributes",
"labels_as_tags",
"additional_tag_map",
"label_order",
"regex_replace_chars",
"id_length_limit",
"label_key_case",
"label_value_case",
"descriptor_formats",
"enabled",
# Use defaults in the module (don't collect)"alias",
"customer_master_key_spec",
"key_usage",
"multi_region",
"policy",
# Hard Coded values"deletion_window_in_days",
"description",
"enable_key_rotation",
]
ο»Ώ
Hard Code Static Values that are Invisible to Consumer
For the KMS key, enforce a deletion window of 14 days. Additionally, set the description for the KMS key that will be displayed in the AWS console. Add the following variable blocks to the kms_key_processor blueprint config:
Terraform
#### Force KMS key deletion window to 14 days
variable {
name ="kms.variables.deletion_window_in_days"type="shortText"
value =14}#### Set description
variable {
name ="kms.variables.description"
value = format("KMS key for encryption of KMS encrypted S3 bucket")}
ο»Ώ
It is important to note the different syntax for the variable name definition. Where in the global blueprint just the variable name was used, providing the value to all modules that collect the given variable, in the KMS module, the name refers to a specific variable in a specific source configuration, namely the kms blueprint config generated from the module. This label is set in the source block of the blueprint config.
Review
The KMS key variable configuration is now complete. The completed kms_key_processor blueprint configuration should look like this:
Terraform
data "autocloud_blueprint_config""kms_key_processor"{source={
kms = autocloud_module.kms_key.blueprint_config
}#### Hide variables from user
omit_variables =[# Global"context",
"tenant",
"stage",
"delimiter",
"attributes",
"labels_as_tags",
"additional_tag_map",
"label_order",
"regex_replace_chars",
"id_length_limit",
"label_key_case",
"label_value_case",
"descriptor_formats",
"enabled",
# Use defaults in the module (don't collect)"alias",
"customer_master_key_spec",
"key_usage",
"multi_region",
"policy",
# Hard Coded values"deletion_window_in_days",
"description",
"enable_key_rotation",
]#### Force KMS key deletion window to 14 days
variable {
name ="kms.variables.deletion_window_in_days"type="shortText"
value =14}#### Set description
variable {
name ="kms.variables.description"
value = format("KMS key for encryption of KMS encrypted S3 bucket")}}
ο»Ώ
Continue on to configure the S3 bucket module variables.
S3 Bucket Variables
Repeat the process for the S3 bucket module variables. These variable definitions can be viewed in the module source repository. As with the KMS key module, most of the variable default values are acceptable, and the rest will not be collected or shown to the consumer.
Omit Variables to Use Default Values
Update the omit_variables block of the s3_bucket_processor resource to omit the variables from display to the user:
Hard Code Static Values that are Invisible to Consumer
For this KMS encrypted S3 bucket blueprint, we wish to enforce encryption at rest and in transit, enforce object ownership permissions, and block all public access. The public access block settings are configured by default, but the other variables will need to be statically set to achieve the desired configuration. Add the following variable resource blocks to the s3_bucket_processor configuration:
Terraform
#### Force encrypted uploads
variable {
name ="s3.variables.allow_encrypted_uploads_only"
value =true}#### Force encrypted downloads
variable {
name ="s3.variables.allow_ssl_requests_only"
value =true}#### Force BucketOwner object permissions
variable {
name ="s3.variables.s3_object_ownership"
value ="BucketOwnerEnforced"}#### Use KMS key encryption
variable {
name ="s3.variables.sse_algorithm"
value ="aws:kms"}
ο»Ώ
Connect KMS Module Dependency
The key motivation for this blueprint is to deploy the encrypted S3 bucket and the KMS key used to encrypt it as one asset package. To do this, the S3 bucket module must be configured to use the KMS key created in the blueprint. The KMS key ARN should be provided to the S3 bucket module from the outputs of the KMS key module. To support this use case, the autocloud_module resource has an outputs attribute that will create this reference in the generated Terraform code. Add the following variable block to the s3_bucket_processor blueprint config:
Terraform
#### Set KMS Key ARN
variable {
name ="s3.variables.kms_master_key_arn"
value = autocloud_module.kms_key.outputs["key_arn"]}
ο»Ώ
The module dependency will now be generated as expected.
Review
The S3 bucket module variable configuration is now complete. The s3_bucket_processor resource should look like this:
Terraform
data "autocloud_blueprint_config""s3_bucket_processor"{source={
s3 = autocloud_module.s3_bucket.blueprint_config
}#### Hide variables from user
omit_variables =[# Global"context",
"tenant",
"stage",
"delimiter",
"attributes",
"labels_as_tags",
"additional_tag_map",
"label_order",
"regex_replace_chars",
"id_length_limit",
"label_key_case",
"label_value_case",
"descriptor_formats",
"enabled",
# Use defaults in the module (don't collect)"access_key_enabled",
"acl",
"allowed_bucket_actions",
"block_public_acls",
"block_public_policy",
"bucket_key_enabled",
"bucket_name",
"cors_configuration",
"force_destroy",
"grants",
"ignore_public_acls",
"lifecycle_configuration_rules",
"lifecycle_rule_ids",
"lifecycle_rules",
"logging",
"object_lock_configuration",
"policy",
"privileged_principal_actions",
"privileged_principal_arns",
"replication_rules",
"restrict_public_buckets",
"s3_replica_bucket_arn",
"s3_replication_enabled",
"s3_replication_permissions_boundary_arn",
"s3_replication_rules",
"s3_replication_source_roles",
"source_policy_documents",
"ssm_base_path",
"store_access_key_in_ssm",
"transfer_acceleration_enabled",
"user_enabled",
"user_permissions_boundary_arn",
"versioning_enabled",
"website_configuration",
"website_redirect_all_requests_to",
# Hard Coded values"allow_encrypted_uploads_only",
"allow_ssl_requests_only",
"kms_master_key_arn",
"s3_object_ownership",
"sse_algorithm",
]#### Force encrypted uploads
variable {
name ="s3.variables.allow_encrypted_uploads_only"
value =true}#### Force encrypted downloads
variable {
name ="s3.variables.allow_ssl_requests_only"
value =true}#### Force BucketOwner object permissions
variable {
name ="s3.variables.s3_object_ownership"
value ="BucketOwnerEnforced"}#### Use KMS key encryption
variable {
name ="s3.variables.sse_algorithm"
value ="aws:kms"}#### Set KMS Key ARN
variable {
name ="s3.variables.kms_master_key_arn"
value = autocloud_module.kms_key.outputs["key_arn"]}}
ο»Ώ
Hide Static Module Variables from Consumer
The final step in the variable configuration is to update the global blueprint config to hide the static values that the consumer does not need to be shown. Update the omit_variables block of the resource to include the variables from the KMS key and S3 bucket modules:
Terraform
#### Hide variables from user
omit_variables =[# Global# Use defaults in the module (don't collect)"context",
"tenant",
"stage",
"delimiter",
"attributes",
"labels_as_tags",
"additional_tag_map",
"label_order",
"regex_replace_chars",
"id_length_limit",
"label_key_case",
"label_value_case",
"descriptor_formats",
# Hard Coded values"enabled",
# KMS Key# Use defaults in the module (don't collect)"alias",
"customer_master_key_spec",
"key_usage",
"multi_region",
"policy",
# Hard Coded values"deletion_window_in_days",
"description",
"enable_key_rotation",
# S3 Bucket# Use defaults in the module (don't collect)"access_key_enabled",
"acl",
"allowed_bucket_actions",
"block_public_acls",
"block_public_policy",
"bucket_key_enabled",
"bucket_name",
"cors_configuration",
"force_destroy",
"grants",
"ignore_public_acls",
"lifecycle_configuration_rules",
"lifecycle_rule_ids",
"lifecycle_rules",
"logging",
"object_lock_configuration",
"policy",
"privileged_principal_actions",
"privileged_principal_arns",
"replication_rules",
"restrict_public_buckets",
"s3_replica_bucket_arn",
"s3_replication_enabled",
"s3_replication_rules",
"s3_replication_source_roles",
"source_policy_documents",
"ssm_base_path",
"store_access_key_in_ssm",
"transfer_acceleration_enabled",
"user_enabled",
"versioning_enabled",
"website_configuration",
"website_redirect_all_requests_to",
# Hard Coded values"allow_encrypted_uploads_only",
"allow_ssl_requests_only",
"kms_master_key_arn",
"s3_object_ownership",
"sse_algorithm",
]