Ejemplo n.º 1
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        prj_name = self.node.try_get_context("project_name")
        env_name = self.node.try_get_context("env")

        basic_rule = waf.CfnWebACL.RuleProperty(
            name='AWSManagedCommonRue',
            priority=0,
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesCommonRuleSet', vendor_name='AWS')),
            override_action=waf.CfnWebACL.OverrideActionProperty(count={}),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='AWSManagedCommonRule',
                sampled_requests_enabled=True))

        web_acl = waf.CfnWebACL(
            self,
            'web-acl-id',
            default_action=waf.CfnWebACL.DefaultActionProperty(allow={}),
            scope='CLOUDFRONT',
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name=prj_name + '-' + env_name,
                sampled_requests_enabled=True),
            name=prj_name + '-' + env_name + 'webacl',
            rules=[basic_rule])

        ssm.StringParameter(self,
                            'web-id-ssm',
                            parameter_name='/' + env_name + '/webacl-id',
                            string_value=web_acl.attr_id)
Ejemplo n.º 2
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        web_acl = wafv2.CfnWebACL(
            scope_=self,
            id='WebAcl',
            default_action=wafv2.CfnWebACL.DefaultActionProperty(allow={}),
            scope='REGIONAL',
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                sampled_requests_enabled=True,
                metric_name='testwafmetric',
            ),
            name='test-web-acl',
            rules=[{
                'name': 'AWS-AWSManagedRulesCommonRuleSet',
                'priority': 0,
                'statement': {
                    'managedRuleGroupStatement': {
                        'vendorName': 'AWS',
                        'name': 'AWSManagedRulesCommonRuleSet'
                    }
                },
                'overrideAction': {
                    'none': {}
                },
                'visibilityConfig': {
                    'sampledRequestsEnabled': True,
                    'cloudWatchMetricsEnabled': True,
                    'metricName': "AWS-AWSManagedRulesCommonRuleSet"
                }
            }, {
                'name': 'AWS-AWSManagedRulesAmazonIpReputationList',
                'priority': 1,
                'statement': {
                    'managedRuleGroupStatement': {
                        'vendorName': 'AWS',
                        'name': 'AWSManagedRulesAmazonIpReputationList'
                    }
                },
                'overrideAction': {
                    'count': {}
                },
                'visibilityConfig': {
                    'sampledRequestsEnabled': True,
                    'cloudWatchMetricsEnabled': True,
                    'metricName': "AWS-AWSManagedRulesAmazonIpReputationList"
                }
            }])
Ejemplo n.º 3
0
    def __init__(self, app: core.App, id: str) -> None:
        super().__init__(app, id)

        vpc = ec2.Vpc(self, "VPC")

        data = open("./httpd.sh", "rb").read()
        httpd = ec2.UserData.for_linux()
        httpd.add_commands(str(data, 'utf-8'))

        asg = autoscaling.AutoScalingGroup(
            self,
            "ASG",
            vpc=vpc,
            instance_type=ec2.InstanceType.of(
                ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO
            ),
            machine_image=ec2.AmazonLinuxImage(generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2),
            user_data=httpd,
        )

        lb = elbv2.ApplicationLoadBalancer(
            self, "LB",
            vpc=vpc,
            internet_facing=True)

        listener = lb.add_listener("Listener", port=80)
        listener.add_targets("Target", port=80, targets=[asg])
        listener.connections.allow_default_port_from_any_ipv4("Open to the world")

        asg.scale_on_request_count("AModestLoad", target_requests_per_second=1)
        core.CfnOutput(self, "LoadBalancer", export_name="LoadBalancer", value=lb.load_balancer_dns_name)

        # === #
        # WAF #
        # === #

        # TODO #10 apply the web_acl to a resource
        # no method to apply the web_acl to a resource in version 1.75.0
        web_acl = wafv2.CfnWebACL(
            scope_=self,
            id="waf",
            default_action=wafv2.CfnWebACL.DefaultActionProperty(),
            scope="REGIONAL",
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name="waf-web-acl",
                sampled_requests_enabled=True
            )
        )
