Amazon Firewall Manager的隐藏功能

Amazon Firewall Manager
0
0
Amazon Firewall Manager (FMS)是一项安全管理服务,可让您在 Amazon Organizations 中跨账户和应用程序集中配置和管理防火墙规则。在创建新应用程序时,您可以借助 Firewall Manager 实施一套通用的安全规则,更轻松地让新应用程序和资源从一开始就达到合规要求。在多account的organization环境中,Amazon Firewall Manager可以大幅简化WAF的配置工作,集中管理大量Web ACL。 本文将介绍一个FMS的隐藏功能,我们知道Amazon WAF是支持配置请求被阻挡时返回给客户的 HTTP 状态代码和响应正文。这些代码可用于将用户重定向到应用程序的不同部分,或者根据用户被 WAF 阻挡的原因向其提供具体的响应代码。此外,您还可以使用自定义响应功能包含原因正文,以向用户返回自定义错误消息。自定义响应功能很强大实用,但是实际使用中会遇到以下两个问题: 1. 自定义响应只能在用户自建的rule group中设置,而对于AWS managed rule group的拦截响应内容,是无法直接修改的; 2. 当WAF规则和规则组很多的时候,只能在每个rule group中单独设置自定义响应内容,rule group之间无法共享这一设置; 那么是否可以通过FMS集中设置管理自定义HTTP状态代码和响应正文呢?在FMS的Web Console上无论是是创建还是修改Policy似乎都没有这一选项。 ![image.png](https://dev-media.amazoncloud.cn/9640f0a3dfe14a9188e29c7844dad5a7_image.png "image.png") 关于FMS的自定义响应,并没有详细的文档描述如何设置,只有一个简短的提示:https://aws.amazon.com/cn/about-aws/whats-new/2022/09/aws-firewall-manager-support-aws-waf-custom-requests-responses/ 那么,如何开启这一功能呢?其实,我们可以使用Terraform或CloudFormation来通过FMS集中管理Web ACL的自定义HTTP 状态代码和响应正文,从而使用FMS这一强大的“隐藏功能”。 以下是经过精简的FMS Policy配置Terraform代码,只保留了自定义响应相关的部分,读者可以根据自己的需要进行扩展。 ``` # 创建 Amazon Firewall Manager (FMS) 策略的 Terraform 资源 resource "aws_fms_policy" "myfmspolicy" { # 策略名称 name = "MY-FMS-POLICY" # 在一定时间内未使用的 Amazon Firewall Manager 管理的资源将被删除 delete_unused_fm_managed_resources = true # 是否启用自动修复 remediation_enabled = true # 策略应用的资源类型 resource_type_list = [ "AWS::ElasticLoadBalancingV2::LoadBalancer", "AWS::ApiGateway::Stage" ] # 与策略关联的服务配置数据 security_service_policy_data { # 安全服务的类型,此处使用 WAFV2 type = "WAFV2" # 注意,这里是配置的关键,应用了terraform的模板功能,以方便在不同环境和策略间共享配置,从模板文件中获取 managed_service_data = templatefile("security_service_policy_data_default.tftpl", { post_block_rule_group_arn = aws_wafv2_rule_group.postblockrulegroup.arn }) } } ``` security_service_policy_data.tftpl的内容如下: ``` # 使用 jsonencode 函数将 HCL 代码转换为 JSON 格式 ${jsonencode({ # 安全服务的类型 type = "WAFV2", # 自定义请求处理 (未设置) customRequestHandling = null, # 这里就是自定义响应配置关键属性 customResponse = { # 自定义响应体配置 customResponseBodies = { "DefaultResponse" = { # 自定义响应体内容(HTML 格式,显示警告信息) responseBody = "<!DOCTYPE html><html lang=\"en\"><head><title>WAF Alert</title></head><body><div class=\"container\"><h1>ALERT</h1><h2>Your request has been denied by our Web Application Firewall (WAF)</h2><p text-align=\"left\">Any attempts of malicious access are strictly prohibited.</p><h1>警告</h1><h2>您的请求已被我们的Web应用程序防火墙(WAF)拒绝</h2><p text-align=\"left\">严禁任何恶意访问。</p></div></body></html>", # 响应体类型为 HTML responseBodyType = "TEXT_HTML", }, }, # 使用自定义响应 customResponseBodyKey = "DefaultResponse", enableCustomResponse = true, # 响应头(未设置) responseHeaders = null, # 自定义响应的 HTTP 响应代码 responseCode = 403, }, # 规则组处理配置 postProcessRuleGroups = [ # 第一个规则组: { ruleGroupType = "ManagedRuleGroup", ruleGroupArn = null, sampledRequestsEnabled = true, excludeRules = [], managedRuleGroupIdentifier = { version = null, vendorName = "AWS", versionEnabled = null, managedRuleGroupName = "AWSManagedRulesCommonRuleSet", }, overrideAction = { type = "NONE", }, ruleActionOverrides = [ # 用于覆盖规则动作的设置,这里将所有规则的Action都替换为Count, 而不是Block { name = "BadBots_Header", actionToUse = { count = {}, }, } # 其他规则略 ], }, # 其他规则设置省略,下面是根据之前规则标签进行实际拦截的规则组: { ruleGroupArn = "${post_block_rule_group_arn}", ruleGroupType = "RuleGroup", excludeRules = [], overrideAction = { type = "NONE", }, managedRuleGroupIdentifier = null, sampledRequestsEnabled = null, }, ], # 未触发任何规则时的默认动作 defaultAction = { type = "ALLOW", }, })} ``` 以下对上述代码做进一步的说明。除了定义自定义响应的属性以外,post_block_rule_group是另一个配置的关键。以上配置的执行逻辑如下图所示: ![image.png](https://dev-media.amazoncloud.cn/00130eda6c544594a1c47f24fc242a6e_image.png "image.png") 符合条件的Web请求不会在AWS Managed Rule Goup直接进行拦截,而只是打上对应的label,而实际的拦截操作是在自定义的post_block_rule_group中进行的,通过这种特征匹配和拦截分开的设计,即可让AWS Managed Rule Goup的拦截也可以使用自定义的HTTP状态码和响应内容。 post_block_rule_group的内容如下: ``` # 创建 AWS WAFv2 规则组资源 resource "aws_wafv2_rule_group" "postblockrulegroup" { # 规则组容量 capacity = "150" # 规则组描述 description = "Block requests with specified labels." # 规则组名称 name = "POST-Block-rg" # 规则组作用范围(此处设置为区域级别) scope = "REGIONAL" # 自定义响应体配置 custom_response_body { # content 设置为来自 "custom_response.tftpl" 模板文件的响应内容 content = templatefile("custom_response.tftpl", {}) # 内容类型设置为 HTML content_type = "TEXT_HTML" # 自定义响应密钥 key = "DefaultResponse" } # 定义真正的拦截规则,注意这条规则要放置在所有规则的最后 rule { # 动作设置为阻止请求,并返回自定义响应 action { block { custom_response { # 使用 "DefaultResponse" 作为自定义响应密钥 custom_response_body_key = "DefaultResponse" # 自定义响应 HTTP 状态码 response_code = 403 } } } # 规则名称 name = "block-restricted-extensions" # 规则优先级(数值越低,优先级越高) priority = 1 # 规则匹配条件 statement { # 或条件匹配 or_statement { statement { # 按标签匹配规则 label_match_statement { # 标签键 key = "awswaf:managed:aws:core-rule-set:BadBots_Header" # 标签搜索范围 scope = "LABEL" } } # 其他规则的匹配条件,已省略 } } # 可见性配置 visibility_config { # 不启用 CloudWatch Metrics cloudwatch_metrics_enabled = false # 可见性配置的指标名称 metric_name = "PostBlock" # 不启用采样请求 sampled_requests_enabled = false } } # 规则组可见性配置 visibility_config { # 不启用 CloudWatch Metrics cloudwatch_metrics_enabled = false # 可见性配置的指标名称 metric_name = "RuleGroupMetrics" # 不启用采样请求 sampled_requests_enabled = false } } ``` 最后,让我们来看下这套Terraform apply到环境中的效果。创建FMS Policy后,FMS会根据Policy在指定的accounts中创建Web ACL并挂载到指定的ALB或API Gateway上。当我们基于FMS管理的Web ACL上增加自己的规则的时候,如果规则的Action设置为Block,并且Enable 'Custom response',则可以看到通过FMS集中配置的定制化响应内容 ![image.png](https://dev-media.amazoncloud.cn/68081ca4dd5147c3bfa790d8508d6b6a_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/3099652e874c43d6a03e8bac0188ef6d_image.png "image.png") 这样,就可以在不同Account的Web ACL和不同的规则间,共享同一套通过FMS管理的自定义响应内容,而不用一个一个单独设置了。 总结一下,目前自定义的HTTP状态码和响应内容只能通过API、Terraform或CloudFormation模板在Amazon Firewall Manager中使用,这一功能简化了在大规模环境下批量设置WAF定制化响应内容的工作,不过FMS设置的自定义响应目前只有自定义规则可以引用,AWS Managed Rule Group和FMS管理的规则,仍需要单独进行设置。使用基础架构即代码(IaC)的方式来配置FMS,是充分发挥FMS功能特性的最佳方式。
0
目录
关闭