From d7a4ab6c467fb470c832b07960f7843d9d41474d Mon Sep 17 00:00:00 2001 From: nitrocode Date: Tue, 6 Jul 2021 14:37:22 -0400 Subject: [PATCH] Upstream zscaler component (#336) --- modules/account-map/README.md | 11 -- modules/github-runners/variables.tf | 2 +- modules/zscaler/README.md | 114 ++++++++++++ modules/zscaler/context.tf | 202 +++++++++++++++++++++ modules/zscaler/default.auto.tfvars | 6 + modules/zscaler/main.tf | 75 ++++++++ modules/zscaler/outputs.tf | 9 + modules/zscaler/providers.tf | 20 ++ modules/zscaler/templates/userdata.sh.tmpl | 17 ++ modules/zscaler/variables.tf | 68 +++++++ modules/zscaler/versions.tf | 26 +++ 11 files changed, 538 insertions(+), 12 deletions(-) create mode 100644 modules/zscaler/README.md create mode 100644 modules/zscaler/context.tf create mode 100644 modules/zscaler/default.auto.tfvars create mode 100644 modules/zscaler/main.tf create mode 100644 modules/zscaler/outputs.tf create mode 100644 modules/zscaler/providers.tf create mode 100644 modules/zscaler/templates/userdata.sh.tmpl create mode 100644 modules/zscaler/variables.tf create mode 100644 modules/zscaler/versions.tf diff --git a/modules/account-map/README.md b/modules/account-map/README.md index 4bb2846e9..aaeadfaaf 100644 --- a/modules/account-map/README.md +++ b/modules/account-map/README.md @@ -38,7 +38,6 @@ components: | Name | Version | |------|---------| | [aws](#provider\_aws) | ~> 3.32 | -| [terraform](#provider\_terraform) | n/a | ## Modules @@ -52,7 +51,6 @@ components: | Name | Type | |------|------| | [aws_organizations_organization.organization](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/organizations_organization) | data source | -| [terraform_remote_state.accounts](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source | ## Inputs @@ -81,15 +79,6 @@ components: | [root\_account\_stage\_name](#input\_root\_account\_stage\_name) | The stage name for the root account | `string` | `"root"` | no | | [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | -| [tfstate\_account\_id](#input\_tfstate\_account\_id) | The ID of the account where the Terraform remote state backend is provisioned | `string` | `""` | no | -| [tfstate\_assume\_role](#input\_tfstate\_assume\_role) | Set to false to use the caller's role to access the Terraform remote state | `bool` | `true` | no | -| [tfstate\_bucket\_environment\_name](#input\_tfstate\_bucket\_environment\_name) | The name of the environment for Terraform state bucket | `string` | `""` | no | -| [tfstate\_bucket\_stage\_name](#input\_tfstate\_bucket\_stage\_name) | The name of the stage for Terraform state bucket | `string` | `"root"` | no | -| [tfstate\_existing\_role\_arn](#input\_tfstate\_existing\_role\_arn) | The ARN of the existing IAM Role to access the Terraform remote state. If not provided and `remote_state_assume_role` is `true`, a role will be constructed from `remote_state_role_arn_template` | `string` | `""` | no | -| [tfstate\_role\_arn\_template](#input\_tfstate\_role\_arn\_template) | IAM Role ARN template for accessing the Terraform remote state | `string` | `"arn:aws:iam::%s:role/%s-%s-%s-%s"` | no | -| [tfstate\_role\_environment\_name](#input\_tfstate\_role\_environment\_name) | The name of the environment for Terraform state IAM role | `string` | `"gbl"` | no | -| [tfstate\_role\_name](#input\_tfstate\_role\_name) | IAM Role name for accessing the Terraform remote state | `string` | `"terraform"` | no | -| [tfstate\_role\_stage\_name](#input\_tfstate\_role\_stage\_name) | The name of the stage for Terraform state IAM role | `string` | `"root"` | no | ## Outputs diff --git a/modules/github-runners/variables.tf b/modules/github-runners/variables.tf index 8b57a2d2a..f72ae9df4 100644 --- a/modules/github-runners/variables.tf +++ b/modules/github-runners/variables.tf @@ -24,7 +24,7 @@ variable "instance_type" { default = "m5.large" } -variable mixed_instances_policy { +variable "mixed_instances_policy" { description = "Policy to use a mixed group of on-demand/spot of differing types. Launch template is automatically generated. https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html#mixed_instances_policy-1" type = object({ diff --git a/modules/zscaler/README.md b/modules/zscaler/README.md new file mode 100644 index 000000000..f0df84185 --- /dev/null +++ b/modules/zscaler/README.md @@ -0,0 +1,114 @@ +# Component: `zscaler` + +This component is responsible for provisioning ZScaler Private Access Connector instances on Amazon Linux 2 AMIs. + +Prior to provisioning this component, it is required that a SecureString SSM Parameter containing the ZScaler App Connector Provisioning Key is populated in each account corresponding to the regional stack the component is deployed to, with the name of the SSM Parameter matching the value of `var.zscaler_key`. + +This parameter should be populated using `chamber`, which is included in the geodesic image: + +``` +chamber write zscaler key +``` + +Where is the ZScaler App Connector Provisioning Key. For more information on how to generate this key, see: [ZScaler documentation on Configuring App Connectors](https://help.zscaler.com/zpa/configuring-connectors). + +## Usage + +**Stack Level**: Regional + +The typical stack configuration for this component is as follows: + +```yaml +components: + terraform: + zscaler: + vars: + zscaler_count: 2 +``` + +Preferably, regional stack configurations can be kept _DRY_ by importing `catalog/zscaler` via the `imports` list at the top of the configuration. + +``` +import: + ... + - catalog/zscaler +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13.0 | +| [aws](#requirement\_aws) | >= 3.0 | +| [null](#requirement\_null) | >= 3.0 | +| [random](#requirement\_random) | >= 3.0 | +| [template](#requirement\_template) | >= 2.2 | +| [utils](#requirement\_utils) | >= 0.4.3 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 3.0 | +| [template](#provider\_template) | >= 2.2 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [ec2\_zscaler](#module\_ec2\_zscaler) | cloudposse/ec2-instance/aws | 0.32.2 | +| [iam\_roles](#module\_iam\_roles) | ../account-map/modules/iam-roles | n/a | +| [this](#module\_this) | cloudposse/label/null | 0.24.1 | + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_role_policy_attachment.ssm_core](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_ami.amazon_linux_2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | +| [aws_ssm_parameter.zscaler_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [template_file.userdata](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | +| [ami\_owner](#input\_ami\_owner) | The owner of the AMI used for the ZScaler EC2 instances. | `string` | `"amazon"` | no | +| [ami\_regex](#input\_ami\_regex) | The regex used to match the latest AMI to be used for the ZScaler EC2 instances. | `string` | `"^amzn2-ami-hvm.*"` | no | +| [attributes](#input\_attributes) | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | +| [aws\_ssm\_enabled](#input\_aws\_ssm\_enabled) | Set true to install the AWS SSM agent on each EC2 instances. | `bool` | `true` | no | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | +| [delimiter](#input\_delimiter) | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [import\_role\_arn](#input\_import\_role\_arn) | IAM Role ARN to use when importing a resource | `string` | `null` | no | +| [instance\_type](#input\_instance\_type) | The instance family to use for the ZScaler EC2 instances. | `string` | `"r5n.medium"` | no | +| [label\_key\_case](#input\_label\_key\_case) | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | +| [name](#input\_name) | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | +| [namespace](#input\_namespace) | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [region](#input\_region) | AWS region | `string` | n/a | yes | +| [secrets\_store\_type](#input\_secrets\_store\_type) | Secret store type for Zscaler provisioning keys. Valid values: `SSM`, `ASM` (but `ASM` not currently supported) | `string` | `"SSM"` | no | +| [security\_group\_rules](#input\_security\_group\_rules) | A list of maps of Security Group rules.
The values of map is fully complated with `aws_security_group_rule` resource.
To get more info see [security\_group\_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule). | `list(any)` |
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"from_port": 0,
"protocol": "-1",
"to_port": 65535,
"type": "egress"
}
]
| no | +| [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | +| [zscaler\_count](#input\_zscaler\_count) | The number of Zscaler instances. | `number` | `1` | no | +| [zscaler\_key](#input\_zscaler\_key) | SSM key (without leading `/`) for the Zscaler provisioning key secret. | `string` | `"zscaler/key"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [instance\_id](#output\_instance\_id) | Instance ID | +| [private\_ip](#output\_private\_ip) | Private IP of the instance | + + +## References +* [cloudposse/terraform-aws-components](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/zscaler) - Cloud Posse's upstream component + +[](https://cpco.io/component) diff --git a/modules/zscaler/context.tf b/modules/zscaler/context.tf new file mode 100644 index 000000000..81f99b4e3 --- /dev/null +++ b/modules/zscaler/context.tf @@ -0,0 +1,202 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.24.1" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for default, which is `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + The letter case of output label values (also used in `tags` and `id`). + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/modules/zscaler/default.auto.tfvars b/modules/zscaler/default.auto.tfvars new file mode 100644 index 000000000..063bfdca6 --- /dev/null +++ b/modules/zscaler/default.auto.tfvars @@ -0,0 +1,6 @@ +enabled = false + +name = "zscaler" + +# Cheapest instance that satisfies DenyInstancesWithoutEncryptionInTransit SCP (see: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/data-protection.html#encryption-transit) +instance_type = "m5n.large" diff --git a/modules/zscaler/main.tf b/modules/zscaler/main.tf new file mode 100644 index 000000000..8fc6734c5 --- /dev/null +++ b/modules/zscaler/main.tf @@ -0,0 +1,75 @@ +locals { + enabled = module.this.enabled + vpc_id = module.vpc.outputs.vpc_id + # Make sure local.vpc_private_subnet_ids is sorted so the order does not change + vpc_private_subnet_ids = sort(module.vpc.outputs.private_subnet_ids) + ssm_enabled = local.enabled && var.aws_ssm_enabled + instances_role_arns = local.ssm_enabled ? toset(module.ec2_zscaler[*].role) : [] + eks_outputs = module.eks.outputs + eks_cluster_managed_security_group_id = local.eks_outputs.eks_cluster_managed_security_group_id + ami_owner = var.ami_owner + ami_name_regex = var.ami_regex +} + +data "aws_ami" "amazon_linux_2" { + count = local.enabled ? 1 : 0 + most_recent = true + owners = [local.ami_owner] + name_regex = local.ami_name_regex + + filter { + name = "architecture" + values = ["x86_64"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } +} + +data "aws_ssm_parameter" "zscaler_key" { + count = local.enabled && var.secrets_store_type == "SSM" ? 1 : 0 + name = format("/%s", var.zscaler_key) + with_decryption = true +} + +data "template_file" "userdata" { + count = local.enabled ? 1 : 0 + template = file("${path.module}/templates/userdata.sh.tmpl") + + vars = { + key = data.aws_ssm_parameter.zscaler_key[0].value + region = var.region + } +} + +module "ec2_zscaler" { + count = var.zscaler_count + + source = "cloudposse/ec2-instance/aws" + version = "0.32.2" + ami = local.enabled ? data.aws_ami.amazon_linux_2[0].id : "" + ssh_key_pair = null + ami_owner = local.ami_owner + vpc_id = local.vpc_id + # Make sure local.vpc_private_subnet_ids is sorted so the order does not change + subnet = local.vpc_private_subnet_ids[count.index % length(local.vpc_private_subnet_ids)] + create_default_security_group = false + security_groups = [local.eks_cluster_managed_security_group_id] + instance_type = var.instance_type + # Zscaler is not compatible with IMDSv2 + metadata_http_tokens_required = false + metadata_http_put_response_hop_limit = 3 + user_data_base64 = local.enabled ? base64encode(data.template_file.userdata[0].rendered) : "" + attributes = [count.index] + + context = module.this.context +} + +# Attach Amazon's managed policy for SSM managed instance +resource "aws_iam_role_policy_attachment" "ssm_core" { + for_each = local.enabled ? local.instances_role_arns : [] + role = each.key + policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" +} diff --git a/modules/zscaler/outputs.tf b/modules/zscaler/outputs.tf new file mode 100644 index 000000000..a6899d191 --- /dev/null +++ b/modules/zscaler/outputs.tf @@ -0,0 +1,9 @@ +output "instance_id" { + value = module.ec2_zscaler.*.id + description = "Instance ID" +} + +output "private_ip" { + value = module.ec2_zscaler.*.private_ip + description = "Private IP of the instance" +} diff --git a/modules/zscaler/providers.tf b/modules/zscaler/providers.tf new file mode 100644 index 000000000..fd46aae55 --- /dev/null +++ b/modules/zscaler/providers.tf @@ -0,0 +1,20 @@ +provider "aws" { + region = var.region + + assume_role { + # `terraform import` will not use data from a data source, + # so on import we have to explicitly specify the role + role_arn = coalesce(var.import_role_arn, module.iam_roles.terraform_role_arn) + } +} + +module "iam_roles" { + source = "../account-map/modules/iam-roles" + context = module.this.context +} + +variable "import_role_arn" { + type = string + default = null + description = "IAM Role ARN to use when importing a resource" +} diff --git a/modules/zscaler/templates/userdata.sh.tmpl b/modules/zscaler/templates/userdata.sh.tmpl new file mode 100644 index 000000000..63b286915 --- /dev/null +++ b/modules/zscaler/templates/userdata.sh.tmpl @@ -0,0 +1,17 @@ +#!/bin/bash +cat < /etc/yum.repos.d/zscaler.repo +[zscaler] +name=Zscaler Private Access Repository +baseurl=https://yum.private.zscaler.com/yum/el7 +enabled=1 +gpgcheck=1 +gpgkey=https://yum.private.zscaler.com/gpg +EOF +yum update -y +sudo yum install -y zpa-connector +echo "${key}" > /opt/zscaler/var/provision_key +systemctl enable zpa-connector +systemctl start zpa-connector +sleep 60 # https://help.zscaler.com/zpa/connector-deployment-guide-amazon-web-services +systemctl stop zpa-connector +systemctl start zpa-connector diff --git a/modules/zscaler/variables.tf b/modules/zscaler/variables.tf new file mode 100644 index 000000000..d3492dd92 --- /dev/null +++ b/modules/zscaler/variables.tf @@ -0,0 +1,68 @@ +variable "region" { + type = string + description = "AWS region" +} + +variable "ami_owner" { + type = string + description = "The owner of the AMI used for the ZScaler EC2 instances." + default = "amazon" +} + +variable "ami_regex" { + type = string + description = "The regex used to match the latest AMI to be used for the ZScaler EC2 instances." + default = "^amzn2-ami-hvm.*" +} + +variable "aws_ssm_enabled" { + type = bool + description = "Set true to install the AWS SSM agent on each EC2 instances." + default = true +} + +variable "instance_type" { + type = string + default = "r5n.medium" + description = "The instance family to use for the ZScaler EC2 instances." +} +variable "secrets_store_type" { + type = string + description = "Secret store type for Zscaler provisioning keys. Valid values: `SSM`, `ASM` (but `ASM` not currently supported)" + default = "SSM" + + validation { + condition = var.secrets_store_type == "SSM" + error_message = "Only SSM is currently supported as the Secrets Store type." + } +} + +variable "zscaler_key" { + type = string + description = "SSM key (without leading `/`) for the Zscaler provisioning key secret." + default = "zscaler/key" +} + +variable "zscaler_count" { + type = number + description = "The number of Zscaler instances." + default = 1 +} + +variable "security_group_rules" { + type = list(any) + default = [ + { + type = "egress" + from_port = 0 + to_port = 65535 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + ] + description = <<-EOT + A list of maps of Security Group rules. + The values of map is fully complated with `aws_security_group_rule` resource. + To get more info see [security_group_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule). + EOT +} diff --git a/modules/zscaler/versions.tf b/modules/zscaler/versions.tf new file mode 100644 index 000000000..007db2651 --- /dev/null +++ b/modules/zscaler/versions.tf @@ -0,0 +1,26 @@ +terraform { + required_version = ">= 0.13.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.0" + } + template = { + source = "hashicorp/template" + version = ">= 2.2" + } + null = { + source = "hashicorp/null" + version = ">= 3.0" + } + random = { + source = "hashicorp/random" + version = ">= 3.0" + } + utils = { + source = "cloudposse/utils" + version = ">= 0.4.3" + } + } +}