Ejemplo n.º 4
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        ##
        ## List available Managed Rule Groups using AWS CLI
        ## aws wafv2 list-available-managed-rule-groups --scope REGIONAL
        ##
        managed_rules = [{
            "name": "AWSManagedRulesCommonRuleSet",
            "priority": 10,
            "override_action": "none",
            "excluded_rules": [],
        }, {
            "name": "AWSManagedRulesAmazonIpReputationList",
            "priority": 20,
            "override_action": "none",
            "excluded_rules": [],
        }, {
            "name": "AWSManagedRulesKnownBadInputsRuleSet",
            "priority": 30,
            "override_action": "none",
            "excluded_rules": [],
        }, {
            "name": "AWSManagedRulesSQLiRuleSet",
            "priority": 40,
            "override_action": "none",
            "excluded_rules": [],
        }, {
            "name": "AWSManagedRulesLinuxRuleSet",
            "priority": 50,
            "override_action": "none",
            "excluded_rules": [],
        }, {
            "name": "AWSManagedRulesUnixRuleSet",
            "priority": 60,
            "override_action": "none",
            "excluded_rules": [],
        }]

        #############################################################
        ##
        ## WAF - Regional, for use in Load Balancers
        ##
        #############################################################

        wafacl = wafv2.CfnWebACL(
            self,
            id="WAF",
            default_action=wafv2.CfnWebACL.DefaultActionProperty(allow={},
                                                                 block=None),
            ##
            ## The scope of this Web ACL.
            ## Valid options: CLOUDFRONT, REGIONAL.
            ## For CLOUDFRONT, you must create your WAFv2 resources
            ## in the US East (N. Virginia) Region, us-east-1
            ## https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafv2-webacl.html#cfn-wafv2-webacl-scope
            ##
            scope="REGIONAL",
            ##
            ## Defines and enables Amazon CloudWatch metrics and web request sample collection.
            ##
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name="waf-regional",
                sampled_requests_enabled=True),
            description="WAFv2 ACL for Regional",
            name="waf-regional",
            rules=self.make_rules(managed_rules),
        )  ## wafv2.CfnWebACL

        core.Tags.of(wafacl).add("Name", "waf-regional", priority=300)
        core.Tags.of(wafacl).add("Purpose", "WAF for Regional", priority=300)
        core.Tags.of(wafacl).add("CreatedBy", "Cloudformation", priority=300)

        core.CfnOutput(self,
                       "WafAclArn",
                       export_name="WafRegionalStack:WafAclRegionalArn",
                       value=wafacl.attr_arn)
Ejemplo n.º 5
0
    def __init__(
            self,
            scope: core.Construct,
            id: str,
            stack_log_level: str,
            secure_api_stage_arn: str,
            rps_limit: str,
            ** kwargs
    ) -> None:
        super().__init__(scope, id, **kwargs)

        # Your Code):
        # Let us create a Rate Based Rule
        web_acl = _wafv2.CfnWebACL(
            self,
            f"apiSentryAcl-{id}",
            default_action=_wafv2.CfnWebACL.DefaultActionProperty(allow={}),
            scope="REGIONAL",
            visibility_config=_wafv2.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name=f"apiSentryAcl_metrics",
                sampled_requests_enabled=True
            ),
            name=f"apiSentryAcl-{id}",
            description=f"{GlobalArgs.OWNER}: Protect API with Web Application Firewall - Rate Based Rules",
            rules=[]
        )

        # Retrieve Cognito App Client Secret and Add to Secrets Manager
        waf_rule_creator = WafRateRuleCreatorStack(
            self,
            "wafRuleCreator",
            web_acl_name=web_acl.name,
            web_acl_id=web_acl.attr_id,
            web_acl_scope=web_acl.scope,
            rps_limit=rps_limit
        )

        # Export Value
        self.waf_rule_creator_status = waf_rule_creator.response

        # Associate WebAcl to API Gateway
        add_waf_to_resource = _wafv2.CfnWebACLAssociation(
            self,
            id="addWafToApiGw",
            resource_arn=secure_api_stage_arn,
            web_acl_arn=web_acl.attr_arn
        )

        add_waf_to_resource.node.add_dependency(waf_rule_creator)

        # Outputs
        output_0 = core.CfnOutput(
            self,
            "AutomationFrom",
            value=f"{GlobalArgs.SOURCE_INFO}",
            description="To know more about this automation stack, check out our github page."
        )

        output_1 = core.CfnOutput(
            self,
            "WafArn",
            value=f"{web_acl.attr_arn}",
            description="The Web ACL to secure our Api"
        )
        output_2 = core.CfnOutput(
            self,
            "RateRuleCreatorStatus",
            value=f"{self.waf_rule_creator_status}",
            description="Waf Rate Rule Creator Status"
        )
