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

feat: add new cloudwatch alarm and waf rule for Cognito login outside Canada #558

Merged
merged 2 commits into from
Dec 27, 2023

Conversation

wmoussa-gc
Copy link
Contributor

Summary | Résumé

Setting up a warning alarm (for now) on out of country access since it could be an indicator of a compromised account.

https://app.zenhub.com/workspaces/gcforms-60cb8929764d71000e481cab/issues/gh/cds-snc/platform-forms-client/3008


This pull request introduces a new rule to the current GC Forms WAF ACL, which identifies and counts instances where a public servant user is attempting to sign in from outside Canada.

Additionally, it sets up a new CloudWatch alarm to send a warning notification to the team when the count exceeds 0 within a 1-minute period.

Test instructions | Instructions pour tester la modification

  • You will need a VPN that allows you to connect via a different country (like ExpressVPN).
  • Pick a country other than Canada.
  • Go to the forms login page and attempt a sign-in.
  • Check the Slack channel for a notification.

@wmoussa-gc wmoussa-gc changed the title feat: Add new cloudwatch alarm and waf rule feat: add new cloudwatch alarm and waf rule for Cognito login outside Canada Dec 22, 2023
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I initially committed this file with some changes, but later decided to remove it from the local workspace to prevent the commit. I'm not sure what you recommend in this situation.

Copy link
Contributor

Choose a reason for hiding this comment

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

The yarn lock changes were more than likely valid. We do also receive lock file refreshes that run weekly on Renovate. In this case it would be easiest to undo the delete and then recommit the changes you would like to include. Since the yarn.lock delete change was done on the last commit in this branch you could do a soft reset by moving HEAD back one step, unstage your changes, stage the WAF priority change, and then commit.

> git reset --soft HEAD~1   # Moves head back one step but keeps changes
> git  reset  # Unstages all staged changes
> git add ./aws/load_balancer/waf.tf  # Stage the file who's changes you want to keep
> git commit -m "fix priority order of the rule"   # Commit the change
> git push --force  # Overwrite origin (aka Github) with local commit history for this branch

Copy link
Contributor Author

Choose a reason for hiding this comment

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

wow thank you for prepping the git commands!!

Copy link
Contributor

@bryan-robitaille bryan-robitaille left a comment

Choose a reason for hiding this comment

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

Looking good! Let's just remove the deleted lock file and we'll be good to merge.

Copy link
Contributor

Choose a reason for hiding this comment

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

The yarn lock changes were more than likely valid. We do also receive lock file refreshes that run weekly on Renovate. In this case it would be easiest to undo the delete and then recommit the changes you would like to include. Since the yarn.lock delete change was done on the last commit in this branch you could do a soft reset by moving HEAD back one step, unstage your changes, stage the WAF priority change, and then commit.

> git reset --soft HEAD~1   # Moves head back one step but keeps changes
> git  reset  # Unstages all staged changes
> git add ./aws/load_balancer/waf.tf  # Stage the file who's changes you want to keep
> git commit -m "fix priority order of the rule"   # Commit the change
> git push --force  # Overwrite origin (aka Github) with local commit history for this branch

@wmoussa-gc wmoussa-gc force-pushed the wmoussa-alarm-cognito branch from 7d43af7 to 708af88 Compare December 22, 2023 17:16
Copy link

⚠ Terrform update available

Terraform: 1.6.6 (using 1.6.5)
Terragrunt: 0.54.10 (using 0.53.8)

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 aws_s3_bucket.maintenance_mode
aws_s3_bucket_policy.allow_cloudfront_to_access_static_website_in_s3
aws_wafv2_web_acl.forms_acl
add aws_wafv2_regex_pattern_set.cognito_login_paths
Show plan
Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
 <= read (data resources)

