1+ locals {
2+ aws_waf_rule_geo_block_countries = var. aws_waf_rule_geo_block_countries != " " ? [
3+ for n in split (" ," , var. aws_waf_rule_geo_block_countries ) : trim (n)
4+ ] : []
5+
6+ aws_waf_rule_geo_allow_only_countries = var. aws_waf_rule_geo_allow_only_countries != " " ? [
7+ for n in split (" ," , var. aws_waf_rule_geo_allow_only_countries ) : trim (n)
8+ ] : []
9+ }
10+
111# ## WAF Configuration
212resource "aws_wafv2_web_acl" "waf" {
313 count = var. aws_waf_enable ? 1 : 0
@@ -9,6 +19,345 @@ resource "aws_wafv2_web_acl" "waf" {
919 allow {}
1020 }
1121
22+ # Rate limiting rule
23+ dynamic "rule" {
24+ for_each = var. aws_waf_rule_rate_limit != " " ? [1 ] : []
25+ content {
26+ name = " RateLimitRule"
27+ priority = 10
28+
29+ action {
30+ block {}
31+ }
32+
33+ statement {
34+ rate_based_statement {
35+ limit = tonumber (var. aws_waf_rule_rate_limit )
36+ aggregate_key_type = " IP"
37+ }
38+ }
39+
40+ visibility_config {
41+ cloudwatch_metrics_enabled = true
42+ metric_name = " RateLimitRule"
43+ sampled_requests_enabled = true
44+ }
45+ }
46+ }
47+
48+ # AWS Managed Core Rule Set
49+ dynamic "rule" {
50+ for_each = var. aws_waf_rule_managed_rules ? [1 ] : []
51+ content {
52+ name = " AWSManagedRulesCommonRuleSet"
53+ priority = 20
54+
55+ override_action {
56+ none {}
57+ }
58+
59+ statement {
60+ managed_rule_group_statement {
61+ name = " AWSManagedRulesCommonRuleSet"
62+ vendor_name = " AWS"
63+ }
64+ }
65+
66+ visibility_config {
67+ cloudwatch_metrics_enabled = true
68+ metric_name = " AWSManagedRulesCommonRuleSetMetric"
69+ sampled_requests_enabled = true
70+ }
71+ }
72+ }
73+
74+ # AWS Managed Known Bad Inputs Rule Set
75+ dynamic "rule" {
76+ for_each = var. aws_waf_rule_managed_bad_inputs ? [1 ] : []
77+ content {
78+ name = " AWSManagedRulesKnownBadInputsRuleSet"
79+ priority = 30
80+
81+ override_action {
82+ none {}
83+ }
84+
85+ statement {
86+ managed_rule_group_statement {
87+ name = " AWSManagedRulesKnownBadInputsRuleSet"
88+ vendor_name = " AWS"
89+ }
90+ }
91+
92+ visibility_config {
93+ cloudwatch_metrics_enabled = true
94+ metric_name = " AWSManagedRulesKnownBadInputsRuleSetMetric"
95+ sampled_requests_enabled = true
96+ }
97+ }
98+ }
99+
100+ # IP reputation rule
101+ dynamic "rule" {
102+ for_each = var. aws_waf_rule_ip_reputation ? [1 ] : []
103+ content {
104+ name = " AWSManagedRulesAmazonIpReputationList"
105+ priority = 40
106+
107+ override_action {
108+ none {}
109+ }
110+
111+ statement {
112+ managed_rule_group_statement {
113+ name = " AWSManagedRulesAmazonIpReputationList"
114+ vendor_name = " AWS"
115+ }
116+ }
117+
118+ visibility_config {
119+ cloudwatch_metrics_enabled = true
120+ metric_name = " AWSManagedRulesAmazonIpReputationListMetric"
121+ sampled_requests_enabled = true
122+ }
123+ }
124+ }
125+
126+ # Anonymous IPs
127+ dynamic "rule" {
128+ for_each = var. aws_waf_rule_anonymous_ip ? [1 ] : []
129+ content {
130+ name = " AWSManagedRulesAnonymousIpList"
131+ priority = 50
132+
133+ override_action {
134+ none {}
135+ }
136+
137+ statement {
138+ managed_rule_group_statement {
139+ name = " AWSManagedRulesAnonymousIpList"
140+ vendor_name = " AWS"
141+ }
142+ }
143+
144+ visibility_config {
145+ cloudwatch_metrics_enabled = true
146+ metric_name = " AWSManagedRulesAnonymousIpListMetric"
147+ sampled_requests_enabled = true
148+ }
149+ }
150+ }
151+
152+ # Bot Control (extra cost)
153+ dynamic "rule" {
154+ for_each = var. aws_waf_rule_bot_control ? [1 ] : []
155+ content {
156+ name = " AWSManagedRulesBotControlRuleSet"
157+ priority = 60
158+
159+ override_action {
160+ none {}
161+ }
162+
163+ statement {
164+ managed_rule_group_statement {
165+ name = " AWSManagedRulesBotControlRuleSet"
166+ vendor_name = " AWS"
167+ }
168+ }
169+
170+ visibility_config {
171+ cloudwatch_metrics_enabled = true
172+ metric_name = " AWSManagedRulesBotControlRuleSetMetric"
173+ sampled_requests_enabled = true
174+ }
175+ }
176+ }
177+
178+ # Geo-Blocking Rule
179+ dynamic "rule" {
180+ for_each = length (local. aws_waf_rule_geo_block_countries ) > 0 ? [1 ] : []
181+ content {
182+ name = " GeoBlockRule"
183+ priority = 70
184+
185+ action {
186+ block {}
187+ }
188+
189+ statement {
190+ geo_match_statement {
191+ country_codes = local. aws_waf_rule_geo_block_countries
192+ }
193+ }
194+
195+ visibility_config {
196+ cloudwatch_metrics_enabled = true
197+ metric_name = " GeoBlockRule"
198+ sampled_requests_enabled = true
199+ }
200+ }
201+ }
202+
203+ # Geo-Allow-Only Rule
204+ dynamic "rule" {
205+ for_each = length (local. aws_waf_rule_geo_allow_only_countries ) > 0 ? [1 ] : []
206+ content {
207+ name = " GeoAllowOnlyRule"
208+ priority = 75
209+
210+ action {
211+ block {}
212+ }
213+
214+ statement {
215+ not_statement {
216+ statement {
217+ geo_match_statement {
218+ country_codes = local. aws_waf_rule_geo_allow_only_countries
219+ }
220+ }
221+ }
222+ }
223+
224+ visibility_config {
225+ cloudwatch_metrics_enabled = true
226+ metric_name = " GeoAllowOnlyRule"
227+ sampled_requests_enabled = true
228+ }
229+ }
230+ }
231+
232+ # User-Defined Rule Group
233+ dynamic "rule" {
234+ for_each = var. aws_waf_rule_user_arn != " " ? [1 ] : []
235+ content {
236+ name = " UserDefinedRuleGroup"
237+ priority = 80
238+
239+ override_action {
240+ none {}
241+ }
242+
243+ statement {
244+ rule_group_reference_statement {
245+ arn = var. aws_waf_rule_user_arn
246+ }
247+ }
248+
249+ visibility_config {
250+ cloudwatch_metrics_enabled = true
251+ metric_name = " UserDefinedRuleGroup"
252+ sampled_requests_enabled = true
253+ }
254+ }
255+ }
256+
257+ # SQL Injection Rule Set
258+ dynamic "rule" {
259+ for_each = var. aws_waf_rule_sqli ? [1 ] : []
260+ content {
261+ name = " AWSManagedRulesSQLiRuleSet"
262+ priority = 85
263+
264+ override_action {
265+ none {}
266+ }
267+
268+ statement {
269+ managed_rule_group_statement {
270+ name = " AWSManagedRulesSQLiRuleSet"
271+ vendor_name = " AWS"
272+ }
273+ }
274+
275+ visibility_config {
276+ cloudwatch_metrics_enabled = true
277+ metric_name = " AWSManagedRulesSQLiRuleSetMetric"
278+ sampled_requests_enabled = true
279+ }
280+ }
281+ }
282+
283+ # Linux Rule Set
284+ dynamic "rule" {
285+ for_each = var. aws_waf_rule_linux ? [1 ] : []
286+ content {
287+ name = " AWSManagedRulesLinuxRuleSet"
288+ priority = 90
289+
290+ override_action {
291+ none {}
292+ }
293+
294+ statement {
295+ managed_rule_group_statement {
296+ name = " AWSManagedRulesLinuxRuleSet"
297+ vendor_name = " AWS"
298+ }
299+ }
300+
301+ visibility_config {
302+ cloudwatch_metrics_enabled = true
303+ metric_name = " AWSManagedRulesLinuxRuleSetMetric"
304+ sampled_requests_enabled = true
305+ }
306+ }
307+ }
308+
309+ # Unix Rule Set
310+ dynamic "rule" {
311+ for_each = var. aws_waf_rule_unix ? [1 ] : []
312+ content {
313+ name = " AWSManagedRulesUnixRuleSet"
314+ priority = 95
315+
316+ override_action {
317+ none {}
318+ }
319+
320+ statement {
321+ managed_rule_group_statement {
322+ name = " AWSManagedRulesUnixRuleSet"
323+ vendor_name = " AWS"
324+ }
325+ }
326+
327+ visibility_config {
328+ cloudwatch_metrics_enabled = true
329+ metric_name = " AWSManagedRulesUnixRuleSetMetric"
330+ sampled_requests_enabled = true
331+ }
332+ }
333+ }
334+
335+ # Admin Protection Rule Set
336+ dynamic "rule" {
337+ for_each = var. aws_waf_rule_admin_protection ? [1 ] : []
338+ content {
339+ name = " AWSManagedRulesAdminProtectionRuleSet"
340+ priority = 100
341+
342+ override_action {
343+ none {}
344+ }
345+
346+ statement {
347+ managed_rule_group_statement {
348+ name = " AWSManagedRulesAdminProtectionRuleSet"
349+ vendor_name = " AWS"
350+ }
351+ }
352+
353+ visibility_config {
354+ cloudwatch_metrics_enabled = true
355+ metric_name = " AWSManagedRulesAdminProtectionRuleSetMetric"
356+ sampled_requests_enabled = true
357+ }
358+ }
359+ }
360+
12361 tags = {
13362 Name = " ${ var . aws_resource_identifier } -waf"
14363 }
@@ -57,8 +406,6 @@ resource "aws_cloudwatch_log_group" "waf_log_group" {
57406 }
58407}
59408
60- # ...existing code...
61-
62409# Add WAF outputs
63410output "waf_web_acl_arn" {
64411 value = var. aws_waf_enable ? aws_wafv2_web_acl. waf [0 ]. arn : null
0 commit comments