-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: optionally add WAF & access logs to ALB (#355)
* chore(wip): optionally add WAF & access logs to ALB * fix: default acl arn * [WIP] Add access logs to alb * [WIP] Fix s3 arn * chore: simplify WAF: users only need to pass in rules * we only need regional WAF not global * reject requests that didn't go through Cloudflare by default * add link for documentation * better documentation * [WIP] Use override action * [WIP] refactor * fix: cloudflare header * [WIP] Fix single header name * chore: allow requests only to domain * fix: prio for rules --------- Co-authored-by: Sam Kah Chiin <[email protected]>
- Loading branch information
1 parent
8a92dcd
commit 5d24f0c
Showing
4 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
locals { | ||
# 1-128 characters, a-z, A-Z, 0-9, and _ (underscore) | ||
# unique within the scope of the resource | ||
# i.e. unique per REGION if scope is REGIONAL | ||
# unique per ACCOUNT if scope is CLOUDFRONT | ||
waf_acl_name = "${var.project}-${var.environment}-alb-waf-acl" | ||
} | ||
|
||
resource "aws_wafv2_web_acl_association" "alb_waf" { | ||
count = var.enable_waf ? 1 : 0 | ||
|
||
resource_arn = aws_alb.alb.arn | ||
web_acl_arn = aws_wafv2_web_acl.alb[0].arn | ||
} | ||
|
||
resource "aws_wafv2_web_acl" "alb" { | ||
count = var.enable_waf ? 1 : 0 | ||
|
||
name = local.waf_acl_name | ||
scope = "REGIONAL" # or "CLOUDFRONT", but we have 1 ALB per cluster | ||
|
||
default_action { | ||
block {} | ||
} | ||
|
||
dynamic "rule" { | ||
for_each = var.waf_rules | ||
content { | ||
name = rule.value.name | ||
priority = rule.value.priority + 1 # prio must be unqiue. Hardcoded rules: see below | ||
|
||
dynamic "action" { | ||
for_each = rule.value.name != "AWSManagedRulesCommonRuleSet" ? [1] : [] | ||
|
||
content { | ||
dynamic "allow" { | ||
for_each = rule.value.action_type == "ALLOW" ? [1] : [] | ||
content {} | ||
} | ||
|
||
dynamic "block" { | ||
for_each = rule.value.action_type == "BLOCK" ? [1] : [] | ||
content {} | ||
} | ||
|
||
dynamic "count" { | ||
for_each = rule.value.action_type == "COUNT" ? [1] : [] | ||
content {} | ||
} | ||
} | ||
} | ||
|
||
dynamic "override_action" { | ||
# TODO: We should match the rule set name here | ||
for_each = rule.value.name == "AWSManagedRulesCommonRuleSet" ? [1] : [] | ||
|
||
content { | ||
dynamic "none" { | ||
for_each = rule.value.action_type == "NONE" ? [1] : [] | ||
content {} | ||
} | ||
dynamic "count" { | ||
for_each = rule.value.action_type == "COUNT" ? [1] : [] | ||
content {} | ||
} | ||
} | ||
} | ||
|
||
statement { | ||
dynamic "byte_match_statement" { | ||
for_each = rule.value.header_name != null ? [1] : [] | ||
content { | ||
search_string = rule.value.header_value | ||
field_to_match { | ||
single_header { | ||
name = rule.value.header_name | ||
} | ||
} | ||
text_transformation { | ||
priority = 0 | ||
type = rule.value.text_transformation | ||
} | ||
positional_constraint = rule.value.positional_constraint | ||
} | ||
} | ||
|
||
dynamic "managed_rule_group_statement" { | ||
for_each = rule.value.name == "AWSManagedRulesCommonRuleSet" ? [1] : [] | ||
content { | ||
name = "AWSManagedRulesCommonRuleSet" | ||
vendor_name = "AWS" | ||
} | ||
} | ||
} | ||
|
||
visibility_config { | ||
cloudwatch_metrics_enabled = true | ||
metric_name = rule.value.name | ||
sampled_requests_enabled = true | ||
} | ||
} | ||
} | ||
|
||
dynamic "rule" { | ||
for_each = [1] | ||
content { | ||
name = "RequireSpecificHost" | ||
priority = 1 # Adjust the priority accordingly | ||
|
||
action { | ||
allow {} | ||
} | ||
|
||
statement { | ||
byte_match_statement { | ||
search_string = var.domain_name | ||
field_to_match { | ||
single_header { | ||
name = "host" | ||
} | ||
} | ||
text_transformation { | ||
priority = 0 | ||
type = "NONE" | ||
} | ||
positional_constraint = "ENDS_WITH" | ||
} | ||
} | ||
|
||
visibility_config { | ||
cloudwatch_metrics_enabled = true | ||
metric_name = "RequireSpecificHost" | ||
sampled_requests_enabled = true | ||
} | ||
} | ||
} | ||
|
||
visibility_config { | ||
cloudwatch_metrics_enabled = true | ||
metric_name = local.waf_acl_name | ||
sampled_requests_enabled = true | ||
} | ||
|
||
tags = { | ||
Name = local.waf_acl_name | ||
Environment = var.environment | ||
Project = var.project | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters