CDK를 사용하는 AWS WAF 간단한 방법, L2?
짧은 소개, CDK용 WAF L2의 현재 상태는 대부분 존재하지 않기 때문에 사용하기 쉬운 방법은 아직 멀었습니다.
당신이 생각하는 것보다 더 가깝지만.
예전에 만들었던 것을 공유해 봅시다.
CDK 프로젝트를 시작하기 위한 다소 합리적인 값을 관리하는 Python WAF 클래스
class WAFv2(Construct):
"""Implement a v2 WAF where metrics are sent to the AWS CloudWatch logs."""
# pylint: disable=W0235
def __init__(self, scope: Construct, construct_id: str) -> None:
super().__init__(scope, construct_id)
def web_acl(
self,
name: str,
rate_value: Union[int, None],
aws_common_rule: bool = True,
aws_anony_list: bool = False,
aws_bad_inputs_rule: bool = False,
aws_sqli_rule: bool = False,
aws_account_takeover_prevention: Union[bool, Dict[Any, Any]] = False,
waf_scope: Literal["REGIONAL", "CLOUDFRONT"] = "REGIONAL",
) -> wafv2.CfnWebACL:
"""Create AWS WAF with default rules.
The minimal configuration will create WAF ACL with aws_reputation_list
:param aws_account_takeover_prevention: The definition for account takeover prevention rule
:param aws_sqli_rule: The WAF managed rule by AWS AWS-AWSManagedRulesSQLiRuleSet
:param aws_bad_inputs_rule: The WAF managed rule by AWS AWS-AWSManagedRulesKnownBadInputsRuleSet
:param aws_anony_list: The WAF managed rule by AWS AWS-AWSManagedRulesAnonymousIpList
:param aws_common_rule: The WAF managed rule by AWS AWS-AWSManagedRulesCommonRuleSet
:param rate_value: The number of packets per seconds for custom rate limiting
:param waf_scope: The WAF scope, it could be regional for API GW, Cognito and ALB or
CLOUDFRONT for cloudfront distributions
:param name: Then name of WAF ACL
:return:
"""
# 0. Reputation List
aws_ip_rep_list = wafv2.CfnWebACL.RuleProperty(
name="AWS-AWSManagedRulesAmazonIpReputationList",
priority=0,
override_action=wafv2.CfnWebACL.OverrideActionProperty(none={}),
statement=wafv2.CfnWebACL.StatementProperty(
managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
name="AWSManagedRulesAmazonIpReputationList",
vendor_name="AWS",
)
),
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True,
metric_name="AWS-AWSManagedRulesAmazonIpReputationList",
sampled_requests_enabled=True,
),
)
waf_rules = [aws_ip_rep_list]
if rate_value:
# 1. Custom Rate Limit
rate_list = wafv2.CfnWebACL.RuleProperty(
name=f"Custom-RateLimit{rate_value}",
priority=1,
action=wafv2.CfnWebACL.RuleActionProperty(block=wafv2.CfnWebACL.BlockActionProperty()),
statement=wafv2.CfnWebACL.StatementProperty(
rate_based_statement=wafv2.CfnWebACL.RateBasedStatementProperty(
aggregate_key_type="IP",
limit=rate_value,
)
),
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True,
metric_name=f"Custom-RateLimit{rate_value}",
sampled_requests_enabled=True,
),
)
waf_rules.append(rate_list)
if aws_common_rule:
# 2. Common Rule
aws_common_rule = wafv2.CfnWebACL.RuleProperty(
name="AWS-AWSManagedRulesCommonRuleSet",
priority=2,
override_action=wafv2.CfnWebACL.OverrideActionProperty(none={}),
statement=wafv2.CfnWebACL.StatementProperty(
managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
name="AWSManagedRulesCommonRuleSet",
vendor_name="AWS",
)
),
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True,
metric_name="AWS-AWSManagedRulesCommonRuleSet",
sampled_requests_enabled=True,
),
)
waf_rules.append(aws_common_rule)
if aws_anony_list:
# 3. AnonymousIpList
aws_anony_list = wafv2.CfnWebACL.RuleProperty(
name="AWS-AWSManagedRulesAnonymousIpList",
priority=3,
override_action=wafv2.CfnWebACL.OverrideActionProperty(none={}),
statement=wafv2.CfnWebACL.StatementProperty(
managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
name="AWSManagedRulesAnonymousIpList",
vendor_name="AWS",
)
),
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True,
metric_name="AWS-AWSManagedRulesAnonymousIpList",
sampled_requests_enabled=True,
),
)
waf_rules.append(aws_anony_list)
if aws_bad_inputs_rule:
# 4. Known Bad Inputs Rule
aws_bad_inputs_rule = wafv2.CfnWebACL.RuleProperty(
name="AWS-AWSManagedRulesKnownBadInputsRuleSet",
priority=4,
override_action=wafv2.CfnWebACL.OverrideActionProperty(none={}),
statement=wafv2.CfnWebACL.StatementProperty(
managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
name="AWSManagedRulesKnownBadInputsRuleSet",
vendor_name="AWS",
)
),
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True,
metric_name="AWS-AWSManagedRulesKnownBadInputsRuleSet",
sampled_requests_enabled=True,
),
)
waf_rules.append(aws_bad_inputs_rule)
if aws_sqli_rule:
# 5. SQLi Rule
aws_sqli_rule = wafv2.CfnWebACL.RuleProperty(
name="AWS-AWSManagedRulesSQLiRuleSet",
priority=5,
override_action=wafv2.CfnWebACL.OverrideActionProperty(none={}),
statement=wafv2.CfnWebACL.StatementProperty(
managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
name="AWSManagedRulesSQLiRuleSet",
vendor_name="AWS",
)
),
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True,
metric_name="AWS-AWSManagedRulesSQLiRuleSet",
sampled_requests_enabled=True,
),
)
waf_rules.append(aws_sqli_rule)
if aws_account_takeover_prevention:
# 6. Account takeover prevention
aws_account_takeover_prevention_rule = wafv2.CfnWebACL.RuleProperty(
name="AWS-AWSManagedRulesATPRuleSet",
priority=6,
override_action=wafv2.CfnWebACL.OverrideActionProperty(none={}),
statement=wafv2.CfnWebACL.StatementProperty(
managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
name="AWSManagedRulesATPRuleSet",
vendor_name="AWS",
managed_rule_group_configs=[
wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
login_path=aws_account_takeover_prevention["login_path"], # type: ignore
),
wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
password_field=wafv2.CfnWebACL.FieldIdentifierProperty(
identifier=aws_account_takeover_prevention["password_field"] # type: ignore
),
),
wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
payload_type="FORM_ENCODED",
),
wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
username_field=wafv2.CfnWebACL.FieldIdentifierProperty(
identifier=aws_account_takeover_prevention["username_field"] # type: ignore
),
),
],
)
),
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True,
metric_name="AWS-AWSManagedRulesATPRuleSet",
sampled_requests_enabled=True,
),
)
waf_rules.append(aws_account_takeover_prevention_rule)
return wafv2.CfnWebACL(
self,
"WAF ACL",
default_action=wafv2.CfnWebACL.DefaultActionProperty(allow={}),
scope=waf_scope,
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
cloud_watch_metrics_enabled=True, metric_name="web-acl", sampled_requests_enabled=True
),
name=name,
rules=waf_rules,
)
def web_acl_association(self, resource_arn, web_acl_arn: str) -> wafv2.CfnWebACLAssociation:
"""Associate AWS Resource with WAF.
:param resource_arn: The ARN of resource that will be protected by WAF
:param web_acl_arn: The WEB Application Access Control List ARN
:return: wafv2.CfnWebACLAssociation
"""
return wafv2.CfnWebACLAssociation(self, "ACLAssociation", resource_arn=resource_arn, web_acl_arn=web_acl_arn)
def web_acl_log(self, log_group_name: str) -> logs.LogGroup:
"""Create CloudWatch log group and associate it with WAF.
:param log_group_name: The name of log group
:return: CDK CloudWatch logs.LogGroup
"""
return logs.LogGroup(
self,
id="web_acl_log_group",
log_group_name=log_group_name,
retention=logs.RetentionDays.ONE_WEEK,
removal_policy=cdk.RemovalPolicy.DESTROY,
)
def web_acl_log_config(self, web_acl_arn: str, log_group: logs.LogGroup) -> wafv2.CfnLoggingConfiguration:
"""Configure provided log group as a target for WAF log destination.
:param web_acl_arn: The WEB Application Access Control List ARN
:param log_group: The CDK construct of a CloudWatch log group
:return: AWS CDK wafv2.CfnLoggingConfiguration
"""
return wafv2.CfnLoggingConfiguration(
self,
id="web_acl_cfn_log_configuration",
log_destination_configs=[
cdk.Stack.of(self).format_arn(
arn_format=cdk.ArnFormat.COLON_RESOURCE_NAME,
service="logs",
resource="log-group",
resource_name=log_group.log_group_name,
)
],
resource_arn=web_acl_arn,
)
우리는 그것으로부터 무엇을 얻을 수 있습니까?
간단히 말해서 AWS 관리형 규칙 5개와 사용자 지정 속도 제한 1개
사용 예:
alb_wafv2_construct = WAFv2(self, construct_id="wafv2_construct")
alb_wafv2_acl = alb_wafv2_construct.web_acl(
name=f"{standard_prefix}-wafv2",
rate_value=500,
aws_common_rule=True,
aws_sqli_rule=True,
aws_anony_list=True,
aws_bad_inputs_rule=True,
aws_account_takeover_prevention={
"login_path": "/important_page/login",
"payload_type": "FORM_ENCODED",
"password_field": "PasswordField",
"username_field": "LoginField",
},
)
alb_wafv2_construct.web_acl_association(resource_arn=alb.load_balancer_arn, web_acl_arn=alb_wafv2_acl.attr_arn)
alb_wafv2_log_group = alb_wafv2_construct.web_acl_log(log_group_name=f"aws-waf-logs-{standard_prefix}-wafv2")
alb_wafv2_construct.web_acl_log_config(log_group=alb_wafv2_log_group, web_acl_arn=alb_wafv2_acl.attr_arn)
그리고 ALB에 연결된 WAF ACL을 사용하여 좋은 출발점을 갖게 됩니다.
Reference
이 문제에 관하여(CDK를 사용하는 AWS WAF 간단한 방법, L2?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/airmonitor/aws-waf-with-cdk-simple-way-l2-58ji텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)