diff --git a/.github/workflows/run-ci-cd.yaml b/.github/workflows/run-ci-cd.yaml index ec9a9a5546..b5d0a8d5b6 100644 --- a/.github/workflows/run-ci-cd.yaml +++ b/.github/workflows/run-ci-cd.yaml @@ -479,6 +479,27 @@ jobs: test-file: rest_test.py rest-url: http://localhost:9500/api/v0 + run-infrastructure-tests: + name: Run Infrastructure tests + needs: + - run-security-scan + - scan-code + - scan-ci-dependencies + permissions: + contents: read + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + + - name: Install Terraform + uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd + with: + terraform_version: 1.14.0 + + - name: Run Infrastructure tests + run: make test-infrastructure + build-staging-images: name: Build Staging Images env: @@ -492,6 +513,7 @@ jobs: - run-frontend-a11y-tests - run-frontend-e2e-tests - run-frontend-unit-tests + - run-infrastructure-tests - set-release-version permissions: contents: read @@ -651,7 +673,6 @@ jobs: plan-staging-nest: name: Plan Nest Staging env: - FORCE_COLOR: 1 TF_INPUT: false TF_IN_AUTOMATION: true environment: staging @@ -700,10 +721,10 @@ jobs: CREATE_RDS_PROXY: false DOMAIN_NAME: ${{ vars.DOMAIN_NAME }} ECS_USE_FARGATE_SPOT: true - ENVIRONMENT: "staging" + ENVIRONMENT: 'staging' FRONTEND_USE_FARGATE_SPOT: true LAMBDA_FUNCTION_NAME: ${{ secrets.ZAPPA_LAMBDA_FUNCTION_NAME }} - PROJECT_NAME: "nest" + PROJECT_NAME: 'nest' run: | umask 377 cat > infrastructure/staging/terraform.tfvars <<-EOF @@ -750,7 +771,6 @@ jobs: deploy-staging-nest: name: Deploy Nest Staging env: - FORCE_COLOR: 1 TF_INPUT: false TF_IN_AUTOMATION: true environment: staging diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ca9565cd55..2a93cd34ef 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: rev: v1.104.0 hooks: - id: terraform_fmt - files: ^infrastructure/.*\.tf$ + files: ^infrastructure/.*\.(tf|tftest\.hcl)$ - id: terraform_tflint files: ^infrastructure/.*\.tf$ args: diff --git a/backend/zappa_callback.py b/backend/zappa_callback.py index 0b5e95fe87..5ac73b7447 100644 --- a/backend/zappa_callback.py +++ b/backend/zappa_callback.py @@ -31,7 +31,7 @@ def clean_package(zappa): temp_path = Path(temp_dir) new_archive_path = temp_path / "new.tar.gz" - # nosemgrep: trailofbits.python.tarfile-extractall-traversal.tarfile-extractall-traversal # noqa: ERA001, E501 + # NOSEMGREP: trailofbits.python.tarfile-extractall-traversal.tarfile-extractall-traversal # noqa: ERA001, E501 with tarfile.open(full_path, "r:gz") as tf: # NOSONAR archive is trusted tf.extractall(temp_path, filter="data") diff --git a/infrastructure/modules/alb/tests/alb.tftest.hcl b/infrastructure/modules/alb/tests/alb.tftest.hcl index 95cc15d3d5..050c6dddaa 100644 --- a/infrastructure/modules/alb/tests/alb.tftest.hcl +++ b/infrastructure/modules/alb/tests/alb.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { alb_sg_id = "sg-alb-12345" common_tags = { Environment = "test", Project = "nest" } @@ -55,10 +57,10 @@ run "test_lambda_alias_name" { command = plan override_data { - target = data.aws_lambda_function.backend[0] - values = { - version = "1" - } + target = data.aws_lambda_function.backend[0] + values = { + version = "1" + } } variables { lambda_function_name = "test-function" @@ -85,10 +87,10 @@ run "test_lambda_permission_action" { command = plan override_data { - target = data.aws_lambda_function.backend[0] - values = { - version = "1" - } + target = data.aws_lambda_function.backend[0] + values = { + version = "1" + } } variables { lambda_function_name = "test-function" @@ -103,10 +105,10 @@ run "test_lambda_permission_principal" { command = plan override_data { - target = data.aws_lambda_function.backend[0] - values = { - version = "1" - } + target = data.aws_lambda_function.backend[0] + values = { + version = "1" + } } variables { lambda_function_name = "test-function" @@ -327,10 +329,10 @@ run "test_lambda_target_group_name_format" { command = plan override_data { - target = data.aws_lambda_function.backend[0] - values = { - version = "1" - } + target = data.aws_lambda_function.backend[0] + values = { + version = "1" + } } variables { lambda_function_name = "test-function" @@ -345,10 +347,10 @@ run "test_lambda_target_group_type" { command = plan override_data { - target = data.aws_lambda_function.backend[0] - values = { - version = "1" - } + target = data.aws_lambda_function.backend[0] + values = { + version = "1" + } } variables { lambda_function_name = "test-function" diff --git a/infrastructure/modules/cache/tests/cache.tftest.hcl b/infrastructure/modules/cache/tests/cache.tftest.hcl index 3d6415a478..bdf2fc3fdb 100644 --- a/infrastructure/modules/cache/tests/cache.tftest.hcl +++ b/infrastructure/modules/cache/tests/cache.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { common_tags = { Environment = "test", Project = "nest" } environment = "test" diff --git a/infrastructure/modules/database/tests/database.tftest.hcl b/infrastructure/modules/database/tests/database.tftest.hcl index 8c184026ac..4bb0323174 100644 --- a/infrastructure/modules/database/tests/database.tftest.hcl +++ b/infrastructure/modules/database/tests/database.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { common_tags = { Environment = "test", Project = "nest" } create_rds_proxy = false @@ -8,7 +10,7 @@ variables { db_subnet_ids = ["subnet-12345678"] db_user = "nest_user" environment = "test" - kms_key_arn = "arn:aws:kms:us-east-2:123456789012:key/12345678-1234-1234-1234-123456789012" + kms_key_arn = "arn:aws:kms:us-east-2:123456789012:key/12345678-1234-1234-1234-123456789012" project_name = "nest" security_group_ids = ["sg-12345678"] } diff --git a/infrastructure/modules/ecs/main.tf b/infrastructure/modules/ecs/main.tf index 2e32045b4b..3dc9d06c69 100644 --- a/infrastructure/modules/ecs/main.tf +++ b/infrastructure/modules/ecs/main.tf @@ -107,7 +107,7 @@ resource "aws_iam_policy" "ecs_tasks_execution_policy" { Version = "2012-10-17" Statement = [ { - # nosemgrep: terraform.lang.security.iam.no-iam-creds-exposure.no-iam-creds-exposure + # NOSEMGREP: terraform.lang.security.iam.no-iam-creds-exposure.no-iam-creds-exposure Action = [ # https://docs.aws.amazon.com/AmazonECR/latest/public/public-repository-policies.html#repository-policy-vs-iam-policy "ecr:GetAuthorizationToken" diff --git a/infrastructure/modules/ecs/modules/task/tests/task.tftest.hcl b/infrastructure/modules/ecs/modules/task/tests/task.tftest.hcl index 785a7257cd..abe5ea3656 100644 --- a/infrastructure/modules/ecs/modules/task/tests/task.tftest.hcl +++ b/infrastructure/modules/ecs/modules/task/tests/task.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { aws_region = "us-east-2" command = ["/bin/sh", "-c", "echo test"] diff --git a/infrastructure/modules/ecs/tests/ecs.tftest.hcl b/infrastructure/modules/ecs/tests/ecs.tftest.hcl index dfef0d5c11..692fd49876 100644 --- a/infrastructure/modules/ecs/tests/ecs.tftest.hcl +++ b/infrastructure/modules/ecs/tests/ecs.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { aws_region = "us-east-2" common_tags = { Environment = "test", Project = "nest" } diff --git a/infrastructure/modules/frontend/main.tf b/infrastructure/modules/frontend/main.tf index c16f482ea0..929be802a8 100644 --- a/infrastructure/modules/frontend/main.tf +++ b/infrastructure/modules/frontend/main.tf @@ -21,7 +21,7 @@ resource "aws_cloudwatch_log_group" "frontend" { } # TODO: disallow tag mutability -# nosemgrep: terraform.aws.security.aws-ecr-mutable-image-tags.aws-ecr-mutable-image-tags +# NOSEMGREP: terraform.aws.security.aws-ecr-mutable-image-tags.aws-ecr-mutable-image-tags resource "aws_ecr_repository" "frontend" { image_tag_mutability = "MUTABLE" name = "${var.project_name}-${var.environment}-frontend" @@ -206,7 +206,7 @@ resource "aws_iam_policy" "ecs_task_execution_policy" { Statement = [ { # https://docs.aws.amazon.com/AmazonECR/latest/public/public-repository-policies.html#repository-policy-vs-iam-policy - # nosemgrep: terraform.lang.security.iam.no-iam-creds-exposure.no-iam-creds-exposure + # NOSEMGREP: terraform.lang.security.iam.no-iam-creds-exposure.no-iam-creds-exposure Action = "ecr:GetAuthorizationToken" Effect = "Allow" Resource = "*" # NOSONAR diff --git a/infrastructure/modules/frontend/tests/frontend.tftest.hcl b/infrastructure/modules/frontend/tests/frontend.tftest.hcl index 054fa955fc..fa04f9e0f7 100644 --- a/infrastructure/modules/frontend/tests/frontend.tftest.hcl +++ b/infrastructure/modules/frontend/tests/frontend.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { aws_region = "us-east-2" common_tags = { Environment = "test", Project = "nest" } diff --git a/infrastructure/modules/kms/tests/kms.tftest.hcl b/infrastructure/modules/kms/tests/kms.tftest.hcl index d9a184855f..01d4546b98 100644 --- a/infrastructure/modules/kms/tests/kms.tftest.hcl +++ b/infrastructure/modules/kms/tests/kms.tftest.hcl @@ -1,3 +1,12 @@ +mock_provider "aws" {} + +override_data { + target = data.aws_iam_policy_document.key_policy + values = { + json = "{\"Statement\":[{\"Sid\":\"EnableIAMUserPermissions\"},{\"Sid\":\"AllowCloudWatchLogs\"}]}" + } +} + variables { common_tags = { Environment = "test", Project = "nest" } environment = "test" diff --git a/infrastructure/modules/networking/main.tf b/infrastructure/modules/networking/main.tf index 8302239008..a220c52a26 100644 --- a/infrastructure/modules/networking/main.tf +++ b/infrastructure/modules/networking/main.tf @@ -18,7 +18,7 @@ resource "aws_vpc" "main" { }) } -# nosemgrep: terraform.aws.security.aws-subnet-has-public-ip-address.aws-subnet-has-public-ip-address +# NOSEMGREP: terraform.aws.security.aws-subnet-has-public-ip-address.aws-subnet-has-public-ip-address resource "aws_subnet" "public" { availability_zone = var.availability_zones[count.index] cidr_block = var.public_subnet_cidrs[count.index] diff --git a/infrastructure/modules/networking/modules/nacl/tests/nacl.tftest.hcl b/infrastructure/modules/networking/modules/nacl/tests/nacl.tftest.hcl index c350c5d893..cdbdef670b 100644 --- a/infrastructure/modules/networking/modules/nacl/tests/nacl.tftest.hcl +++ b/infrastructure/modules/networking/modules/nacl/tests/nacl.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { common_tags = { Environment = "test", Project = "nest" } environment = "test" diff --git a/infrastructure/modules/networking/modules/vpc-endpoint/tests/vpc-endpoint.tftest.hcl b/infrastructure/modules/networking/modules/vpc-endpoint/tests/vpc-endpoint.tftest.hcl index 3447f2abcb..1ceb87e68c 100644 --- a/infrastructure/modules/networking/modules/vpc-endpoint/tests/vpc-endpoint.tftest.hcl +++ b/infrastructure/modules/networking/modules/vpc-endpoint/tests/vpc-endpoint.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { aws_region = "us-east-1" common_tags = { Environment = "test", Project = "nest" } @@ -15,11 +17,11 @@ run "test_security_group_not_created_when_no_endpoint" { variables { create_cloudwatch_logs = false - create_ecr_api = false - create_ecr_dkr = false - create_s3 = false - create_secretsmanager = false - create_ssm = false + create_ecr_api = false + create_ecr_dkr = false + create_s3 = false + create_secretsmanager = false + create_ssm = false } assert { @@ -33,11 +35,11 @@ run "test_security_group_created_with_interface_endpoint" { variables { create_cloudwatch_logs = true - create_ecr_api = false - create_ecr_dkr = false - create_s3 = false - create_secretsmanager = false - create_ssm = false + create_ecr_api = false + create_ecr_dkr = false + create_s3 = false + create_secretsmanager = false + create_ssm = false } assert { condition = length(aws_security_group.vpc_endpoints) == 1 @@ -50,7 +52,7 @@ run "test_security_group_allows_https_from_vpc" { variables { create_cloudwatch_logs = true - create_s3 = false + create_s3 = false } assert { condition = aws_security_group_rule.vpc_endpoints_ingress_https[0].from_port == 443 @@ -71,7 +73,7 @@ run "test_security_group_name_format" { variables { create_cloudwatch_logs = true - create_s3 = false + create_s3 = false } assert { condition = aws_security_group.vpc_endpoints[0].tags["Name"] == "nest-test-vpc-endpoints-sg" diff --git a/infrastructure/modules/networking/tests/networking.tftest.hcl b/infrastructure/modules/networking/tests/networking.tftest.hcl index 53b853b908..ad9e6d19c2 100644 --- a/infrastructure/modules/networking/tests/networking.tftest.hcl +++ b/infrastructure/modules/networking/tests/networking.tftest.hcl @@ -1,20 +1,22 @@ +mock_provider "aws" {} + variables { - availability_zones = ["us-east-2a", "us-east-2b", "us-east-2c"] - aws_region = "us-east-2" - common_tags = { Environment = "test", Project = "nest" } - create_vpc_cloudwatch_logs_endpoint = false - create_vpc_ecr_api_endpoint = false - create_vpc_ecr_dkr_endpoint = false - create_vpc_s3_endpoint = false - create_vpc_secretsmanager_endpoint = false - create_vpc_ssm_endpoint = false - environment = "test" - kms_key_arn = "arn:aws:kms:us-east-2:123456789012:key/12345678-1234-1234-1234-123456789012" - log_retention_in_days = 90 - private_subnet_cidrs = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"] - project_name = "nest" - public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24", "10.0.6.0/24"] - vpc_cidr = "10.0.0.0/16" + availability_zones = ["us-east-2a", "us-east-2b", "us-east-2c"] + aws_region = "us-east-2" + common_tags = { Environment = "test", Project = "nest" } + create_vpc_cloudwatch_logs_endpoint = false + create_vpc_ecr_api_endpoint = false + create_vpc_ecr_dkr_endpoint = false + create_vpc_s3_endpoint = false + create_vpc_secretsmanager_endpoint = false + create_vpc_ssm_endpoint = false + environment = "test" + kms_key_arn = "arn:aws:kms:us-east-2:123456789012:key/12345678-1234-1234-1234-123456789012" + log_retention_in_days = 90 + private_subnet_cidrs = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"] + project_name = "nest" + public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24", "10.0.6.0/24"] + vpc_cidr = "10.0.0.0/16" } run "test_vpc_name_format" { @@ -57,7 +59,7 @@ run "test_public_subnet_name_format" { command = plan assert { - condition = alltrue([ + condition = alltrue([ for i, subnet in aws_subnet.public : subnet.tags["Name"] == "${var.project_name}-${var.environment}-public-${var.availability_zones[i]}" ]) @@ -96,7 +98,7 @@ run "test_private_subnet_name_format" { command = plan assert { - condition = alltrue([ + condition = alltrue([ for i, subnet in aws_subnet.private : subnet.tags["Name"] == "${var.project_name}-${var.environment}-private-${var.availability_zones[i]}" ]) @@ -126,7 +128,7 @@ run "test_private_subnets_no_public_ip" { command = plan assert { - condition = alltrue([for subnet in aws_subnet.private : subnet.map_public_ip_on_launch == false]) + condition = alltrue([for subnet in aws_subnet.private : subnet.map_public_ip_on_launch != true]) error_message = "Private subnets must not auto-assign public IPs." } } diff --git a/infrastructure/modules/parameters/tests/parameters.tftest.hcl b/infrastructure/modules/parameters/tests/parameters.tftest.hcl index 6d6eeccfda..1e8ff3ae13 100644 --- a/infrastructure/modules/parameters/tests/parameters.tftest.hcl +++ b/infrastructure/modules/parameters/tests/parameters.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { allowed_hosts = "nest.owasp.dev" allowed_origins = "https://nest.owasp.dev" diff --git a/infrastructure/modules/security/tests/security.tftest.hcl b/infrastructure/modules/security/tests/security.tftest.hcl index 4622f43bb5..f179defb13 100644 --- a/infrastructure/modules/security/tests/security.tftest.hcl +++ b/infrastructure/modules/security/tests/security.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { common_tags = { Environment = "test", Project = "nest" } db_port = 5432 diff --git a/infrastructure/modules/storage/modules/s3-bucket/tests/s3-bucket.tftest.hcl b/infrastructure/modules/storage/modules/s3-bucket/tests/s3-bucket.tftest.hcl index d577e1244a..44d1669c6c 100644 --- a/infrastructure/modules/storage/modules/s3-bucket/tests/s3-bucket.tftest.hcl +++ b/infrastructure/modules/storage/modules/s3-bucket/tests/s3-bucket.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { bucket_name = "test-bucket" tags = { Environment = "test", Project = "nest" } diff --git a/infrastructure/modules/storage/tests/storage.tftest.hcl b/infrastructure/modules/storage/tests/storage.tftest.hcl index 933238bf57..b01bb6bbf6 100644 --- a/infrastructure/modules/storage/tests/storage.tftest.hcl +++ b/infrastructure/modules/storage/tests/storage.tftest.hcl @@ -1,3 +1,5 @@ +mock_provider "aws" {} + variables { common_tags = { Environment = "test", Project = "nest" } environment = "test"