Ejemplo n.º 6
0
    def __init__(self, scope: core.Construct, id: str, target_arn,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        waf_rules = []

        # 1, AWS general rules
        aws_managed_rules = waf.CfnWebACL.RuleProperty(
            name='AWS-AWSManagedRulesCommonRuleSet',
            priority=1,
            override_action=waf.CfnWebACL.OverrideActionProperty(none={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesCommonRuleSet',
                    vendor_name='AWS',
                    excluded_rules=[
                        waf.CfnWebACL.ExcludedRuleProperty(
                            name='SizeRestrictions_BODY')
                    ])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='awsCommonRules',
                sampled_requests_enabled=True,
            ),
        )
        waf_rules.append(aws_managed_rules)

        # 2, AWS AnonIPAddress
        aws_anoniplist = waf.CfnWebACL.RuleProperty(
            name='awsAnonymousIP',
            priority=2,
            override_action=waf.CfnWebACL.OverrideActionProperty(none={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesAnonymousIpList',
                    vendor_name='AWS',
                    excluded_rules=[])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='awsAnonymous',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(aws_anoniplist)

        # 3 AWS ip reputation List
        aws_ip_rep_list = waf.CfnWebACL.RuleProperty(
            name='aws_Ipreputation',
            priority=3,
            override_action=waf.CfnWebACL.OverrideActionProperty(none={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesAmazonIpReputationList',
                    vendor_name='AWS',
                    excluded_rules=[])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='aws_reputation',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(aws_ip_rep_list)

        # 4 GeoBlock NZ from accessing gateway
        geoblock_rule = waf.CfnWebACL.RuleProperty(
            name='geoblocking_rule',
            priority=4,
            action=waf.CfnWebACL.RuleActionProperty(block={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                geo_match_statement=waf.CfnWebACL.GeoMatchStatementProperty(
                    country_codes=['NZ'], )),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='geoblock',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(geoblock_rule)

        # Create the Waf ACL
        WebACL = waf.CfnWebACL(
            self,
            'WebACL',
            default_action=waf.CfnWebACL.DefaultActionProperty(allow={}),
            scope="REGIONAL",  # vs 'CLOUDFRONT'
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='webACL',
                sampled_requests_enabled=True),
            name='HelloWorldACL',
            rules=waf_rules)

        # Associate it with the resource provided.

        waf.CfnWebACLAssociation(self,
                                 'WAFAssnAPI',
                                 web_acl_arn=WebACL.attr_arn,
                                 resource_arn=target_arn)
Ejemplo n.º 7
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        API_ARN = self.node.try_get_context("api_arn")
        RATE = self.node.try_get_context("rate")

        if not API_ARN or not RATE:
            logger.error(
                f"Required context variables for {id} were not provided!")
        else:
            # Create the WAF IPSets
            doslist = wafv2.CfnIPSet(
                self,
                "Ext06DosIpSet",
                addresses=[],
                ip_address_version="IPV4",
                scope="REGIONAL",
                name="Ext06DosIpSet",
            )

            suslist = wafv2.CfnIPSet(
                self,
                "Ext06SusIpSet",
                addresses=[],
                ip_address_version="IPV4",
                scope="REGIONAL",
                name="Ext06SusIpSet",
            )

            # Create a WAF
            waf = wafv2.CfnWebACL(
                self,
                id="Ext06_WAF",
                name="Ext06-WAF",
                default_action=wafv2.CfnWebACL.DefaultActionProperty(allow={}),
                scope="REGIONAL",
                visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                    cloud_watch_metrics_enabled=True,
                    metric_name="EXT06_WAF",
                    sampled_requests_enabled=True),
                rules=[],
            )

            # Create Susunban lambda
            lambda_dir_path = os.path.join(os.getcwd(), "ir_cdk_stacks",
                                           "ext_06")
            susunban_lambda = _lambda.Function(
                self,
                "Ext06ResponseSusUnbanFunction",
                runtime=_lambda.Runtime.PYTHON_3_8,
                handler="susunban_lambda.lambda_handler",
                code=_lambda.Code.from_asset(lambda_dir_path),
                environment={
                    "ipset_id": suslist.attr_id,
                    "ipset_name": suslist.name,
                    "ipset_scope": suslist.scope,
                })
            # Assign WAF permissions to lambda
            susunban_lambda.add_to_role_policy(
                iam.PolicyStatement(
                    actions=["wafv2:GetIPSet", "wafv2:UpdateIPSet"],
                    effect=iam.Effect.ALLOW,
                    resources=[suslist.attr_arn],
                ))

            # Create Dosunban lambda
            lambda_dir_path = os.path.join(os.getcwd(), "ir_cdk_stacks",
                                           "ext_06")
            dosunban_lambda = _lambda.Function(
                self,
                "Ext06ResponseDosUnbanFunction",
                runtime=_lambda.Runtime.PYTHON_3_8,
                handler="dosunban_lambda.lambda_handler",
                code=_lambda.Code.from_asset(lambda_dir_path),
                environment={
                    "ipset_id": doslist.attr_id,
                    "ipset_name": doslist.name,
                    "ipset_scope": doslist.scope,
                })
            # Assign WAF permissions to lambda
            dosunban_lambda.add_to_role_policy(
                iam.PolicyStatement(
                    actions=["wafv2:GetIPSet", "wafv2:UpdateIPSet"],
                    effect=iam.Effect.ALLOW,
                    resources=[doslist.attr_arn],
                ))

            # Create dos stepfunction
            # Define a second state machine to unban the blacklisted IP after 1 hour
            doswait_step = sfn.Wait(
                self,
                "Ext06ResponseStepDosWait",
                time=sfn.WaitTime.duration(core.Duration.hours(1)),
            )
            suswait_step = sfn.Wait(
                self,
                "Ext06ResponseStepSusWait",
                time=sfn.WaitTime.duration(core.Duration.hours(1)),
            )
            dosunban_step = sfn.Task(
                self,
                "Ext06ResponseStepDosUnban",
                task=tasks.RunLambdaTask(
                    dosunban_lambda,
                    integration_pattern=sfn.ServiceIntegrationPattern.
                    FIRE_AND_FORGET,
                    payload={"Input.$": "$"},
                ),
            )
            susunban_step = sfn.Task(
                self,
                "Ext06ResponseStepSosUnban",
                task=tasks.RunLambdaTask(
                    susunban_lambda,
                    integration_pattern=sfn.ServiceIntegrationPattern.
                    FIRE_AND_FORGET,
                    payload={"Input.$": "$"},
                ),
            )
            dos_statemachine = sfn.StateMachine(
                self,
                "Ext06ResponseDosUnbanStateMachine",
                definition=doswait_step.next(dosunban_step),
                timeout=core.Duration.hours(1.5),
            )

            sus_statemachine = sfn.StateMachine(
                self,
                "Ext06ResponseSusUnbanStateMachine",
                definition=suswait_step.next(susunban_step),
                timeout=core.Duration.hours(1.5),
            )
            # Create lambda function
            lambda_func = _lambda.Function(
                self,
                "Ext06ResponseFunction",
                runtime=_lambda.Runtime.PYTHON_3_8,
                handler="response_lambda.lambda_handler",
                code=_lambda.Code.from_asset(lambda_dir_path),
                environment={
                    "suslist_id": suslist.attr_id,
                    "suslist_name": suslist.name,
                    "suslist_scope": suslist.scope,
                    "doslist_id": doslist.attr_id,
                    "doslist_name": doslist.name,
                    "doslist_scope": doslist.scope,
                    "dos_arn": dos_statemachine.state_machine_arn,
                    "sus_arn": sus_statemachine.state_machine_arn,
                },
            )

            kinesis_log = s3.Bucket(
                self,
                id='dos_logs',
                access_control=s3.BucketAccessControl.PUBLIC_READ_WRITE,
            )

            # Assign permissions to response lambda
            lambda_func.add_to_role_policy(
                iam.PolicyStatement(
                    actions=[
                        "wafv2:GetIPSet",
                        "wafv2:UpdateIPSet",
                        "states:StartExecution",
                        "s3:GetObject",
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[
                        doslist.attr_arn, suslist.attr_arn,
                        sus_statemachine.state_machine_arn,
                        dos_statemachine.state_machine_arn,
                        kinesis_log.bucket_arn, kinesis_log.bucket_arn,
                        kinesis_log.bucket_arn + "/*"
                    ],
                ))

            # Create an IAM role for the steram
            stream_role = iam.Role(
                self,
                id="waf-kinesis-log-role",
                assumed_by=iam.ServicePrincipal(
                    service="firehose.amazonaws.com", ),
            )

            stream_permissions = iam.Policy(
                self,
                id="Ext-06-kinesis-permissions",
                statements=[
                    iam.PolicyStatement(
                        actions=[
                            "s3:AbortMultipartUpload",
                            "s3:GetBucketLocation",
                            "s3:GetObject",
                            "s3:ListBucket",
                            "s3:ListBucketMultipartUploads",
                            "s3:PutObject",
                        ],
                        effect=iam.Effect.ALLOW,
                        resources=[
                            kinesis_log.bucket_arn,
                            kinesis_log.bucket_arn + "/*"
                        ],
                    )
                ])

            stream_role.attach_inline_policy(stream_permissions)

            log_stream = firehose.CfnDeliveryStream(
                self,
                id="aws-waf-logs-ext06",
                delivery_stream_type="DirectPut",
                delivery_stream_name="aws-waf-logs-ext06",
                s3_destination_configuration=firehose.CfnDeliveryStream.
                S3DestinationConfigurationProperty(
                    bucket_arn=kinesis_log.bucket_arn,
                    buffering_hints=firehose.CfnDeliveryStream.
                    BufferingHintsProperty(interval_in_seconds=300,
                                           size_in_m_bs=5),
                    compression_format="UNCOMPRESSED",
                    role_arn=stream_role.role_arn),
            )
            kinesis_log.add_event_notification(
                s3.EventType.OBJECT_CREATED,
                dest=s3_notifications.LambdaDestination(lambda_func))
            utc_time = datetime.now(tz=timezone.utc)
            utc_time = utc_time + timedelta(minutes=5)
            cron_string = "cron(" + str(utc_time.minute) + " " + str(
                utc_time.hour) + " " + str(utc_time.day) + " " + str(
                    utc_time.month) + " ? " + str(utc_time.year) + ")"
            trigger = events.Rule(
                self,
                id="ext-06 setup",
                rule_name="Ext06-trigger",
                schedule=events.Schedule.expression(cron_string))

            setup_dir_path = os.path.join(os.getcwd(), "ir_cdk_stacks",
                                          "ext_06")
            setup_func = _lambda.Function(
                self,
                id="Ext06Setup",
                runtime=_lambda.Runtime.PYTHON_3_8,
                handler="setup.lambda_handler",
                code=_lambda.Code.from_asset(setup_dir_path),
                environment={
                    "waf_arn": waf.attr_arn,
                    "waf_id": waf.attr_id,
                    "waf_scope": waf.scope,
                    "waf_name": waf.name,
                    "firehose_arn": log_stream.attr_arn,
                    "rule_name": "Ext06-trigger",
                    "doslist_arn": doslist.attr_arn,
                    "rate": str(RATE),
                },
            )

            # Assign permissions to setup lambda
            setup_func.add_to_role_policy(
                iam.PolicyStatement(
                    actions=[
                        "wafv2:PutLoggingConfiguration", "wafv2:GetWebACL",
                        "wafv2:UpdateWebACL"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[waf.attr_arn, doslist.attr_arn],
                ))

            setup = targets.LambdaFunction(handler=setup_func, )

            setup.bind(rule=trigger)
            trigger.add_target(target=setup)

            wafv2.CfnWebACLAssociation(
                self,
                id="API gateway association",
                resource_arn=API_ARN,
                web_acl_arn=waf.attr_arn,
            )
Ejemplo n.º 8
0
    def __init__(self, scope: core.Construct, id: str, env, target_arn,
                 **kwargs) -> None:
        super().__init__(scope, id, env=env, **kwargs)

        waf_rules = list()
        """ 1. Reputation List """
        aws_ip_rep_list = waf.CfnWebACL.RuleProperty(
            name='WafIpreputation',
            priority=1,
            override_action=waf.CfnWebACL.OverrideActionProperty(count={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesAmazonIpReputationList',
                    vendor_name='AWS',
                    excluded_rules=[])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='aws_reputation',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(aws_ip_rep_list)
        """ 2. AnonymousIpList """
        aws_anony_list = waf.CfnWebACL.RuleProperty(
            name='WafAnony',
            priority=2,
            override_action=waf.CfnWebACL.OverrideActionProperty(count={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesAnonymousIpList',
                    vendor_name='AWS',
                    excluded_rules=[])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='aws_anony',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(aws_anony_list)
        """ 3. CommonRule """
        aws_common_rule = waf.CfnWebACL.RuleProperty(
            name='WafCommonRule',
            priority=3,
            override_action=waf.CfnWebACL.OverrideActionProperty(count={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesCommonRuleSet',
                    vendor_name='AWS',
                    excluded_rules=[])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='aws_common',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(aws_common_rule)
        """ 4. PHP Rule """
        aws_php_rule = waf.CfnWebACL.RuleProperty(
            name='WafPHPRule',
            priority=4,
            override_action=waf.CfnWebACL.OverrideActionProperty(count={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesPHPRuleSet',
                    vendor_name='AWS',
                    excluded_rules=[])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='aws_php',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(aws_php_rule)
        """ 5. Linux Rule """
        aws_linux_rule = waf.CfnWebACL.RuleProperty(
            name='WafLinuxRule',
            priority=5,
            override_action=waf.CfnWebACL.OverrideActionProperty(count={}),
            statement=waf.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=waf.CfnWebACL.
                ManagedRuleGroupStatementProperty(
                    name='AWSManagedRulesLinuxRuleSet',
                    vendor_name='AWS',
                    excluded_rules=[])),
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='aws_linux',
                sampled_requests_enabled=True,
            ))
        waf_rules.append(aws_linux_rule)
        """ DefaultAction: Action of AWS WAF to perform when a web request doesn't match any of the rules in the WebACL. """
        web_acl = waf.CfnWebACL(
            self,
            'WebACL',
            default_action=waf.CfnWebACL.DefaultActionProperty(allow={}),
            scope="REGIONAL",  # vs 'CLOUDFRONT'
            visibility_config=waf.CfnWebACL.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='webACL',
                sampled_requests_enabled=True),
            name=f'prod-acl',
            rules=waf_rules)
        """ Associate it with the resource provided. """
        waf.CfnWebACLAssociation(self,
                                 'WAFACLAssociateALB',
                                 web_acl_arn=web_acl.attr_arn,
                                 resource_arn=target_arn)
Ejemplo n.º 9
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Demo app with an ALB, which only allows traffic from the specified set of CIDRs
        app = DemoApp(self, 'DemoApp', allow_from_cidrs=['0.0.0.0/0'])

        ###
        # Example of adding a Web ACL with a custom rule to the load balancer of a demo app
        ###
        acl = waf.CfnWebACL

        custom_rule = acl.RuleProperty(
            name='BlockQueriesContainingSubString',
            priority=1,
            action=acl.RuleActionProperty(block={}),
            statement=acl.StatementOneProperty(
                byte_match_statement=acl.ByteMatchStatementProperty(
                    search_string='blockme',
                    field_to_match=acl.FieldToMatchProperty(query_string={}),
                    positional_constraint='CONTAINS',
                    text_transformations=[
                        acl.TextTransformationProperty(priority=0,
                                                       type='NONE'),
                    ],
                )),
            visibility_config=acl.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                sampled_requests_enabled=True,
                metric_name='custom_rule',
            ))

        # Check out the following for examples using managed rules (shield advanced)
        # https://web.archive.org/web/20210321152739/https://dev.to/vumdao/using-aws-waf-and-shield-to-protect-ddos-5d03

        # Create the ACL
        web_acl = waf.CfnWebACL(
            self,
            'WebACL',
            default_action=acl.DefaultActionProperty(allow={}),
            scope='REGIONAL',  # or use CLOUDFRONT if protecting a distribution
            visibility_config=acl.VisibilityConfigProperty(
                cloud_watch_metrics_enabled=True,
                metric_name='webACL',
                sampled_requests_enabled=True),
            name=f'test-acl',
            rules=[
                custom_rule,
            ])

        # Associate the ACL with a resource; Here the ALB for the demo app.
        waf.CfnWebACLAssociation(
            self,
            'WafAclAssociationALB',
            web_acl_arn=web_acl.attr_arn,
            resource_arn=app.alb.load_balancer_arn,
        )

        # Link that triggers a block, and another to the AWS Console showing the generated WebACL
        core.CfnOutput(self,
                       'BlockedExampleUrl',
                       value='http://{}/?blockme'.format(
                           app.alb.load_balancer_dns_name))
        core.CfnOutput(
            self,
            'AclConsoleUrl',
            value=
            'https://console.aws.amazon.com/wafv2/homev2/web-acls?region={}'.
            format(core.Stack.of(self).region))
Ejemplo n.º 10
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        API_ARN = self.node.try_get_context("api_arn")
        if not API_ARN:
            logger.error(
                f"Required context variables for {id} were not provided!")
        else:
            # Create XSS rule
            xss_body = wafv2.CfnRuleGroup.StatementOneProperty(
                xss_match_statement=wafv2.CfnRuleGroup.
                XssMatchStatementProperty(
                    field_to_match=BODY,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))
            xss_query_string = wafv2.CfnRuleGroup.StatementOneProperty(
                xss_match_statement=wafv2.CfnRuleGroup.
                XssMatchStatementProperty(
                    field_to_match=QUERY_STRING,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))
            xss_uri = wafv2.CfnRuleGroup.StatementOneProperty(
                xss_match_statement=wafv2.CfnRuleGroup.
                XssMatchStatementProperty(
                    field_to_match=URI_PATH,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))
            xss_header = wafv2.CfnRuleGroup.StatementOneProperty(
                xss_match_statement=wafv2.CfnRuleGroup.
                XssMatchStatementProperty(
                    field_to_match=SINGLE_HEADER,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))

            xss_rule_group = wafv2.CfnRuleGroup(
                self,
                id="XSS",
                capacity=160,
                scope="REGIONAL",
                visibility_config=wafv2.CfnRuleGroup.VisibilityConfigProperty(
                    cloud_watch_metrics_enabled=True,
                    metric_name="xss_attacks",
                    sampled_requests_enabled=False),
                rules=[
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="xss_query_string",
                        priority=1,
                        statement=xss_query_string,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="xss_attacks",
                            sampled_requests_enabled=False),
                    ),
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="xss_body",
                        priority=2,
                        statement=xss_body,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="xss_attacks",
                            sampled_requests_enabled=False)),
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="xss_uri",
                        priority=3,
                        statement=xss_uri,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="xss_attacks",
                            sampled_requests_enabled=False)),
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="xss_header",
                        priority=4,
                        statement=xss_header,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="xss_attacks",
                            sampled_requests_enabled=False),
                    ),
                ],
            )

            # Create the SQLI rule group
            sqli_body = wafv2.CfnRuleGroup.StatementOneProperty(
                sqli_match_statement=wafv2.CfnRuleGroup.
                SqliMatchStatementProperty(
                    field_to_match=BODY,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))
            sqli_query_string = wafv2.CfnRuleGroup.StatementOneProperty(
                sqli_match_statement=wafv2.CfnRuleGroup.
                SqliMatchStatementProperty(
                    field_to_match=QUERY_STRING,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))
            sqli_uri = wafv2.CfnRuleGroup.StatementOneProperty(
                sqli_match_statement=wafv2.CfnRuleGroup.
                SqliMatchStatementProperty(
                    field_to_match=URI_PATH,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))
            sqli_header = wafv2.CfnRuleGroup.StatementOneProperty(
                sqli_match_statement=wafv2.CfnRuleGroup.
                SqliMatchStatementProperty(
                    field_to_match=SINGLE_HEADER,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))

            sqli_rule_group = wafv2.CfnRuleGroup(
                self,
                id="SQLI",
                capacity=80,
                scope="REGIONAL",
                visibility_config=wafv2.CfnRuleGroup.VisibilityConfigProperty(
                    cloud_watch_metrics_enabled=True,
                    metric_name="sqli_attacks",
                    sampled_requests_enabled=False),
                rules=[
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="sqli_query_string",
                        priority=1,
                        statement=sqli_query_string,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="sqli_attacks",
                            sampled_requests_enabled=False),
                    ),
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="sqli_body",
                        priority=2,
                        statement=sqli_body,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="sqli_attacks",
                            sampled_requests_enabled=False)),
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="sqli_uri",
                        priority=3,
                        statement=sqli_uri,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="sqli_attacks",
                            sampled_requests_enabled=False)),
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="sqli_header",
                        priority=4,
                        statement=sqli_header,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="sqli_attacks",
                            sampled_requests_enabled=False),
                    ),
                ],
            )

            # Create the LFI and path traversal sets
            regex_pattern_set = wafv2.CfnRegexPatternSet(
                self,
                id="Ext01LptSet",
                regular_expression_list=[".*\.\./.*", ".*://.*"],
                scope="REGIONAL")
            lpt_query_string = wafv2.CfnRuleGroup.StatementOneProperty(
                regex_pattern_set_reference_statement=wafv2.CfnRuleGroup.
                RegexPatternSetReferenceStatementProperty(
                    arn=regex_pattern_set.attr_arn,
                    field_to_match=QUERY_STRING,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))
            lpt_uri = wafv2.CfnRuleGroup.StatementOneProperty(
                regex_pattern_set_reference_statement=wafv2.CfnRuleGroup.
                RegexPatternSetReferenceStatementProperty(
                    arn=regex_pattern_set.attr_arn,
                    field_to_match=URI_PATH,
                    text_transformations=[NO_TEXT_TRANSFORMATION]))

            lpt_rule_group = wafv2.CfnRuleGroup(
                self,
                id="LPT",
                capacity=50,
                scope="REGIONAL",
                visibility_config=wafv2.CfnRuleGroup.VisibilityConfigProperty(
                    cloud_watch_metrics_enabled=True,
                    metric_name="lpt_attacks",
                    sampled_requests_enabled=False),
                rules=[
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="lpt_query_string",
                        priority=1,
                        statement=lpt_query_string,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="lpt_attacks",
                            sampled_requests_enabled=False),
                    ),
                    wafv2.CfnRuleGroup.RuleProperty(
                        name="lpt_uri",
                        priority=2,
                        statement=lpt_uri,
                        action=wafv2.CfnRuleGroup.RuleActionProperty(block={}),
                        visibility_config=wafv2.CfnRuleGroup.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="lpt_attacks",
                            sampled_requests_enabled=False)),
                ],
            )

            # Create new WAF IPSet
            blacklist = wafv2.CfnIPSet(
                self,
                "Ext01ResponseIpSet",
                addresses=[],
                ip_address_version="IPV4",
                scope="REGIONAL",
                name="Ext01ResponseIpSet",
            )

            # Create reference statements
            xss_ref = wafv2.CfnWebACL.RuleGroupReferenceStatementProperty(
                arn=xss_rule_group.attr_arn)
            sqli_ref = wafv2.CfnWebACL.RuleGroupReferenceStatementProperty(
                arn=sqli_rule_group.attr_arn)
            lpt_ref = wafv2.CfnWebACL.RuleGroupReferenceStatementProperty(
                arn=lpt_rule_group.attr_arn)

            # Create a WAF
            waf = wafv2.CfnWebACL(
                self,
                id="Ext01_WAF",
                name="Ext01-WAF",
                default_action=wafv2.CfnWebACL.DefaultActionProperty(allow={}),
                scope="REGIONAL",
                visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                    cloud_watch_metrics_enabled=True,
                    metric_name="EXT01_WAF",
                    sampled_requests_enabled=True),
                rules=[
                    wafv2.CfnWebACL.RuleProperty(
                        name="SQLI",
                        priority=2,
                        statement=wafv2.CfnWebACL.StatementOneProperty(
                            rule_group_reference_statement=sqli_ref),
                        visibility_config=wafv2.CfnWebACL.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="sqli_requests",
                            sampled_requests_enabled=False),
                        override_action=wafv2.CfnWebACL.OverrideActionProperty(
                            none={}),
                    ),
                    wafv2.CfnWebACL.RuleProperty(
                        name="XSS",
                        priority=3,
                        statement=wafv2.CfnWebACL.StatementOneProperty(
                            rule_group_reference_statement=xss_ref),
                        visibility_config=wafv2.CfnWebACL.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="xss_requests",
                            sampled_requests_enabled=False),
                        override_action=wafv2.CfnWebACL.OverrideActionProperty(
                            none={}),
                    ),
                    wafv2.CfnWebACL.RuleProperty(
                        name="LPT",
                        priority=4,
                        statement=wafv2.CfnWebACL.StatementOneProperty(
                            rule_group_reference_statement=lpt_ref),
                        visibility_config=wafv2.CfnWebACL.
                        VisibilityConfigProperty(
                            cloud_watch_metrics_enabled=False,
                            metric_name="lpt_requests",
                            sampled_requests_enabled=False),
                        override_action=wafv2.CfnWebACL.OverrideActionProperty(
                            none={}),
                    ),
                ],
            )

            # Create unban lambda
            lambda_dir_path = os.path.join(os.getcwd(), "ir_cdk_stacks",
                                           "ext_01")
            unban_lambda = _lambda.Function(
                self,
                "Ext01ResponseUnbanFunction",
                runtime=_lambda.Runtime.PYTHON_3_8,
                handler="unban_lambda.lambda_handler",
                code=_lambda.Code.from_asset(lambda_dir_path),
                environment={
                    "ipset_id": blacklist.attr_id,
                    "ipset_name": blacklist.name,
                    "ipset_scope": blacklist.scope,
                })
            # Assign WAF permissions to lambda
            unban_lambda.add_to_role_policy(
                iam.PolicyStatement(
                    actions=["wafv2:GetIPSet", "wafv2:UpdateIPSet"],
                    effect=iam.Effect.ALLOW,
                    resources=[blacklist.attr_arn],
                ))

            # Create stepfunction
            # Define a second state machine to unban the blacklisted IP after 1 hour
            wait_step = sfn.Wait(
                self,
                "Ext01ResponseStepWait",
                time=sfn.WaitTime.duration(core.Duration.hours(1)),
            )
            unban_step = sfn.Task(
                self,
                "Ext01ResponseStepUnban",
                task=tasks.RunLambdaTask(
                    unban_lambda,
                    integration_pattern=sfn.ServiceIntegrationPattern.
                    FIRE_AND_FORGET,
                    payload={"Input.$": "$"}),
            )
            statemachine = sfn.StateMachine(
                self,
                "Ext01ResponseUnbanStateMachine",
                definition=wait_step.next(unban_step),
                timeout=core.Duration.hours(1.5),
            )

            # Create lambda function
            lambda_func = _lambda.Function(
                self,
                "Ext01ResponseFunction",
                runtime=_lambda.Runtime.PYTHON_3_8,
                handler="response_lambda.lambda_handler",
                code=_lambda.Code.from_asset(lambda_dir_path),
                environment={
                    "ipset_id": blacklist.attr_id,
                    "ipset_name": blacklist.name,
                    "ipset_scope": blacklist.scope,
                    "sfn_arn": statemachine.state_machine_arn,
                },
            )

            kinesis_log = s3.Bucket(
                self,
                id='waf_logs',
                access_control=s3.BucketAccessControl.PUBLIC_READ_WRITE,
            )

            # Assign permissions to response lambda
            lambda_func.add_to_role_policy(
                iam.PolicyStatement(
                    actions=[
                        "wafv2:GetIPSet",
                        "wafv2:UpdateIPSet",
                        "states:StartExecution",
                        "s3:GetObject",
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[
                        blacklist.attr_arn, statemachine.state_machine_arn,
                        kinesis_log.bucket_arn, kinesis_log.bucket_arn,
                        kinesis_log.bucket_arn + "/*"
                    ],
                ))

            # Create an IAM role for the steram
            stream_role = iam.Role(
                self,
                id="waf-kinesis-log-role",
                assumed_by=iam.ServicePrincipal(
                    service="firehose.amazonaws.com", ),
            )

            stream_permissions = iam.Policy(
                self,
                id="Ext-01-kinesis-permissions",
                statements=[
                    iam.PolicyStatement(
                        actions=[
                            "s3:AbortMultipartUpload",
                            "s3:GetBucketLocation",
                            "s3:GetObject",
                            "s3:ListBucket",
                            "s3:ListBucketMultipartUploads",
                            "s3:PutObject",
                        ],
                        effect=iam.Effect.ALLOW,
                        resources=[
                            kinesis_log.bucket_arn,
                            kinesis_log.bucket_arn + "/*"
                        ],
                    )
                ])

            stream_role.attach_inline_policy(stream_permissions)

            log_stream = firehose.CfnDeliveryStream(
                self,
                id="aws-waf-logs-ext01",
                delivery_stream_type="DirectPut",
                delivery_stream_name="aws-waf-logs-ext01",
                s3_destination_configuration=firehose.CfnDeliveryStream.
                S3DestinationConfigurationProperty(
                    bucket_arn=kinesis_log.bucket_arn,
                    buffering_hints=firehose.CfnDeliveryStream.
                    BufferingHintsProperty(interval_in_seconds=120,
                                           size_in_m_bs=5),
                    compression_format="UNCOMPRESSED",
                    role_arn=stream_role.role_arn),
            )
            kinesis_log.add_event_notification(
                s3.EventType.OBJECT_CREATED,
                dest=s3_notifications.LambdaDestination(lambda_func))
            utc_time = datetime.now(tz=timezone.utc)
            utc_time = utc_time + timedelta(minutes=5)
            cron_string = "cron(" + str(utc_time.minute) + " " + str(
                utc_time.hour) + " " + str(utc_time.day) + " " + str(
                    utc_time.month) + " ? " + str(utc_time.year) + ")"
            trigger = events.Rule(
                self,
                id="ext-01 setup",
                rule_name="Ext01-trigger",
                schedule=events.Schedule.expression(cron_string))

            setup_dir_path = os.path.join(os.getcwd(), "ir_cdk_stacks",
                                          "ext_01")
            setup_func = _lambda.Function(
                self,
                id="Ext01Setup",
                runtime=_lambda.Runtime.PYTHON_3_8,
                handler="setup.lambda_handler",
                code=_lambda.Code.from_asset(setup_dir_path),
                environment={
                    "waf_arn": waf.attr_arn,
                    "waf_id": waf.attr_id,
                    "waf_scope": waf.scope,
                    "waf_name": waf.name,
                    "firehose_arn": log_stream.attr_arn,
                    "rule_name": "Ext01-trigger",
                    "blacklist_arn": blacklist.attr_arn,
                },
            )

            # Assign permissions to setup lambda
            setup_func.add_to_role_policy(
                iam.PolicyStatement(
                    actions=[
                        "wafv2:PutLoggingConfiguration", "wafv2:GetWebACL",
                        "wafv2:UpdateWebACL"
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[
                        waf.attr_arn, blacklist.attr_arn,
                        xss_rule_group.attr_arn, sqli_rule_group.attr_arn,
                        lpt_rule_group.attr_arn
                    ],
                ))

            setup = targets.LambdaFunction(handler=setup_func, )

            setup.bind(rule=trigger)
            trigger.add_target(target=setup)

            wafv2.CfnWebACLAssociation(
                self,
                id="API gateway association",
                resource_arn=API_ARN,
                web_acl_arn=waf.attr_arn,
            )