Terraform will perform the following actions:

  # data.aws_iam_policy_document.allow_cloudfront_to_access_static_website_in_s3 will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "aws_iam_policy_document" "allow_cloudfront_to_access_static_website_in_s3" {
      + id   = (known after apply)
      + json = (known after apply)

      + statement {
          + actions   = [
              + "s3:GetObject",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:s3:::gc-forms-application-maintenance-page/*",
            ]

          + principals {
              + identifiers = [
                  + "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2PGE1KRH6OS33",
                ]
              + type        = "AWS"
            }
        }
    }

  # aws_s3_bucket.maintenance_mode will be updated in-place
  ~ resource "aws_s3_bucket" "maintenance_mode" {
        id                          = "gc-forms-application-maintenance-page"
        tags                        = {
            "CostCentre" = "forms-platform-staging"
            "Terraform"  = "true"
        }
        # (13 unchanged attributes hidden)

      - website {
          - index_document = "index.html" -> null
        }

        # (2 unchanged blocks hidden)
    }

  # aws_s3_bucket_policy.allow_cloudfront_to_access_static_website_in_s3 will be updated in-place
  ~ resource "aws_s3_bucket_policy" "allow_cloudfront_to_access_static_website_in_s3" {
        id     = "gc-forms-application-maintenance-page"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "s3:GetObject"
                      - Effect    = "Allow"
                      - Principal = {
                          - AWS = "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2PGE1KRH6OS33"
                        }
                      - Resource  = "arn:aws:s3:::gc-forms-application-maintenance-page/*"
                      - Sid       = ""
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # aws_wafv2_regex_pattern_set.cognito_login_paths will be created
  + resource "aws_wafv2_regex_pattern_set" "cognito_login_paths" {
      + arn         = (known after apply)
      + description = "Regex to match the login URIs"
      + id          = (known after apply)
      + lock_token  = (known after apply)
      + name        = "cognito_login_paths"
      + scope       = "REGIONAL"
      + tags_all    = (known after apply)

      + regular_expression {
          + regex_string = "^\\/(api\\/auth\\/(signin|callback)\\/cognito)$"
        }
    }

  # 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       = {
            "CostCentre" = "forms-platform-staging"
            "Terraform"  = "true"
        }
        # (5 unchanged attributes hidden)

      + rule {
          + name     = "AWSCognitoLoginOutsideCanada"
          + priority = 8

          + action {
              + count {
                }
            }

          + statement {
              + and_statement {
                  + statement {
                      + not_statement {
                          + statement {
                              + geo_match_statement {
                                  + country_codes = [
                                      + "CA",
                                    ]
                                }
                            }
                        }
                    }
                  + statement {
                      + regex_pattern_set_reference_statement {
                          + arn = (known after apply)

                          + field_to_match {
                              + uri_path {}
                            }

                          + text_transformation {
                              + priority = 1
                              + type     = "COMPRESS_WHITE_SPACE"
                            }
                          + text_transformation {
                              + priority = 2
                              + type     = "LOWERCASE"
                            }
                        }
                    }
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "AWSCognitoLoginOutsideCanada"
              + sampled_requests_enabled   = false
            }
        }

        # (9 unchanged blocks hidden)
    }

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

Warning: Argument is deprecated

  with aws_s3_bucket.firehose_waf_logs,
  on kinesis.tf line 30, in resource "aws_s3_bucket" "firehose_waf_logs":
  30: resource "aws_s3_bucket" "firehose_waf_logs" {

Use the aws_s3_bucket_server_side_encryption_configuration resource instead

(and 5 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_s3_bucket_object.maintenance_static_page_css_files[\"style.css\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.maintenance_static_page_html_files[\"index-fr.html\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.maintenance_static_page_html_files[\"index.html\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.maintenance_static_page_ico_files[\"favicon.ico\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.maintenance_static_page_svg_files[\"site-unavailable.svg\"]"]
WARN - plan.json - main - Missing Common Tags: ["aws_wafv2_regex_pattern_set.cognito_login_paths"]
WARN - plan.json - main - Missing Common Tags: ["aws_wafv2_regex_pattern_set.forms_base_url"]
WARN - plan.json - main - Missing Common Tags: ["aws_wafv2_regex_pattern_set.valid_app_uri_paths"]
WARN - plan.json - main - Missing Common Tags: ["aws_wafv2_regex_pattern_set.valid_maintenance_mode_uri_paths"]

28 tests, 19 passed, 9 warnings, 0 failures, 0 exceptions

Copy link

Staging: lambdas

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

Plan: 0 to add, 1 to change, 0 to destroy
Show summary
CHANGE NAME
update aws_lambda_function.vault_integrity
Show plan
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_lambda_function.vault_integrity will be updated in-place
  ~ resource "aws_lambda_function" "vault_integrity" {
        id                             = "Vault_Data_Integrity_Check"
      ~ last_modified                  = "2023-12-14T16:47:42.000+0000" -> (known after apply)
      ~ source_code_hash               = "9opCvMNrZA+BCLvHUGkHDweCXfVwLgP5jcHfkTPLySc=" -> "TowbMcppnki+0a5fq50Oral3CqleiwGw7U1igvFz0Ws="
        tags                           = {
            "CostCentre" = "forms-platform-staging"
            "Terraform"  = "true"
        }
        # (22 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

Plan: 0 to add, 1 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_cloudwatch_event_rule.cron_2am_every_day"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.cron_3am_every_day"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.cron_4am_every_day"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_event_rule.cron_5am_every_business_day"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.archive_form_templates"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.audit_logs"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.dead_letter_queue_consumer"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.nagware"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.reliability"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.response_archiver"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.submission"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_log_group.vault_integrity"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.audit_logs_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.form_archiver_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.nagware_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.reliability_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.reliability_dlq_consumer_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.response_archiver_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.submission_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_s3_bucket_object.vault_integrity_code"]
WARN - plan.json - main - Missing Common Tags: ["aws_signer_signing_profile.lambda_signing_profile[0]"]

40 tests, 19 passed, 21 warnings, 0...

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.cognito_login_outside_canada_warn
Show plan
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_cloudwatch_metric_alarm.cognito_login_outside_canada_warn will be created
  + resource "aws_cloudwatch_metric_alarm" "cognito_login_outside_canada_warn" {
      + actions_enabled                       = true
      + alarm_actions                         = [
          + "arn:aws:sns:ca-central-1:687401027353:alert-warning",
        ]
      + alarm_description                     = "Forms: A sign-in by a forms owner has been detected from outside of Canada."
      + alarm_name                            = "AWSCognitoLoginOutsideCanadaAlarm"
      + arn                                   = (known after apply)
      + comparison_operator                   = "GreaterThanThreshold"
      + dimensions                            = {
          + "Rule"   = "AWSCognitoLoginOutsideCanada"
          + "WebACL" = "GCForms"
        }
      + evaluate_low_sample_count_percentiles = (known after apply)
      + evaluation_periods                    = 1
      + id                                    = (known after apply)
      + metric_name                           = "CountedRequests"
      + namespace                             = "AWS/WAFV2"
      + period                                = 60
      + statistic                             = "SampleCount"
      + tags_all                              = (known after apply)
      + threshold                             = 0
      + 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_logging resource instead

(and 8 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_cloudwatch_log_group.notify_slack"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.alb_ddos"]
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.route53_ddos[0]"]
WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.vault_data_integrity_check_lambda_iterator_age"]

24 tests, 19 passed, 5 warnings, 0 failures, 0 exceptions

@wmoussa-gc wmoussa-gc enabled auto-merge (squash) December 22, 2023 18:08
@wmoussa-gc wmoussa-gc merged commit d23a252 into develop Dec 27, 2023
4 checks passed
@wmoussa-gc wmoussa-gc deleted the wmoussa-alarm-cognito branch December 27, 2023 15:37
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