-
-
Save matheushent/1c5a02bac6397209f2fe41c0ab3567a3 to your computer and use it in GitHub Desktop.
#CDK python WAF with CloudFront and regex and ip set rules (v1.102.0 of CDK and above) | |
from aws_cdk import ( | |
core as cdk, | |
aws_cloudfront as cloudfront, | |
aws_cloudfront_origins as cloudfront_origins, | |
aws_s3 as s3, | |
aws_certificatemanager as acm, | |
aws_route53 as route53, | |
aws_wafv2 as wafv2, | |
) | |
import json | |
import jsii | |
# this is needed to fix a bug in CDK | |
@jsii.implements(wafv2.CfnRuleGroup.IPSetReferenceStatementProperty) | |
class IPSetReferenceStatement: | |
@property | |
def arn(self): | |
return self._arn | |
@arn.setter | |
def arn(self, value): | |
self._arn = value | |
class CloudfrontStack(cdk.Stack): | |
def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None: | |
super().__init__(scope, construct_id, **kwargs) | |
############################################################################## | |
# Create the WAF regex pattern and IP sets | |
############################################################################## | |
ip_set_v4 = wafv2.CfnIPSet( | |
self, | |
"IPSetv4", | |
addresses=[ | |
"1.2.3.4/32", | |
"5.6.7.8/32", | |
], | |
ip_address_version="IPV4", | |
scope="CLOUDFRONT", | |
) | |
#note we use the class declared above to get around a bug in CDK | |
ip_ref_statement_v4 = IPSetReferenceStatement() | |
ip_ref_statement_v4.arn = ip_set_v4.attr_arn | |
regex_pattern_set = wafv2.CfnRegexPatternSet( | |
self, | |
"RegexPatternSet", | |
regular_expression_list=["^.*(Mozilla).*$"], | |
scope="CLOUDFRONT", | |
description="Checks user-agent for signatures that match devices", | |
name="device-detector", | |
) | |
regex_statement = ( | |
wafv2.CfnWebACL.RegexPatternSetReferenceStatementProperty( | |
arn=regex_pattern_set.attr_arn, | |
field_to_match=wafv2.CfnWebACL.FieldToMatchProperty( | |
single_header={"Name": "User-Agent"} | |
), | |
text_transformations=[ | |
wafv2.CfnWebACL.TextTransformationProperty(priority=0, type="NONE") | |
], | |
) | |
) | |
############################################################################## | |
# Create the WAF | |
############################################################################## | |
waf = wafv2.CfnWebACL( | |
self, | |
"CloudFrontWebACL", | |
#################################################################################### | |
# Set this to allow|block to enable/prevent access to requests not matching a rule | |
#################################################################################### | |
default_action=wafv2.CfnWebACL.DefaultActionProperty(block={}), | |
scope="CLOUDFRONT", | |
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty( | |
cloud_watch_metrics_enabled=True, | |
metric_name="WAF", | |
sampled_requests_enabled=True, | |
), | |
rules=[ | |
#blocks any user agents NOT matching the regex | |
wafv2.CfnWebACL.RuleProperty( | |
name="Permitted-User-Agents", | |
priority=0, | |
action=wafv2.CfnWebACL.RuleActionProperty(block={}), | |
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty( | |
sampled_requests_enabled=True, | |
cloud_watch_metrics_enabled=True, | |
metric_name="allow-permitted-devices", | |
), | |
statement=wafv2.CfnWebACL.StatementProperty( | |
not_statement=wafv2.CfnWebACL.NotStatementProperty( | |
statement=wafv2.CfnWebACL.StatementProperty( | |
regex_pattern_set_reference_statement=regex_statement | |
) | |
) | |
), | |
), | |
wafv2.CfnWebACL.RuleProperty( | |
name="Permitted-IPs", | |
priority=1, | |
action=wafv2.CfnWebACL.RuleActionProperty(allow={}), | |
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty( | |
sampled_requests_enabled=True, | |
cloud_watch_metrics_enabled=True, | |
metric_name="allow-permitted-ips", | |
), | |
statement=wafv2.CfnWebACL.StatementProperty( | |
ip_set_reference_statement=ip_ref_statement_v4 | |
), | |
), | |
wafv2.CfnWebACL.RuleProperty( | |
name="AWS-AWSManagedRulesCommonRuleSet", | |
priority=3, | |
statement=wafv2.CfnWebACL.StatementProperty( | |
managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty( | |
vendor_name="AWS", name="AWSManagedRulesCommonRuleSet" | |
) | |
), | |
override_action=wafv2.CfnWebACL.OverrideActionProperty(none={}), | |
visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty( | |
sampled_requests_enabled=True, | |
cloud_watch_metrics_enabled=True, | |
metric_name="AWS-AWSManagedRulesCommonRuleSet", | |
), | |
), | |
], | |
) | |
############################################################################## | |
# Create the source bucket | |
############################################################################## | |
s3_bucket_source = s3.Bucket( | |
self, | |
"DeploymentBucket", | |
encryption=s3.BucketEncryption.S3_MANAGED, | |
block_public_access=s3.BlockPublicAccess.BLOCK_ALL, | |
removal_policy=cdk.RemovalPolicy.DESTROY, | |
server_access_logs_bucket=s3.Bucket(self, "LogsBucket"), | |
) | |
############################################################################## | |
# Create the OAI | |
############################################################################## | |
oai = cloudfront.OriginAccessIdentity( | |
self, "OAI", comment="Connects CF with S3" | |
) | |
s3_bucket_source.grant_read(oai) | |
############################################################################## | |
# Create an ACM certificate using DNS validation | |
############################################################################## | |
hosted_zone = route53.HostedZone.from_hosted_zone_attributes( | |
self, "MyZone", zone_name=<cloudfront_hostname>, hosted_zone_id=<hosted_zone_id> | |
) | |
certificate = acm.Certificate( | |
self, | |
"Certificate", | |
domain_name=<"www." + cloudfront_hostname>, | |
validation=acm.CertificateValidation.from_dns(hosted_zone=hosted_zone), | |
validation_method=acm.ValidationMethod.DNS, | |
) | |
############################################################################## | |
# Create the Distribution | |
############################################################################## | |
distribution = cloudfront.Distribution( | |
self, | |
"CloudFrontDistribution", | |
web_acl_id=waf.attr_arn, | |
geo_restriction=cloudfront.GeoRestriction.whitelist("AU", "NZ"), | |
certificate=certificate, | |
minimum_protocol_version=cloudfront.SecurityPolicyProtocol.TLS_V1_2_2018, | |
enable_logging=True, | |
default_behavior=cloudfront.BehaviorOptions( | |
allowed_methods=cloudfront.AllowedMethods.ALLOW_ALL, | |
origin=cloudfront_origins.S3Origin( | |
bucket=s3_bucket_source, | |
origin_access_identity=oai, | |
origin_path="/", | |
), | |
viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, | |
), | |
default_root_object="index.html", | |
domain_names=[parameters.env + "." + cloudfront_hostname], | |
error_responses=[ | |
cloudfront.ErrorResponse( | |
http_status=404, | |
response_page_path="/index.html", | |
ttl=cdk.Duration.seconds(amount=0), | |
response_http_status=200, | |
) | |
], | |
) |
hi bro, i clone this code but i don't work at, IPSetReferenceStatementProperty this is the exception " raise JSIIError(resp.error) from JavaScriptError(resp.stack) jsii.errors.JSIIError: Resolution error: Supplied properties not correct for "CfnWebACLProps" rules: element 12: supplied properties not correct for "RuleProperty" statement: supplied properties not correct for "StatementProperty" ipSetReferenceStatement: supplied properties not correct for "IPSetReferenceStatementProperty" arn: required but missing."
yo bro. I tested with CDK v1. Make sure you have both the packages and the CLI installed with version 1.
oh yeb, i just have know cdk V2 is fixed this Bug get ARN from CfnIpSet so i code like document aws and it worked. thank bro.
Nice man, glad it worked for ya.
hi bro, i clone this code but i don't work at, IPSetReferenceStatementProperty this is the exception " raise JSIIError(resp.error) from JavaScriptError(resp.stack)
jsii.errors.JSIIError: Resolution error: Supplied properties not correct for "CfnWebACLProps"
rules: element 12: supplied properties not correct for "RuleProperty"
statement: supplied properties not correct for "StatementProperty"
ipSetReferenceStatement: supplied properties not correct for "IPSetReferenceStatementProperty"
arn: required but missing."