Skip to content

Commit

Permalink
[p] Allow for specific IPs to bypass WAF (#6243, #6244, PR #6245)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsotirho-ucsc committed May 9, 2024
2 parents d4f909f + c963290 commit b3c6b23
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 121 deletions.
4 changes: 4 additions & 0 deletions src/azul/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,10 @@ def docker_images(self) -> dict[str, ImageSpec]:
def docker_image_manifests_path(self) -> Path:
return Path(config.project_root) / 'image_manifests.json'

blocked_v4_ips_term = 'blocked_v4_ips'

allowed_v4_ips_term = 'allowed_v4_ips'

waf_rate_rule_name = 'RateRule'

waf_rate_rule_period = 300 # seconds; this value is fixed by AWS
Expand Down
250 changes: 129 additions & 121 deletions terraform/api_gateway.tf.json.template.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,15 @@ def for_domain(cls, domain):
for zone in range(vpc.num_zones)
},
'aws_wafv2_ip_set': {
'blocked': {
'name': 'blocked',
name: {
'name': config.qualified_resource_name(resource_name=name,
stage=config.main_deployment_stage),
'scope': 'REGIONAL'
}
for name in [
config.blocked_v4_ips_term,
config.allowed_v4_ips_term
]
}
},
*(
Expand Down Expand Up @@ -202,137 +207,140 @@ def for_domain(cls, domain):
'allow': {}
},
'rule': [
{
'priority': 0,
'name': 'BlockedIPs',
'action': {
'block': {}
},
'statement': {
'ip_set_reference_statement': {
'arn': '${data.aws_wafv2_ip_set.blocked.arn}'
{**rule, 'priority': i}
for i, rule in enumerate([
*[
{
'name': name,
'action': {
action: {}
},
'statement': {
'ip_set_reference_statement': {
'arn': '${data.aws_wafv2_ip_set.%s.arn}' % ip_set_term
}
},
'visibility_config': {
'metric_name': name,
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
}
for name, action, ip_set_term in [
('BlockedIPs', 'block', config.blocked_v4_ips_term),
('AllowedIPs', 'allow', config.allowed_v4_ips_term)
]
],
{
'name': config.waf_rate_rule_name,
'action': {
'block': {
'custom_response': {
'response_code': 429,
'response_header': [
{
'name': 'Retry-After',
'value': str(config.waf_rate_rule_retry_after)
}
]
}
}
},
'statement': {
'rate_based_statement': {
'limit': 1000, # limit must be between 100 and 20,000,000
'aggregate_key_type': 'IP'
}
},
'visibility_config': {
'metric_name': config.waf_rate_rule_name,
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
'visibility_config': {
'metric_name': 'BlockedIPs',
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
{
'priority': 1,
'name': config.waf_rate_rule_name,
'action': {
'block': {
'custom_response': {
'response_code': 429,
'response_header': [
{
'name': 'AWS-CommonRuleSet',
'override_action': {
'none': {}
},
'statement': {
'managed_rule_group_statement': {
'name': 'AWSManagedRulesCommonRuleSet',
'vendor_name': 'AWS',
'rule_action_override': [
{
# This rule would limit the query
# string to 2048 bytes, which would
# block valid requests made during
# the integration tests. We disarm
# it by setting the action to
# `count`. API Gateway protects us
# from over-sized query strings by
# limiting the total combined size
# of the request line and header
# values to 10240 bytes.
'name': 'SizeRestrictions_QUERYSTRING',
'action_to_use': {
'count': {}
}
},
# FIXME: https://github.com/DataBiosphere/azul-private/issues/128
{
'name': 'Retry-After',
'value': str(config.waf_rate_rule_retry_after)
# This rule aims to limit bodies to
# 8192 bytes. We need to be able to
# handle larger bodies with hoisted
# parameters, so we demote the rule
# action to be counting instead of
# blocking.
'name': 'SizeRestrictions_BODY',
'action_to_use': {
'count': {}
}
}
]
}
},
'visibility_config': {
'metric_name': 'AWS-CommonRuleSet',
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
'statement': {
'rate_based_statement': {
'limit': 1000, # limit must be between 100 and 20,000,000
'aggregate_key_type': 'IP'
}
},
'visibility_config': {
'metric_name': config.waf_rate_rule_name,
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
{
'priority': 2,
'name': 'AWS-CommonRuleSet',
'override_action': {
'none': {}
},
'statement': {
'managed_rule_group_statement': {
'name': 'AWSManagedRulesCommonRuleSet',
'vendor_name': 'AWS',
'rule_action_override': [
{
# This rule would limit the query
# string to 2048 bytes, which would
# block valid requests made during
# the integration tests. We disarm
# it by setting the action to
# `count`. API Gateway protects us
# from over-sized query strings by
# limiting the total combined size
# of the request line and header
# values to 10240 bytes.
'name': 'SizeRestrictions_QUERYSTRING',
'action_to_use': {
'count': {}
}
},
# FIXME: https://github.com/DataBiosphere/azul-private/issues/128
{
# This rule aims to limit bodies to
# 8192 bytes. We need to be able to
# handle larger bodies with hoisted
# parameters, so we demote the rule
# action to be counting instead of
# blocking.
'name': 'SizeRestrictions_BODY',
'action_to_use': {
'count': {}
}
}
]
}
},
'visibility_config': {
'metric_name': 'AWS-CommonRuleSet',
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
{
'priority': 3,
'name': 'AWS-AmazonIpReputationList',
'override_action': {
'none': {}
},
'statement': {
'managed_rule_group_statement': {
'name': 'AWSManagedRulesAmazonIpReputationList',
'vendor_name': 'AWS'
{
'name': 'AWS-AmazonIpReputationList',
'override_action': {
'none': {}
},
'statement': {
'managed_rule_group_statement': {
'name': 'AWSManagedRulesAmazonIpReputationList',
'vendor_name': 'AWS'
}
},
'visibility_config': {
'metric_name': 'AWS-AmazonIpReputationList',
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
'visibility_config': {
'metric_name': 'AWS-AmazonIpReputationList',
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
{
'priority': 4,
'name': 'AWS-UnixRuleSet',
'override_action': {
'none': {}
},
'statement': {
'managed_rule_group_statement': {
'name': 'AWSManagedRulesUnixRuleSet',
'vendor_name': 'AWS'
{
'name': 'AWS-UnixRuleSet',
'override_action': {
'none': {}
},
'statement': {
'managed_rule_group_statement': {
'name': 'AWSManagedRulesUnixRuleSet',
'vendor_name': 'AWS'
}
},
'visibility_config': {
'metric_name': 'AWS-UnixRuleSet',
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
'visibility_config': {
'metric_name': 'AWS-UnixRuleSet',
'sampled_requests_enabled': True,
'cloudwatch_metrics_enabled': True
}
},
],
])],
'scope': 'REGIONAL',
'visibility_config': {
'cloudwatch_metrics_enabled': True,
Expand Down
19 changes: 19 additions & 0 deletions terraform/shared/shared.tf.json.template.py
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,8 @@ def conformance_pack(name: str) -> str:
}
},
'aws_wafv2_ip_set': {
# FIXME: Remove once no deployments reference this
# https://github.com/DataBiosphere/azul/issues/6244
'blocked': {
'name': 'blocked',
'scope': 'REGIONAL',
Expand All @@ -993,6 +995,23 @@ def conformance_pack(name: str) -> str:
'addresses'
]
}
},
**{
name: {
'name': config.qualified_resource_name(name),
'scope': 'REGIONAL',
'ip_address_version': 'IPV4',
'addresses': [],
'lifecycle': {
'ignore_changes': [
'addresses'
]
}
}
for name in [
config.blocked_v4_ips_term,
config.allowed_v4_ips_term
]
}
},
'aws_ecr_repository': {
Expand Down

0 comments on commit b3c6b23

Please sign in to comment.