背景

AWS WAF(Web Application Firewall)是亚马逊网络服务(AWS)提供的一项安全服务,用于保护应用程序免受常见的网络威胁,如跨站脚本(XSS)、SQL注入、跨站请求伪造(CSRF)等。它通过检测和阻止恶意请求,实时监控和灵活的规则设置,提供了全面的应用程序防护。

AWS WAF的功能和必要性

  1. 防护应用程序: AWS WAF可以根据预定义的规则或自定义规则来过滤和阻止请求,有效地保护应用程序免受各种网络威胁。
  2. 实时监控和日志记录: 提供实时监控和日志记录功能,有助于及时发现和应对潜在的网络威胁。记录所有请求和响应数据,生成详细的日志供审计和分析使用。
  3. 灵活的规则设置: 允许用户根据自身需求设置规则,适应不同的应用程序和网络威胁场景。支持预定义规则和自定义规则,提供高度灵活性。
  4. 高可用性和可扩展性: 作为基于云的服务,AWS WAF具有高可用性和可扩展性,能够自动处理大量的请求流量,并根据需要进行水平扩展。

开发WAF批量添加ALB防护的功能的好处

  1. 提高效率: 批量添加ALB防护功能可以帮助用户快速、批量地将WAF规则应用到多个应用程序中,从而提高配置的效率。通过一次性的批量操作,用户无需逐个手动添加规则。
  2. 降低错误率: 批量添加功能可以减少人工操作的错误率。相比手动添加,批量添加可以减少因疏忽或错误而导致的规则配置错误,提高安全性。
  3. 简化管理: 批量添加功能可以简化WAF规则的管理。用户可以通过一次性的批量操作来添加、更新或删除规则,而无需逐个操作,从而减少了管理的复杂性。

前提

  • 已经在us-east-1安装区域WAF功能。
  • 提前设置好本地开发环境AK/SK。

开发环境

  • Python 3.8.2

安装依赖包

pip install boto3==1.26.105

用户权限

用户需要以下权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "wafv2:ListResourcesForWebACL",
                "cloudwatch:PutMetricAlarm",
                "shield:AssociateHealthCheck",
                "elasticloadbalancing:DescribeLoadBalancers",
                "wafv2:ListWebACLs",
                "wafv2:AssociateWebACL",
                "route53:CreateHealthCheck",
                "shield:CreateProtection",
                "shield:EnableApplicationLayerAutomaticResponse",
                "shield:ListProtections",
                "apigateway:SetWebACL",
                "apigateway:GET",
                "iam:GetRole",
                "elasticloadbalancing:SetWebACL"
            ],
            "Resource": "*"
        }
    ]
}

WAF批量添加ALB防护

以下Python脚本实现了对外部提供服务的ALB批量添加WAF防护的功能。新增保护返回状态码200,空白说明已经受到保护。

import boto3

# 获取所有WAFv2WebACL的ARN
def get_wafv2_web_acl_arns():
    wafv2 = boto3.client('wafv2', region_name='us-east-1')
    response = wafv2.list_web_acls(Scope='REGIONAL')
    web_acl_arns = [web_acl['ARN'] for web_acl in response['WebACLs']]
    return web_acl_arns

# 获取所有应用类型的负载均衡器的ARN
def get_load_balancer_arns():
    elbv2 = boto3.client('elbv2', region_name='us-east-1')
    response = elbv2.describe_load_balancers()
    load_balancer_arns = [lb['LoadBalancerArn'] for lb in response['LoadBalancers'] if lb['Type'] == 'application' and not lb['Scheme'] == 'internal']
    return load_balancer_arns

# 将WAFACL与ALB关联
def associate_waf_acl_with_alb(web_acl_arn, alb_arn):
    wafv2 = boto3.client('wafv2')
    response = wafv2.associate_web_acl(
        WebACLArn=web_acl_arn,
        ResourceArn=alb_arn
    )
    return response

# 检查ALB是否与WAF关联
def is_alb_protected(alb_arn, web_acl_arn):
    wafv2 = boto3.client('wafv2', region_name='us-east-1')
    response = wafv2.list_resources_for_web_acl(WebACLArn=web_acl_arn)
    protected_resources = response['ResourceArns']
    return alb_arn in protected_resources

# 使用示例
web_acl_arns = get_wafv2_web_acl_arns()
load_balancer_arns = get_load_balancer_arns()
for alb_arn in load_balancer_arns:
    for web_acl_arn in web_acl_arns:
        value = is_alb_protected(alb_arn, web_acl_arn)
        if not value:
            response = associate_waf_acl_with_alb(web_acl_arn, alb_arn)
            print(response["ResponseMetadata"]["HTTPStatusCode"])

WAF批量移除ALB防护

以下Python脚本实现了WAF批量移除ALB

以下详解权限没有单独验证,笔者是使用管理员实现,移除返回状态200,空白说明没有可移除

import boto3  # 导入boto3库,用于与AWS服务进行交互

def get_load_balancer_arns():  # 定义获取负载均衡器ARN的函数
    elbv2 = boto3.client('elbv2', region_name='us-east-1')  # 创建elbv2客户端对象
    response = elbv2.describe_load_balancers()  # 调用describe_load_balancers方法获取负载均衡器信息
    load_balancer_arns = [lb['LoadBalancerArn'] for lb in response['LoadBalancers'] if lb['Type'] == 'application' and not lb['Scheme'] == 'internal']  # 提取符合条件的负载均衡器ARN
    return load_balancer_arns  # 返回负载均衡器ARN列表

def get_wafv2_web_acl_arns():  # 定义获取WAFv2 Web ACL ARN的函数
    wafv2 = boto3.client('wafv2', region_name='us-east-1')  # 创建wafv2客户端对象
    response = wafv2.list_web_acls(Scope='REGIONAL')  # 调用list_web_acls方法获取Web ACL信息
    web_acl_arns = [web_acl['ARN'] for web_acl in response['WebACLs']]  # 提取Web ACL ARN
    return web_acl_arns  # 返回Web ACL ARN列表

def disassociate_web_acl(resource_arn):  # 定义取消关联Web ACL的函数
    wafv2 = boto3.client('wafv2')  # 创建wafv2客户端对象
    response = wafv2.disassociate_web_acl(ResourceArn=resource_arn)  # 调用disassociate_web_acl方法取消关联Web ACL
    return response  # 返回取消关联操作的响应

def is_alb_protected(alb_arn, web_acl_arn):  # 定义判断负载均衡器是否受到保护的函数
    wafv2 = boto3.client('wafv2', region_name='us-east-1')  # 创建wafv2客户端对象
    response = wafv2.list_resources_for_web_acl(WebACLArn=web_acl_arn)  # 调用list_resources_for_web_acl方法获取与Web ACL关联的资源
    protected_resources = response['ResourceArns']  # 提取受保护的资源ARN列表
    return alb_arn in protected_resources  # 判断负载均衡器ARN是否在受保护的资源列表中

# 使用示例
load_balancer_arns = get_load_balancer_arns()  # 获取负载均衡器ARN列表
web_acl_arns = get_wafv2_web_acl_arns()  # 获取Web ACL ARN列表
for resource_arn in load_balancer_arns:  # 遍历负载均衡器ARN列表
    for web_acl_arn in web_acl_arns:  # 遍历Web ACL ARN列表
        value = is_alb_protected(resource_arn, web_acl_arn)  # 判断负载均衡器是否受到保护
        if value:  # 如果受到保护
            response = disassociate_web_acl(resource_arn)  # 取消关联Web ACL
            print(response["ResponseMetadata"]["HTTPStatusCode"])  # 打印取消关联操作的HTTP状态码