Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
351 changes: 278 additions & 73 deletions config/terraform/aws/waf.tf
Original file line number Diff line number Diff line change
@@ -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
}