cds-snc / forms-terraform

Infrastructure as Code for the GC Forms environment
MIT License
16 stars 7 forks source link

feat: add IPv4 blocklist rule to App, IdP WAF ACLs #821

Closed patheard closed 2 months ago

patheard commented 2 months ago

Summary

Add an IPv4 blocklist that will have malicious IPs temporarily added to it when attacks are detected.

Add a block rule to the App, API and IdP WAF ACLs that will block IP addresses that are part of this blocklist.

TODO

The following will be added in a future PR:

Related

github-actions[bot] commented 2 months ago

⚠ Terrform update available

Terraform: 1.9.5 (using 1.9.2)
Terragrunt: 0.67.4 (using 0.63.2)
github-actions[bot] commented 2 months ago

Staging: load_balancer

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

Plan: 1 to add, 1 to change, 0 to destroy
Show summary | CHANGE | NAME | |--------|-----------------------------------| | update | `aws_wafv2_web_acl.forms_acl` | | add | `aws_wafv2_ip_set.ipv4_blocklist` |
Show plan ```terraform Resource actions are indicated with the following symbols: + create ~ update in-place Terraform will perform the following actions: # aws_wafv2_ip_set.ipv4_blocklist will be created + resource "aws_wafv2_ip_set" "ipv4_blocklist" { + arn = (known after apply) + id = (known after apply) + ip_address_version = "IPV4" + lock_token = (known after apply) + name = "ipv4_blocklist" + scope = "REGIONAL" + tags_all = { + "CostCentre" = "forms-platform-staging" + "Terraform" = "true" } } # aws_wafv2_web_acl.forms_acl will be updated in-place ~ resource "aws_wafv2_web_acl" "forms_acl" { id = "e8fc1b67-9d4d-4a29-8c94-65b37b30a231" name = "GCForms" tags = {} # (8 unchanged attributes hidden) - rule { - name = "AWSManagedRulesAmazonIpReputationList" -> null - priority = 1 -> null - override_action { - none {} } - statement { - managed_rule_group_statement { - name = "AWSManagedRulesAmazonIpReputationList" -> null - vendor_name = "AWS" -> null # (1 unchanged attribute hidden) } } - visibility_config { - cloudwatch_metrics_enabled = true -> null - metric_name = "AWSManagedRulesAmazonIpReputationList" -> null - sampled_requests_enabled = true -> null } } - rule { - name = "AWSManagedRulesKnownBadInputsRuleSet" -> null - priority = 40 -> null - override_action { - none {} } - statement { - managed_rule_group_statement { - name = "AWSManagedRulesKnownBadInputsRuleSet" -> null - vendor_name = "AWS" -> null # (1 unchanged attribute hidden) } } - visibility_config { - cloudwatch_metrics_enabled = true -> null - metric_name = "AWSManagedRulesKnownBadInputsRuleSet" -> null - sampled_requests_enabled = true -> null } } - rule { - name = "AWSManagedRulesLinuxRuleSet" -> null - priority = 50 -> null - override_action { - none {} } - statement { - managed_rule_group_statement { - name = "AWSManagedRulesLinuxRuleSet" -> null - vendor_name = "AWS" -> null # (1 unchanged attribute hidden) } } - visibility_config { - cloudwatch_metrics_enabled = true -> null - metric_name = "AWSManagedRulesLinuxRuleSet" -> null - sampled_requests_enabled = true -> null } } + rule { + name = "BlockedIPv4" + priority = 80 + action { + block { } } + statement { + ip_set_reference_statement { + arn = (known after apply) } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "BlockedIPv4" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesAmazonIpReputationList" + priority = 1 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesAmazonIpReputationList" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesAmazonIpReputationList" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesKnownBadInputsRuleSet" + priority = 40 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesKnownBadInputsRuleSet" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesKnownBadInputsRuleSet" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesLinuxRuleSet" + priority = 50 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesLinuxRuleSet" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesLinuxRuleSet" + sampled_requests_enabled = true } } # (7 unchanged blocks hidden) } Plan: 1 to add, 1 to change, 0 to destroy. Changes to Outputs: + waf_ipv4_blocklist_arn = (known after apply) ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan.tfplan To perform exactly these actions, run the following command to apply: terraform apply "plan.tfplan" ```
Show Conftest results ```sh WARN - plan.json - main - Missing Common Tags: ["aws_acm_certificate.form_viewer"] WARN - plan.json - main - Missing Common Tags: ["aws_acm_certificate.form_viewer_maintenance_mode"] WARN - plan.json - main - Missing Common Tags: ["aws_acm_certificate.forms_api[0]"] WARN - plan.json - main - Missing Common Tags: ["aws_alb_listener_rule.forms_api[0]"] WARN - plan.json - main - Missing Common Tags: ["aws_cloudfront_distribution.maintenance_mode"] WARN - plan.json - main - Missing Common Tags: ["aws_iam_role.firehose_waf_logs"] WARN - plan.json - main - Missing Common Tags: ["aws_kinesis_firehose_delivery_stream.firehose_waf_logs"] WARN - plan.json - main - Missing Common Tags: ["aws_lb.form_viewer"] WARN - plan.json - main - Missing Common Tags: ["aws_lb_listener.form_viewer_http"] WARN - plan.json - main - Missing Common Tags: ["aws_lb_listener.form_viewer_https"] WARN - plan.json - main - Missing Common Tags: ["aws_lb_target_group.form_viewer_1"] WARN - plan.json - main - Missing Common Tags: ["aws_lb_target_group.form_viewer_2"] WARN - plan.json - main - Missing Common Tags: ["aws_lb_target_group.forms_api[0]"] WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket.maintenance_mode"] WARN - plan.json - main - Missing Common Tags: ["aws_s3_object.maintenance_static_page_css_files[\"style.css\"]"] WARN - plan.json - main - Missing Common Tags: ["aws_s3_object.maintenance_static_page_html_files[\"index-fr.html\"]"] WARN - plan.json - main - Missing Common Tags: ["aws_s3_object.maintenance_static_page_html_files[\"index.html\"]"] WARN - plan.json - main - Missing Common Tags: ["aws_s3_object.maintenance_static_page_ico_files[\"favicon.ico\"]"] WARN - plan.json - main - Missing Common Tags: ["aws_s3_object.maintenance_static_page_svg_files[\"site-unavailable.svg\"]"] WARN - plan.json - main - Missing Common Tags: ["aws_shield_protection.alb"] WARN - plan.json - main - Missing Common Tags: ["aws_shield_protection.route53_hosted_zone[0]"] WARN - plan.json - main -... ```
github-actions[bot] commented 2 months ago

