From 17f62cd48b86f5d86f34676eac6cb0ad3ce8cd08 Mon Sep 17 00:00:00 2001 From: Darren Foo Date: Tue, 30 Jun 2020 12:40:54 -0700 Subject: [PATCH] convert to wafv2 resources and add relevant AWS managed rules --- config/terraform/aws/waf.tf | 351 ++++++++++++++++++++++++++++-------- 1 file changed, 278 insertions(+), 73 deletions(-) diff --git a/config/terraform/aws/waf.tf b/config/terraform/aws/waf.tf index b710ff5..3259b9e 100644 --- a/config/terraform/aws/waf.tf +++ b/config/terraform/aws/waf.tf @@ -1,113 +1,318 @@ ### -# AWS WAF - Key Submission - /claim-key +# AWS WAF - Managed Rules ### +resource "aws_wafv2_web_acl" "key_submission" { + name = "key_submission" + scope = "REGIONAL" -resource "aws_wafregional_byte_match_set" "key_submission_claim_key_uri" { - name = "KeySubmissionClaimKeyURI" - byte_match_tuples { - text_transformation = "NONE" - target_string = "/claim-key" - positional_constraint = "CONTAINS" + default_action { + block {} + } + + rule { + name = "AWSManagedRulesAmazonIpReputationList" + priority = 1 + + override_action { + none {} + } + + statement { + managed_rule_group_statement { + name = "AWSManagedRulesAmazonIpReputationList" + vendor_name = "AWS" + } + } - field_to_match { - type = "URI" + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesAmazonIpReputationList" + sampled_requests_enabled = true } } -} -resource "aws_wafregional_rate_based_rule" "key_submission_claim_key_uri" { - name = "KeySubmissionClaimKeyURIRateLimit" - metric_name = "KeySubmissionClaimKeyURIRateLimit" - rate_key = "IP" + rule { + name = "AWSManagedRulesCommonRuleSet" + priority = 2 + + override_action { + none {} + } - rate_limit = 100 + statement { + managed_rule_group_statement { + name = "AWSManagedRulesCommonRuleSet" + vendor_name = "AWS" + } + } - predicate { - type = "ByteMatch" - data_id = aws_wafregional_byte_match_set.key_submission_claim_key_uri.id - negated = false + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesCommonRuleSet" + sampled_requests_enabled = true + } } -} -### -# AWS WAF - Key Submission - /new-key-claim -### + rule { + name = "AWSManagedRulesKnownBadInputsRuleSet" + priority = 3 + + override_action { + none {} + } -resource "aws_wafregional_byte_match_set" "key_submission_new_key_claim_uri" { - name = "KeySubmissionNewKeyClaimURI" - byte_match_tuples { - text_transformation = "NONE" - target_string = "/new-key-claim" - positional_constraint = "CONTAINS" + statement { + managed_rule_group_statement { + name = "AWSManagedRulesKnownBadInputsRuleSet" + vendor_name = "AWS" + } + } - field_to_match { - type = "URI" + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesKnownBadInputsRuleSet" + sampled_requests_enabled = true } } -} -resource "aws_wafregional_byte_match_set" "key_submission_authorization_header" { - name = "KeySubmissionAuthorizationHeader" - byte_match_tuples { - text_transformation = "NONE" - target_string = "Bearer" - positional_constraint = "CONTAINS" + rule { + name = "AWSManagedRulesLinuxRuleSet" + priority = 4 + + override_action { + none {} + } + + statement { + managed_rule_group_statement { + name = "AWSManagedRulesLinuxRuleSet" + vendor_name = "AWS" + } + } - field_to_match { - type = "HEADER" - data = "authorization" + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesLinuxRuleSet" + sampled_requests_enabled = true } } -} -resource "aws_wafregional_rule" "key_submission_new_key_claim_authorization_header" { - name = "KeySubmissionNewKeyClaimURIMissingAuthorizationHeader" - metric_name = "KeySubmissionNewKeyClaimURIMissingAuthorizationHeader" + rule { + name = "AWSManagedRulesSQLiRuleSet" + priority = 5 - predicate { - type = "ByteMatch" - data_id = aws_wafregional_byte_match_set.key_submission_authorization_header.id - negated = true - } - predicate { - type = "ByteMatch" - data_id = aws_wafregional_byte_match_set.key_submission_new_key_claim_uri.id - negated = false + override_action { + none {} + } + + statement { + managed_rule_group_statement { + name = "AWSManagedRulesSQLiRuleSet" + vendor_name = "AWS" + } + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesSQLiRuleSet" + sampled_requests_enabled = true + } } -} -### -# AWS WAF ACL - Key Submission -### + rule { + name = "KeySubmissionClaimKeyURIRateLimit" + priority = 100 -resource "aws_wafregional_web_acl" "key_submission" { - name = "KeySubmission" - metric_name = "KeySubmission" + action { + block {} + } - default_action { - type = "ALLOW" + statement { + rate_based_statement { + limit = 100 + aggregate_key_type = "IP" + scope_down_statement { + byte_match_statement { + positional_constraint = "EXACTLY" + field_to_match { + uri_path {} + } + search_string = "/claim-key" + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" + } + text_transformation { + priority = 2 + type = "LOWERCASE" + } + } + } + } + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "KeySubmissionClaimKeyURIRateLimit" + sampled_requests_enabled = true + } } rule { - type = "RATE_BASED" - priority = 1 - rule_id = aws_wafregional_rate_based_rule.key_submission_claim_key_uri.id + name = "KeySubmissionURIs" + priority = 200 + action { - type = "BLOCK" + allow {} + } + + statement { + or_statement { + statement { + byte_match_statement { + positional_constraint = "STARTS_WITH" + field_to_match { + uri_path {} + } + search_string = "/services/" + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" + } + text_transformation { + priority = 2 + type = "LOWERCASE" + } + } + } + statement { + byte_match_statement { + positional_constraint = "STARTS_WITH" + field_to_match { + uri_path {} + } + search_string = "/exposure-configuration/" + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" + } + text_transformation { + priority = 2 + type = "LOWERCASE" + } + } + } + statement { + byte_match_statement { + positional_constraint = "EXACTLY" + field_to_match { + uri_path {} + } + search_string = "/upload" + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" + } + text_transformation { + priority = 2 + type = "LOWERCASE" + } + } + } + statement { + byte_match_statement { + positional_constraint = "EXACTLY" + field_to_match { + uri_path {} + } + search_string = "/claim-key" + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" + } + text_transformation { + priority = 2 + type = "LOWERCASE" + } + } + } + } + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "KeySubmissionURIs" + sampled_requests_enabled = false } } rule { - type = "REGULAR" - priority = 2 - rule_id = aws_wafregional_rule.key_submission_new_key_claim_authorization_header.id + name = "NewKeyClaimURI" + priority = 201 + action { - type = "BLOCK" + allow {} + } + + statement { + and_statement { + statement { + byte_match_statement { + positional_constraint = "STARTS_WITH" + field_to_match { + uri_path {} + } + search_string = "/new-key-claim" + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" + } + text_transformation { + priority = 2 + type = "LOWERCASE" + } + } + } + statement { + byte_match_statement { + positional_constraint = "STARTS_WITH" + field_to_match { + single_header { + name = "authorization" + } + } + search_string = "Bearer" + text_transformation { + priority = 1 + type = "NONE" + } + } + } + } } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "NewKeyClaimURI" + sampled_requests_enabled = false + } + } + + tags = { + (var.billing_tag_key) = var.billing_tag_value + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "key_submission" + sampled_requests_enabled = false } } -resource "aws_wafregional_web_acl_association" "key_submission" { +### +# AWS WAF - Resource Assocation +### +resource "aws_wafv2_web_acl_association" "key_submission_assocation" { resource_arn = aws_lb.covidshield_key_submission.arn - web_acl_id = aws_wafregional_web_acl.key_submission.id + web_acl_arn = aws_wafv2_web_acl.key_submission.arn }