From c6f8eb5e038b17f7fe7d0ae2df2b1303af64f6bd Mon Sep 17 00:00:00 2001 From: David Redmin Date: Tue, 19 Nov 2024 15:10:32 -0500 Subject: [PATCH 1/3] Specify all variables as non-nullable This means that we need not worry about whether variables are explicitly specified as null. Since this is not something we were expecting, it makes sense to avoid the situation. See also: https://developer.hashicorp.com/terraform/language/values/variables#disallowing-null-input-values Co-authored-by: Jeremy Frasier --- terraform/variables.tf | 54 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/terraform/variables.tf b/terraform/variables.tf index 90a25a3f..f7e1cab8 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -6,61 +6,73 @@ variable "bod_lambda_function_bucket" { description = "The name of the S3 bucket where the Lambda function zip files reside. Terraform cannot access buckets that are not in the provider's region, so the region name will be appended to the bucket name to obtain the actual bucket where the zips are stored. So if we are working in region `us-west-1` and this variable has the value `buckethead`, then the zips will be looked for in the bucket `buckethead-us-west-1`." + nullable = false type = string } variable "dmarc_import_es_role_arn" { description = "The ARN of the role that must be assumed in order to read the dmarc-import Elasticsearch database." + nullable = false type = string } variable "findings_data_field_map" { description = "The key for the file storing field name mappings in JSON format." + nullable = false type = string } variable "findings_data_import_lambda_s3_key" { description = "The key (name) of the zip file for the findings data import Lambda function inside the S3 bucket." + nullable = false type = string } variable "findings_data_input_suffix" { description = "The suffix used by files found in the findings_data_s3_bucket that contain findings data." + nullable = false type = string } variable "lambda_artifacts_bucket" { description = "The name of the S3 bucket that stores AWS Lambda deployment artifacts. This bucket should be created with the cisagov/cyhy-lambda-bucket-terraform project. Note that in production terraform workspaces, the string '-production' will be appended to the bucket name. In non-production workspaces, '-' will be appended to the bucket name." + nullable = false type = string } variable "mgmt_nessus_activation_codes" { description = "A list of strings containing Nessus activation codes used in the management VPC." + nullable = false type = list(string) } variable "nessus_activation_codes" { description = "A list of strings containing Nessus activation codes." + nullable = false type = list(string) } variable "nessus_instance_count" { description = "The number of Nessus instances to create." + nullable = false type = number } variable "nmap_instance_count" { description = "The number of Nmap instances to create." + nullable = false type = number } variable "remote_ssh_user" { description = "The username to use when sshing to the EC2 instances." + nullable = false type = string } variable "ses_role_arn" { description = "The ARN of the role that must be assumed in order to send emails." + nullable = false type = string } @@ -81,30 +93,35 @@ variable "ami_prefixes" { reporter = "cyhy", } description = "An object whose keys are the types of Packer images (defined in the `packer/` directory in the root of the repository) and whose values are the prefix to use for the corresponding AMI. The default for all images is \"cyhy\"." + nullable = false type = object({ bastion = string, dashboard = string, docker = string, mongo = string, nessus = string, nmap = string, reporter = string }) } variable "aws_availability_zone" { default = "a" description = "The AWS availability zone to deploy into (e.g. a, b, c, etc.)." + nullable = false type = string } variable "aws_region" { default = "us-east-1" description = "The AWS region to deploy into (e.g. us-east-1)." + nullable = false type = string } variable "bod_lambda_functions" { default = {} description = "A map of information for each BOD 18-01 Lambda. The keys are the scan types and the values are objects that contain the Lambda's name and the key (name) for the corresponding deployment package in the BOD Lambda S3 bucket. Example: `{ pshtt = { lambda_file = \"pshtt.zip\", lambda_name = \"task_pshtt\" }}`" + nullable = false type = map(object({ lambda_file = string, lambda_name = string })) } variable "bod_nat_gateway_eip" { default = "" description = "The IP corresponding to the EIP to be used for the BOD 18-01 NAT gateway in production. In a non-production workspace an EIP will be created." + nullable = false type = string } @@ -113,6 +130,7 @@ variable "cloudwatch_alarm_emails" { "cisa-cool-group+cyhy@gwe.cisa.dhs.gov", ] description = "A list of the emails to which alerts should be sent if any CloudWatch Alarm is triggered." + nullable = false type = list(string) } @@ -123,42 +141,49 @@ variable "commander_config" { next_scan_limit = 8192 } description = "Configuration options for the CyHy commander's configuration file." + nullable = false type = object({ jobs_per_nessus_host = number, jobs_per_nmap_host = number, next_scan_limit = number }) } variable "create_bod_flow_logs" { default = false description = "Whether or not to create flow logs for the BOD 18-01 VPC." + nullable = false type = bool } variable "create_cyhy_flow_logs" { default = false description = "Whether or not to create flow logs for the CyHy VPC." + nullable = false type = bool } variable "create_mgmt_flow_logs" { default = false description = "Whether or not to create flow logs for the Management VPC." + nullable = false type = bool } variable "cyhy_archive_bucket_name" { default = "ncats-cyhy-archive" description = "S3 bucket for storing compressed archive files created by cyhy-archive." + nullable = false type = string } variable "cyhy_elastic_ip_cidr_block" { default = "" description = "The CIDR block of elastic addresses available for use by CyHy scanner instances." + nullable = false type = string } variable "cyhy_portscan_first_elastic_ip_offset" { default = 0 description = "The offset of the address (from the start of the elastic IP CIDR block) to be assigned to the *first* CyHy portscan instance. For example, if the CIDR block is 192.168.1.0/24 and the offset is set to 10, the first portscan address used will be 192.168.1.10. This is only used in production workspaces. Each additional portscan instance will get the next consecutive address in the block. NOTE: This will only work as intended when a contiguous CIDR block of EIP addresses is available." + nullable = false type = number } @@ -170,24 +195,28 @@ variable "cyhy_user_info" { uid = 2048 } description = "User information for the CyHy user created in our AMIs. Please see `packer/ansible/vars/cyhy_user.yml` for the configuration used when AMIs are built." + nullable = false type = object({ gid = number, home = string, name = string, uid = number }) } variable "cyhy_vulnscan_first_elastic_ip_offset" { default = 1 description = "The offset of the address (from the start of the elastic IP CIDR block) to be assigned to the *first* CyHy vulnscan instance. For example, if the CIDR block is 192.168.1.0/24 and the offset is set to 10, the first vulnscan address used will be 192.168.1.10. This is only used in production workspaces. Each additional vulnscan instance will get the next consecutive address in the block. NOTE: This will only work as intended when a contiguous CIDR block of EIP addresses is available." + nullable = false type = number } variable "dmarc_import_aws_region" { default = "us-east-1" description = "The AWS region where the dmarc-import Elasticsearch database resides." + nullable = false type = string } variable "docker_mailer_override_filename" { default = "docker-compose.bod.yml" description = "This file is used to add/override any Docker composition settings for cyhy-mailer for the docker EC2 instance. It must already exist in /var/cyhy/cyhy-mailer." + nullable = false type = string } @@ -203,24 +232,28 @@ variable "docker_mailer_override_filename" { variable "enable_mgmt_vpc" { default = false description = "Whether or not to enable unfettered access from the vulnerability scanner in the Management VPC to other VPCs (CyHy, BOD). This should only be enabled while running security scans from the Management VPC." + nullable = false type = bool } variable "findings_data_import_db_hostname" { default = "" description = "The hostname that has the database to store the findings data in." + nullable = false type = string } variable "findings_data_import_db_port" { default = "" description = "The port that the database server is listening on." + nullable = false type = string } variable "findings_data_import_lambda_failure_emails" { default = [] description = "A list of the emails to which alerts should be sent if findings data processing fails." + nullable = false type = list(string) } @@ -228,60 +261,70 @@ variable "findings_data_import_lambda_failure_emails" { variable "findings_data_import_lambda_failure_prefix" { default = "failed/" description = "The object prefix that findings JSONs that have failed to process successfully will have in the findings data bucket." + nullable = false type = string } variable "findings_data_import_lambda_failure_suffix" { default = ".json" description = "The object suffix that findings JSONs that have failed to process successfully will have in the findings data bucket." + nullable = false type = string } variable "findings_data_import_lambda_description" { default = "Lambda function for importing findings data." description = "The description to associate with the findings-data-import Lambda function." + nullable = false type = string } variable "findings_data_import_lambda_handler" { default = "lambda_handler.handler" description = "The entrypoint for the findings-data-import Lambda." + nullable = false type = string } variable "findings_data_import_ssm_db_name" { default = "" description = "The name of the parameter in AWS SSM that holds the name of the database to store the findings data in." + nullable = false type = string } variable "findings_data_import_ssm_db_password" { default = "" description = "The name of the parameter in AWS SSM that holds the database password for the user with write permission to the findings database." + nullable = false type = string } variable "findings_data_import_ssm_db_user" { default = "" description = "The name of the parameter in AWS SSM that holds the database username with write permission to the findings database." + nullable = false type = string } variable "findings_data_s3_bucket" { default = "" description = "The name of the bucket where the findings data JSON file can be found. Note that in production Terraform workspaces, the string '-production' will be appended to the bucket name. In non-production workspaces, '-' will be appended to the bucket name." + nullable = false type = string } variable "findings_data_save_failed" { default = true description = "Whether or not to save files for imports that have failed." + nullable = false type = bool } variable "findings_data_save_succeeded" { default = false description = "Whether or not to save files for imports that have succeeded." + nullable = false type = bool } @@ -291,12 +334,14 @@ variable "kevsync_failure_emails" { "vulnerability@cisa.dhs.gov", ] description = "A list of the emails to which alerts should be sent if KEV synchronization fails." + nullable = false type = list(string) } variable "mgmt_nessus_instance_count" { default = 1 description = "The number of Nessus instances to create if a management environment is set to be created." + nullable = false type = number } @@ -307,42 +352,49 @@ variable "mongo_disks" { log = "/dev/xvdd" } description = "The data volumes for the mongo instance(s)." + nullable = false type = map(string) } variable "mongo_instance_count" { default = 1 description = "The number of Mongo instances to create." + nullable = false type = number } variable "nessus_cyhy_runner_disk" { default = "/dev/xvdb" description = "The cyhy-runner data volume for the Nessus instance(s)." + nullable = false type = string } variable "nmap_cyhy_runner_disk" { default = "/dev/nvme1n1" description = "The cyhy-runner data volume for the Nmap instance(s)." + nullable = false type = string } variable "reporter_mailer_override_filename" { default = "docker-compose.cyhy.yml" description = "This file is used to add/override any Docker composition settings for cyhy-mailer for the reporter EC2 instance. It must already exist in /var/cyhy/cyhy-mailer." + nullable = false type = string } variable "ses_aws_region" { default = "us-east-1" description = "The AWS region where SES is configured." + nullable = false type = string } variable "tags" { default = {} description = "Tags to apply to all AWS resources created." + nullable = false type = map(string) } @@ -351,11 +403,13 @@ variable "tags" { variable "trusted_ingress_networks_ipv4" { default = ["0.0.0.0/0"] description = "IPv4 CIDR blocks from which to allow ingress to the bastion server." + nullable = false type = list(string) } variable "trusted_ingress_networks_ipv6" { default = ["::/0"] description = "IPv6 CIDR blocks from which to allow ingress to the bastion server." + nullable = false type = list(string) } From 42dcc85d47af7d5d2adb2d3c62af2a34d32f382e Mon Sep 17 00:00:00 2001 From: David Redmin Date: Tue, 19 Nov 2024 15:13:11 -0500 Subject: [PATCH 2/3] Bump the required version of Terraform up to 1.1 Version 1.1 of Terraform is the first version to support the nullable key in variable definitions. Co-authored-by: Jeremy Frasier --- terraform/versions.tf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/terraform/versions.tf b/terraform/versions.tf index c8d9e58a..0078f39b 100644 --- a/terraform/versions.tf +++ b/terraform/versions.tf @@ -1,7 +1,8 @@ terraform { - # We want to hold off on 1.1 or higher until we have tested it. - required_version = "~> 1.0" + # Version 1.1 of Terraform is the first version to support the + # nullable key in variable definitions. + required_version = "~> 1.1" # If you use any other providers you should also pin them to the # major version currently being used. This practice will help us From 94a2bfc75ef5b416a3664c3bc11254f7f2490e85 Mon Sep 17 00:00:00 2001 From: David Redmin Date: Tue, 19 Nov 2024 15:14:01 -0500 Subject: [PATCH 3/3] Update terraform-docs content in README.md --- terraform/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform/README.md b/terraform/README.md index c651f898..22e3241d 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -146,7 +146,7 @@ terraform apply -var-file=.tfvars | Name | Version | |------|---------| -| terraform | ~> 1.0 | +| terraform | ~> 1.1 | | aws | ~> 4.9 | | cloudinit | ~> 2.0 |