Skip to content

Commit 68550d8

Browse files
committed
Different rate limits depending on HTTP method (#5555)
1 parent bd7c321 commit 68550d8

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

src/azul/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,8 @@ def docker_images(self) -> dict[str, ImageSpec]:
14621462

14631463
waf_rate_rule_name = 'RateRule'
14641464

1465+
waf_expensive_rate_rule_name = 'ExpensiveRateRule'
1466+
14651467

14661468
config: Config = Config() # yes, the type hint does help PyCharm
14671469

terraform/api_gateway.tf.json.template.py

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,34 @@ def for_domain(cls, domain):
204204
'rule': [
205205
{
206206
'priority': 0,
207+
'name': 'LabelPutRequests',
208+
'action': {
209+
'count': {}
210+
},
211+
'rule_label': {
212+
'name': 'azul:expensive'
213+
},
214+
'statement': {
215+
'byte_match_statement': {
216+
'field_to_match': {
217+
'method': {}
218+
},
219+
'positional_constraint': 'EXACTLY',
220+
'search_string': 'PUT',
221+
'text_transformation': {
222+
'priority': 0,
223+
'type': 'NONE'
224+
}
225+
}
226+
},
227+
'visibility_config': {
228+
'metric_name': 'LabelPutRequests',
229+
'sampled_requests_enabled': True,
230+
'cloudwatch_metrics_enabled': True
231+
}
232+
},
233+
{
234+
'priority': 1,
207235
'name': 'BlockedIPs',
208236
'action': {
209237
'block': {}
@@ -220,7 +248,31 @@ def for_domain(cls, domain):
220248
}
221249
},
222250
{
223-
'priority': 1,
251+
'priority': 2,
252+
'name': config.waf_expensive_rate_rule_name,
253+
'action': {
254+
'block': {}
255+
},
256+
'statement': {
257+
'rate_based_statement': {
258+
'limit': 100, # limit must be between 100 and 20,000,000
259+
'aggregate_key_type': 'IP',
260+
'scope_down_statement': {
261+
'label_match_statement': {
262+
'scope': 'LABEL',
263+
'key': 'azul:expensive'
264+
}
265+
}
266+
}
267+
},
268+
'visibility_config': {
269+
'metric_name': config.waf_expensive_rate_rule_name,
270+
'sampled_requests_enabled': True,
271+
'cloudwatch_metrics_enabled': True
272+
}
273+
},
274+
{
275+
'priority': 3,
224276
'name': config.waf_rate_rule_name,
225277
'action': {
226278
'block': {
@@ -248,7 +300,7 @@ def for_domain(cls, domain):
248300
}
249301
},
250302
{
251-
'priority': 2,
303+
'priority': 4,
252304
'name': 'AWS-CommonRuleSet',
253305
'override_action': {
254306
'none': {}
@@ -297,7 +349,7 @@ def for_domain(cls, domain):
297349
}
298350
},
299351
{
300-
'priority': 3,
352+
'priority': 5,
301353
'name': 'AWS-AmazonIpReputationList',
302354
'override_action': {
303355
'none': {}
@@ -315,7 +367,7 @@ def for_domain(cls, domain):
315367
}
316368
},
317369
{
318-
'priority': 4,
370+
'priority': 6,
319371
'name': 'AWS-UnixRuleSet',
320372
'override_action': {
321373
'none': {}

terraform/cloudwatch.tf.json.template.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,25 @@ def prod_qualified_resource_name(name: str) -> str:
367367
},
368368
'alarm_actions': ['${data.aws_sns_topic.monitoring.arn}'],
369369
'ok_actions': ['${data.aws_sns_topic.monitoring.arn}'],
370+
},
371+
'waf_expensive_rate_blocked': {
372+
'alarm_name': config.qualified_resource_name('waf_expensive_rate_blocked'),
373+
'comparison_operator': 'GreaterThanThreshold',
374+
'threshold': 0,
375+
'datapoints_to_alarm': 1,
376+
'evaluation_periods': 1,
377+
'period': 5 * 60,
378+
'metric_name': 'BlockedRequests',
379+
'namespace': 'AWS/WAFV2',
380+
'statistic': 'Sum',
381+
'treat_missing_data': 'notBreaching',
382+
'dimensions': {
383+
'WebACL': '${aws_wafv2_web_acl.api_gateway.name}',
384+
'Region': config.region,
385+
'Rule': config.waf_expensive_rate_rule_name
386+
},
387+
'alarm_actions': ['${data.aws_sns_topic.monitoring.arn}'],
388+
'ok_actions': ['${data.aws_sns_topic.monitoring.arn}'],
370389
}
371390
}
372391
}

0 commit comments

Comments
 (0)