Skip to content

Commit 4d76291

Browse files
committed
eli-537 enabling WAF blocks
1 parent 4ff5a3e commit 4d76291

2 files changed

Lines changed: 31 additions & 22 deletions

File tree

infrastructure/stacks/api-layer/waf.tf

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# WAF Web ACL for API Gateway
22
# Only deployed in production environment for cost optimization
3-
# Initially all rules are in COUNT mode to monitor traffic patterns
43

54
resource "aws_wafv2_web_acl" "api_gateway" {
65
count = local.waf_enabled ? 1 : 0
@@ -19,7 +18,7 @@ resource "aws_wafv2_web_acl" "api_gateway" {
1918
priority = 10
2019

2120
override_action {
22-
count {} # Start in count mode - change to none {} when ready to block
21+
none {}
2322
}
2423

2524
statement {
@@ -43,13 +42,21 @@ resource "aws_wafv2_web_acl" "api_gateway" {
4342
priority = 20
4443

4544
override_action {
46-
count {} # Start in count mode - change to none {} when ready to block
45+
none {}
4746
}
4847

4948
statement {
5049
managed_rule_group_statement {
5150
vendor_name = "AWS"
5251
name = "AWSManagedRulesCommonRuleSet"
52+
53+
# Override NoUserAgent_Header to count only - APIM health checks send no User-Agent
54+
rule_action_override {
55+
name = "NoUserAgent_Header"
56+
action_to_use {
57+
count {}
58+
}
59+
}
5360
}
5461
}
5562

@@ -93,7 +100,7 @@ resource "aws_wafv2_web_acl" "api_gateway" {
93100
priority = 40
94101

95102
action {
96-
count {} # Start in count mode - change to block {} when ready
103+
block {}
97104
}
98105

99106
statement {
@@ -110,15 +117,15 @@ resource "aws_wafv2_web_acl" "api_gateway" {
110117
}
111118
}
112119

113-
# Rule 5: Geographic Monitoring Rule - Monitor non-UK traffic (COUNT only)
114-
# NHS-specific requirement: initially monitor requests originating from outside GB
115-
# This rule COUNTS any request whose geo country code is not GB (does not block)
120+
# Rule 5: Geographic Block Rule - Block non-UK traffic
121+
# NHS-specific requirement: block requests originating from outside GB
122+
# Defence-in-depth against stolen mTLS certificates being used from outside the UK
116123
rule {
117-
name = "MonitorNonUK"
124+
name = "BlockNonUK"
118125
priority = 50
119126

120127
action {
121-
count {}
128+
block {}
122129
}
123130

124131
statement {
@@ -133,7 +140,7 @@ resource "aws_wafv2_web_acl" "api_gateway" {
133140

134141
visibility_config {
135142
cloudwatch_metrics_enabled = true
136-
metric_name = "MonitorNonUK"
143+
metric_name = "BlockNonUK"
137144
sampled_requests_enabled = true
138145
}
139146
}

infrastructure/stacks/api-layer/waf_alarms.tf

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,14 @@ resource "aws_cloudwatch_metric_alarm" "waf_rate_limit_blocks" {
129129
)
130130
}
131131

132-
# Alarm for non-UK rate limit violations
132+
# Alarm for blocked non-UK requests
133133
resource "aws_cloudwatch_metric_alarm" "waf_non_uk_counted" {
134134
count = local.waf_enabled ? 1 : 0
135-
alarm_name = "WAF-NonUK-CountedRequests-${local.workspace}"
136-
alarm_description = "Alerts when non-UK requests are observed (COUNT mode) by geo rule"
135+
alarm_name = "WAF-NonUK-BlockedRequests-${local.workspace}"
136+
alarm_description = "Alerts when non-UK requests are blocked by geo rule - may indicate stolen mTLS cert use from outside UK"
137137
comparison_operator = "GreaterThanThreshold"
138138
evaluation_periods = 2
139-
metric_name = "CountedRequests"
139+
metric_name = "BlockedRequests"
140140
namespace = "AWS/WAFV2"
141141
period = 300
142142
statistic = "Sum"
@@ -145,7 +145,7 @@ resource "aws_cloudwatch_metric_alarm" "waf_non_uk_counted" {
145145

146146
dimensions = {
147147
Region = var.default_aws_region
148-
Rule = "MonitorNonUK"
148+
Rule = "BlockNonUK"
149149
WebACL = aws_wafv2_web_acl.api_gateway[0].name
150150
}
151151

@@ -154,8 +154,8 @@ resource "aws_cloudwatch_metric_alarm" "waf_non_uk_counted" {
154154
tags = merge(
155155
local.tags,
156156
{
157-
Name = "WAF-NonUK-CountedRequests"
158-
Severity = "medium"
157+
Name = "WAF-NonUK-BlockedRequests"
158+
Severity = "high"
159159
Environment = var.environment
160160
}
161161
)
@@ -192,19 +192,21 @@ resource "aws_cloudwatch_metric_alarm" "waf_all_requests_high" {
192192
)
193193
}
194194

195-
# Alarm for monitoring counted requests (during initial count mode)
196-
# This helps identify if rules would block legitimate traffic
195+
# Alarm for counted requests (NoUserAgent_Header override)
196+
# The CRS NoUserAgent_Header sub-rule is kept in COUNT to allow the API proxy healthcheck.
197+
# This alarm alerts if count spikes unexpectedly, which could indicate rule misconfiguration
198+
# or unexpected traffic patterns hitting that override.
197199
resource "aws_cloudwatch_metric_alarm" "waf_counted_requests_monitoring" {
198200
count = local.waf_enabled ? 1 : 0
199201
alarm_name = "WAF-CountedRequests-Monitoring-${local.workspace}"
200-
alarm_description = "Monitors requests that would be blocked if rules were active (COUNT mode)"
202+
alarm_description = "Monitors counted requests - expected to be low volume (healthcheck NoUserAgent_Header override only)"
201203
comparison_operator = "GreaterThanThreshold"
202204
evaluation_periods = 1
203205
metric_name = "CountedRequests"
204206
namespace = "AWS/WAFV2"
205207
period = 300
206208
statistic = "Sum"
207-
threshold = 100 # Alert if many requests would be blocked
209+
threshold = 100 # Alert if count spikes beyond normal healthcheck frequency
208210
treat_missing_data = "notBreaching"
209211

210212
dimensions = {
@@ -220,7 +222,7 @@ resource "aws_cloudwatch_metric_alarm" "waf_counted_requests_monitoring" {
220222
Name = "WAF-CountedRequests-Monitoring"
221223
Severity = "low"
222224
Environment = var.environment
223-
Purpose = "Initial monitoring during COUNT mode phase"
225+
Purpose = "Monitor NoUserAgent_Header count override for healthcheck proxy"
224226
}
225227
)
226228
}

0 commit comments

Comments
 (0)