Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Update to latest dynamic IP blocking module #892

Merged
merged 8 commits into from
Nov 20, 2024

Conversation

bryan-robitaille
Copy link
Contributor

@bryan-robitaille bryan-robitaille commented Nov 19, 2024

Summary | Résumé

Update Dynamic IP Blocking module to latest which contains the ability to filter on load balancer logs instead of WAF.

Checks every 15 minutes for 50 bad requests from an IP in the last 24 hours.

The blocked IP list covers all 3 services (IDP, API Server, App)

Adds an alarm to warn when IPs are added to the block list.

Copy link

Staging: app

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

Plan: 1 to add, 0 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_ecs_task_definition.form_viewer
Show plan
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_ecs_task_definition.form_viewer will be created
  + resource "aws_ecs_task_definition" "form_viewer" {
      + arn                      = (known after apply)
      + arn_without_revision     = (known after apply)
      + container_definitions    = jsonencode(
            [
              + {
                  + environment      = [
                      + {
                          + name  = "AUDIT_LOG_QUEUE_URL"
                          + value = "https://sqs.ca-central-1.amazonaws.com/687401027353/audit_log_queue"
                        },
                      + {
                          + name  = "COGNITO_CLIENT_ID"
                          + value = "17bsg3b2b7q5snon007rru264u"
                        },
                      + {
                          + name  = "COGNITO_ENDPOINT_URL"
                          + value = "cognito-idp.ca-central-1.amazonaws.com/ca-central-1_Cguq9JNQ1"
                        },
                      + {
                          + name  = "EMAIL_ADDRESS_CONTACT_US"
                          + value = "assistance+forms-formulaires@cds-snc.ca"
                        },
                      + {
                          + name  = "EMAIL_ADDRESS_SUPPORT"
                          + value = "assistance+forms-formulaires@cds-snc.ca"
                        },
                      + {
                          + name  = "HOST_URL"
                          + value = "https://forms-staging.cdssandbox.xyz"
                        },
                      + {
                          + name  = "METRIC_PROVIDER"
                          + value = "stdout"
                        },
                      + {
                          + name  = "NEXTAUTH_URL"
                          + value = "https://forms-staging.cdssandbox.xyz"
                        },
                      + {
                          + name  = "RECAPTCHA_V3_SITE_KEY"
                          + value = "6LfJDN4eAAAAAGvdRF7ZnQ7ciqdo1RQnQDFmh0VY"
                        },
                      + {
                          + name  = "REDIS_URL"
                          + value = "gcforms-redis-rep-group.uwpetx.ng.0001.cac1.cache.amazonaws.com"
                        },
                      + {
                          + name  = "RELIABILITY_FILE_STORAGE"
                          + value = "forms-staging-reliability-file-storage"
                        },
                      + {
                          + name  = "REPROCESS_SUBMISSION_QUEUE_URL"
                          + value = "https://sqs.ca-central-1.amazonaws.com/687401027353/reprocess_submission_queue.fifo"
                        },
                      + {
                          + name  = "TEMPLATE_ID"
                          + value = "8d597a1b-a1d6-4e3c-8421-042a2b4158b7"
                        },
                      + {
                          + name  = "TEMPORARY_TOKEN_TEMPLATE_ID"
                          + value = "b6885d06-d10a-422a-973f-05e274d9aa86"
                        },
                      + {
                          + name  = "TRACER_PROVIDER"
                          + value = "stdout"
                        },
                      + {
                          + name  = "VAULT_FILE_STORAGE"
                          + value = "forms-staging-vault-file-storage"
                        },
                      + {
                          + name  = "ZITADEL_PROVIDER"
                          + value = "https://auth.forms-staging.cdssandbox.xyz"
                        },
                    ]
                  + essential        = true
                  + image            = "687401027353.dkr.ecr.ca-central-1.amazonaws.com/form_viewer_staging"
                  + linuxParameters  = {
                      + capabilities = {
                          + add  = []
                          + drop = [
                              + "ALL",
                            ]
                        }
                    }
                  + logConfiguration = {
                      + logDriver = "awslogs"
                      + options   = {
                          + awslogs-group         = "Forms"
                          + awslogs-region        = "ca-central-1"
                          + awslogs-stream-prefix = "ecs-form-viewer"
                        }
                    }
                  + mountPoints      = []
                  + name             = "form_viewer"
                  + portMappings     = [
                      + {
                          + containerPort = 3000
                          + hostPort      = 3000
                          + protocol      = "tcp"
                        },
                    ]
                  + secrets          = [
                      + {
                          + name      = "DATABASE_URL"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:server-database-url-0PSpE3"
                        },
                      + {
                          + name      = "FRESHDESK_API_KEY"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:freshdesk_api_key-JVyxop"
                        },
                      + {
                          + name      = "GC_NOTIFY_CALLBACK_BEARER_TOKEN"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:notify_callback_bearer_token-aXJPLs"
                        },
                      + {
                          + name      = "NEXT_SERVER_ACTIONS_ENCRYPTION_KEY"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:next_server_actions_encryption_key-ByhiLu"
                        },
                      + {
                          + name      = "NOTIFY_API_KEY"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:notify_api_key-eR3nNp"
                        },
                      + {
                          + name      = "RECAPTCHA_V3_SECRET_KEY"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:recaptcha_secret-tTjsBo"
                        },
                      + {
                          + name      = "SENTRY_API_KEY"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:sentry_api_key-QBmONz"
                        },
                      + {
                          + name      = "TOKEN_SECRET"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:token_secret-n5Doyu"
                        },
                      + {
                          + name      = "ZITADEL_ADMINISTRATION_KEY"
                          + valueFrom = "arn:aws:secretsmanager:ca-central-1:687401027353:secret:zitadel_administration_key-Oaki1d"
                        },
                    ]
                  + systemControls   = []
                  + volumesFrom      = []
                },
            ]
        )
      + cpu                      = "2048"
      + execution_role_arn       = "arn:aws:iam::687401027353:role/form-viewer"
      + family                   = "form-viewer"
      + id                       = (known after apply)
      + memory                   = "4096"
      + network_mode             = "awsvpc"
      + requires_compatibilities = [
          + "FARGATE",
        ]
      + revision                 = (known after apply)
      + skip_destroy             = false
      + tags_all                 = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
        }
      + task_role_arn            = "arn:aws:iam::687401027353:role/form-viewer"
      + track_latest             = false
    }