Staging: idp

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

Plan: 0 to add, 2 to change, 0 to destroy
Show summary | CHANGE | NAME | |--------|---------------------------------------| | update | `aws_wafv2_web_acl.idp` | | | `module.idp_ecs.aws_ecs_service.this` |
Show plan ```terraform Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_wafv2_web_acl.idp will be updated in-place ~ resource "aws_wafv2_web_acl" "idp" { id = "bab5476e-86d5-4718-aa69-55b379a8673d" name = "idp" tags = { "CostCentre" = "forms-platform-staging" "Terraform" = "true" } # (8 unchanged attributes hidden) - rule { - name = "AWSManagedRulesAmazonIpReputationList" -> null - priority = 10 -> null - override_action { - none {} } - statement { - managed_rule_group_statement { - name = "AWSManagedRulesAmazonIpReputationList" -> null - vendor_name = "AWS" -> null # (1 unchanged attribute hidden) } } - visibility_config { - cloudwatch_metrics_enabled = true -> null - metric_name = "AWSManagedRulesAmazonIpReputationList" -> null - sampled_requests_enabled = true -> null } } - rule { - name = "AWSManagedRulesKnownBadInputsRuleSet" -> null - priority = 30 -> null - override_action { - none {} } - statement { - managed_rule_group_statement { - name = "AWSManagedRulesKnownBadInputsRuleSet" -> null - vendor_name = "AWS" -> null # (1 unchanged attribute hidden) } } - visibility_config { - cloudwatch_metrics_enabled = true -> null - metric_name = "AWSManagedRulesKnownBadInputsRuleSet" -> null - sampled_requests_enabled = true -> null } } - rule { - name = "AWSManagedRulesLinuxRuleSet" -> null - priority = 40 -> null - override_action { - none {} } - statement { - managed_rule_group_statement { - name = "AWSManagedRulesLinuxRuleSet" -> null - vendor_name = "AWS" -> null # (1 unchanged attribute hidden) } } - visibility_config { - cloudwatch_metrics_enabled = true -> null - metric_name = "AWSManagedRulesLinuxRuleSet" -> null - sampled_requests_enabled = true -> null } } + rule { + name = "BlockedIPv4" + priority = 70 + action { + block { } } + statement { + ip_set_reference_statement { + arn = "arn:aws:wafv2:ca-central-1:123456789012:ipset/mock-ip-blocklist/abcd1234-efgh5678-ijkl9012" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "BlockedIPv4" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesAmazonIpReputationList" + priority = 10 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesAmazonIpReputationList" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesAmazonIpReputationList" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesKnownBadInputsRuleSet" + priority = 30 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesKnownBadInputsRuleSet" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesKnownBadInputsRuleSet" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesLinuxRuleSet" + priority = 40 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesLinuxRuleSet" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesLinuxRuleSet" + sampled_requests_enabled = true } } # (7 unchanged blocks hidden) } # module.idp_ecs.aws_ecs_service.this will be updated in-place ~ resource "aws_ecs_service" "this" { id = "arn:aws:ecs:ca-central-1:687401027353:service/idp/zitadel" name = "zitadel" tags = { "CostCentre" = "forms-platform-staging" "Terraform" = "true" } ~ task_definition = "zitadel:3" -> "zitadel" # (15 unchanged attributes hidden) # (5 unchanged blocks hidden) } Plan: 0 to add, 2 to change, 0 to destroy. ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan.tfplan To perform exactly these actions, run the following command to apply: terraform apply "plan.tfplan" ```
Show Conftest results ```sh WARN - plan.json - main - Missing Common Tags: ["aws_alb_listener_rule.idp_protocol_version"] WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.idp_send_email"] WARN - plan.json - main - Missing Common Tags: ["aws_iam_user.idp_send_email"] WARN - plan.json - main - Missing Common Tags: ["aws_shield_protection.idp"] 23 tests, 19 passed, 4 warnings, 0 failures, 0 exceptions ```