Plan: 1 to add, 0 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
WARN - plan.json - main - Missing Common Tags: ["aws_appautoscaling_target.forms[0]"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.forms"]
WARN - plan.json - main - Missing Common Tags: ["aws_codedeploy_app.app"]
WARN - plan.json - main - Missing Common Tags: ["aws_codedeploy_deployment_group.app"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecs_cluster.forms"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecs_service.form_viewer"]
WARN - plan.json - main - Missing Common Tags: ["aws_ecs_task_definition.form_viewer"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.cognito"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_dynamodb"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_kms"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_s3"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_secrets_manager"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_policy.forms_sqs"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_role.codedeploy"]
WARN - plan.json - main - Missing Common Tags: ["aws_iam_role.forms"]

34 tests, 19 passed, 15 warnings, 0 failures, 0 exceptions

Copy link
Contributor

@craigzour craigzour left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Wondering whether we should wait for my work on #810 to be merged and released in production before pushing your changes (that would become part of the next release). This would be if we prefer making sure that everything works as expected in Staging since it is a brand new feature in both the terraform-modules and our infra repositories.

@bryan-robitaille
Copy link
Contributor Author

Wondering whether we should wait for my work

@craigzour We can definitely wait for your work to merge before this. I want it to sit on staging for a bit to ensure everything is ok.

@bryan-robitaille bryan-robitaille marked this pull request as draft November 19, 2024 19:08
@bryan-robitaille bryan-robitaille marked this pull request as ready for review November 20, 2024 15:33
Copy link

⚠ Terrform update available

Terraform: 1.9.8 (using 1.9.2)
Terragrunt: 0.69.0 (using 0.63.2)

Copy link

Staging: load_balancer

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

Plan: 1 to add, 3 to change, 0 to destroy
Show summary
CHANGE NAME
update module.waf_ip_blocklist.aws_cloudwatch_event_rule.ipv4_blocklist
module.waf_ip_blocklist.aws_iam_policy.ipv4_blocklist
module.waf_ip_blocklist.aws_lambda_function.ipv4_blocklist
add module.waf_ip_blocklist.aws_cloudwatch_log_metric_filter.ip_added_to_block_list
Show plan
Resource actions are indicated with the following symbols:
  + create
  ~ update in-place

Terraform will perform the following actions:

  # module.waf_ip_blocklist.aws_cloudwatch_event_rule.ipv4_blocklist will be updated in-place
  ~ resource "aws_cloudwatch_event_rule" "ipv4_blocklist" {
        id                  = "ipv4_blocklist_forms_app"
        name                = "ipv4_blocklist_forms_app"
      ~ schedule_expression = "rate(2 hours)" -> "rate(15 minutes)"
        tags                = {
            "CostCentre" = "forms"
            "Terraform"  = "true"
        }
        # (9 unchanged attributes hidden)
    }

  # module.waf_ip_blocklist.aws_cloudwatch_log_metric_filter.ip_added_to_block_list will be created
  + resource "aws_cloudwatch_log_metric_filter" "ip_added_to_block_list" {
      + id             = (known after apply)
      + log_group_name = "/aws/lambda/ipv4_blocklist_forms_app"
      + name           = "IpAddedToBlockList"
      + pattern        = "\"[Metric] - New IP added to WAF IP Set\""

      + metric_transformation {
          + default_value = "0"
          + name          = "IpAddedToBlockList"
          + namespace     = "CDS_Platform"
          + unit          = "None"
          + value         = "1"
        }
    }

  # module.waf_ip_blocklist.aws_iam_policy.ipv4_blocklist will be updated in-place
  ~ resource "aws_iam_policy" "ipv4_blocklist" {
        id               = "arn:aws:iam::687401027353:policy/ipv4_blocklist_forms_app"
        name             = "ipv4_blocklist_forms_app"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                    {
                        Action   = [
                            "athena:StartQueryExecution",
                            "athena:GetQueryResults",
                            "athena:GetQueryExecution",
                        ]
                        Effect   = "Allow"
                        Resource = "arn:aws:athena:ca-central-1:687401027353:workgroup/primary"
                        Sid      = "AthenaQueryAccess"
                    },
                  ~ {
                      ~ Resource = [
                          ~ "arn:aws:athena:ca-central-1:687401027353:catalog/AwsDataCatalog/database/access_logs/table/waf_logs" -> "arn:aws:athena:ca-central-1:687401027353:catalog/AwsDataCatalog/database/access_logs/table/*",
                            "arn:aws:athena:ca-central-1:687401027353:catalog/AwsDataCatalog/database/access_logs",
                        ]
                        # (3 unchanged attributes hidden)
                    },
                  ~ {
                      ~ Resource = [
                          ~ "arn:aws:glue:ca-central-1:687401027353:table/access_logs/waf_logs" -> "arn:aws:glue:ca-central-1:687401027353:table/access_logs/*",
                            "arn:aws:glue:ca-central-1:687401027353:database/access_logs",
                            # (1 unchanged element hidden)
                        ]
                        # (3 unchanged attributes hidden)
                    },
                    {
                        Action   = [
                            "logs:PutLogEvents",
                            "logs:CreateLogStream",
                        ]
                        Effect   = "Allow"
                        Resource = "arn:aws:logs:ca-central-1:687401027353:log-group:/aws/lambda/ipv4_blocklist_forms_app:*"
                        Sid      = "CloudWatchWriteAccess"
                    },
                    # (3 unchanged elements hidden)
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {
            "CostCentre" = "forms"
            "Terraform"  = "true"
        }
        # (7 unchanged attributes hidden)
    }

  # module.waf_ip_blocklist.aws_lambda_function.ipv4_blocklist will be updated in-place
  ~ resource "aws_lambda_function" "ipv4_blocklist" {
        id                             = "ipv4_blocklist_forms_app"
      ~ last_modified                  = "2024-09-23T13:49:40.486+0000" -> (known after apply)
      ~ source_code_hash               = "fCJk+rUL/Gi+YyFakKfRGodgqUC5Mq5QYcxBi1huoa0=" -> "x+q+cCA6WdzkkfRRAAH785MD20xSWJM6+iYOPe/0x+U="
        tags                           = {
            "CostCentre" = "forms"
            "Terraform"  = "true"
        }
        # (27 unchanged attributes hidden)

      ~ environment {
          ~ variables = {
              + "ATHENA_LB_TABLE"      = "lb_logs"
              - "ATHENA_TABLE"         = "waf_logs" -> null
              + "ATHENA_WAF_TABLE"     = "waf_logs"
              ~ "BLOCK_THRESHOLD"      = "20" -> "50"
              + "QUERY_LB"             = "true"
              + "QUERY_WAF"            = "false"
                # (7 unchanged elements hidden)
            }
        }

        # (3 unchanged blocks hidden)
    }

Plan: 1 to add, 3 to change, 0 to destroy.

Changes to Outputs:
  + waf_ipv4_new_blocked_ip_metric_filter_name      = "IpAddedToBlockList"
  + waf_ipv4_new_blocked_ip_metric_filter_namespace = "CDS_Platform"

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
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"]
WARN - plan.json - main - Missing Common Tags: ["aws_alb_listener_rule.forms_api"]
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"]
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 - Missing...

Copy link

Staging: alarms

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

Plan: 1 to add, 0 to change, 0 to destroy
Show summary
CHANGE NAME
add aws_cloudwatch_metric_alarm.ip_added_to_block_list
Show plan
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_cloudwatch_metric_alarm.ip_added_to_block_list will be created
  + resource "aws_cloudwatch_metric_alarm" "ip_added_to_block_list" {
      + actions_enabled                       = true
      + alarm_actions                         = [
          + "arn:aws:sns:ca-central-1:687401027353:alert-warning",
        ]
      + alarm_description                     = "WAF - IP(s) Has been added to the dynamic block list."
      + alarm_name                            = "IpAddedToBlockList"
      + arn                                   = (known after apply)
      + comparison_operator                   = "GreaterThanThreshold"
      + evaluate_low_sample_count_percentiles = (known after apply)
      + evaluation_periods                    = 1
      + id                                    = (known after apply)
      + metric_name                           = "default"
      + namespace                             = "default"
      + period                                = 900
      + statistic                             = "Sum"
      + tags_all                              = {
          + "CostCentre" = "forms-platform-staging"
          + "Terraform"  = "true"
        }
      + threshold                             = 1
      + treat_missing_data                    = "notBreaching"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Warning: Argument is deprecated

  with module.athena_bucket.aws_s3_bucket.this,
  on .terraform/modules/athena_bucket/S3/main.tf line 8, in resource "aws_s3_bucket" "this":
   8: resource "aws_s3_bucket" "this" {

Use the aws_s3_bucket_server_side_encryption_configuration resource instead

(and 3 more similar warnings elsewhere)

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: plan.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "plan.tfplan"
Show Conftest results
WARN - plan.json - main - Missing Common Tags: ["aws_athena_data_catalog.dynamodb"]
WARN - plan.json - main - Missing Common Tags: ["aws_athena_data_catalog.rds_data_catalog"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.codedeploy_sns"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.notify_slack"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.ELB_5xx_error_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.ELB_healthy_hosts"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.UnHealthyHostCount-TargetGroup1"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.UnHealthyHostCount-TargetGroup2"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.alb_ddos"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_audit_log_dead_letter_queue_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_cpu_utilization_high_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_lb_healthy_host_count"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_lb_unhealthy_host_count"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_memory_utilization_high_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.api_response_time_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.audit_log_dead_letter_queue_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.cognito_login_outside_canada_warn"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.cognito_signin_exceeded"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.ddos_detected_forms_warn"]
WARN - plan.json - main - Missing Common Tags:...

Copy link
Contributor

@craigzour craigzour left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Nice work 🙂

@bryan-robitaille bryan-robitaille merged commit d14ff31 into main Nov 20, 2024
11 checks passed
@bryan-robitaille bryan-robitaille deleted the feature/update_dynamic_ip_blocking branch November 20, 2024 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants