Beispiel #1
0
    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        
        #template = cfn_inc.CfnInclude(self, id='Template', template_file='template.yaml')
        # The code that defines your stack goes here
        bucket_names = 'config-1' + str(core.Aws.ACCOUNT_ID)
        sns_topic = _sns.Topic(self, id='topic-config', topic_name='config-topic')
        sns_topic.add_subscription(subscriptions.EmailSubscription("*****@*****.**"))
        bucket = s3.Bucket(self, id='s3cdkbuckets',bucket_name=bucket_names,versioned=True)
        bucket_arn2 = str(bucket.bucket_arn) + "/AWSLogs/" + str(core.Aws.ACCOUNT_ID) + "/Config/*"
        bucket_policy = bucket.add_to_resource_policy(iam.PolicyStatement(effect=iam.Effect.ALLOW, 
                                                                             resources=[bucket.bucket_arn],
                                                                             actions=["s3:GetBucketAcl"],
                                                                             sid = "AWSConfigBucketPermissionsCheck",
                                                                             principals=[iam.ServicePrincipal("config.amazonaws.com")]
                                                                             ))
        bucket_policy2 = bucket.add_to_resource_policy(iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                                                           resources=[bucket_arn2],
                                                                           actions=["s3:PutObject"],
                                                                           sid = "AWSConfigBucketDelivery",
                                                                           principals=[iam.ServicePrincipal("config.amazonaws.com")],
                                                                           conditions={"StringEquals": {
                                                                               "s3:x-amz-acl": "bucket-owner-full-control"}
                                                                                        }))
        recorder = config.CfnConfigurationRecorder(self,
                id='recorder',
                role_arn='arn:aws:iam::306646308112:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig',
                recording_group=None)
        channel = config.CfnDeliveryChannel(self,
                id='channel',
                s3_bucket_name=bucket.bucket_name,
                sns_topic_arn=sns_topic.topic_arn)
        time.sleep(20)
        srule = config.CfnConfigRule(self,
                id='rule1',
                source=config.CfnConfigRule.SourceProperty(owner="AWS",
                    source_identifier="REQUIRED_TAGS"),  
                input_parameters={"tag1Key":"tagVal"})
        srule2 = config.CfnConfigRule(self, id='rule2',
                 source=config.CfnConfigRule.SourceProperty(owner="AWS",
                    source_identifier="S3_BUCKET_LEVEL_PUBLIC_ACCESS_PROHIBITED"))
        srule3 = config.CfnConfigRule(self, id='rule3',
                 source=config.CfnConfigRule.SourceProperty(owner="AWS",
                    source_identifier="VPC_SG_OPEN_ONLY_TO_AUTHORIZED_PORTS"))
        srule.add_depends_on(recorder)
        srule2.add_depends_on(recorder)
        srule3.add_depends_on(recorder)
        event_rule = _events.Rule(self, id='event_rule', event_pattern = {
           "source": ["aws.config"],
           "detail": {
               "messageType": ["ConfigurationItemChangeNotification"],
               "newEvaluationResult": {
               "compliance_type": ["NON_COMPLIANT"]
    }
  }
})
        event_rule.add_target(targets.SnsTopic(sns_topic))
Beispiel #2
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        ## Config
        #- Create bucket
        #- Create IAM role
        #- Setup Recorder
        #- Setup Delivery Channel: https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_config/CfnDeliveryChannel.html

        cliSts = boto3.client('sts')
        caller = cliSts.get_caller_identity()

        roleConfig = _iam.CfnRole(self, "CustomAWSConfigService",
                               role_name="CustomAWSConfigService",
                               assume_role_policy_document={
                                    "Version": "2012-10-17",
                                    "Statement": [
                                        {
                                        "Effect": "Allow",
                                        "Principal": {
                                            "Service": "config.amazonaws.com"
                                        },
                                        "Action": "sts:AssumeRole"
                                        }
                                    ]
                                    },
                                managed_policy_arns=[
                                    "arn:aws:iam::aws:policy/service-role/AWSConfigRole",
                                    "arn:aws:iam::aws:policy/AmazonS3FullAccess"
                                ])

        bname = "aws-config-custom-{}".format(caller['Account'])
        bucketConfig = _s3.CfnBucket(self, bname, bucket_name=bname)
        bucketConfig.apply_removal_policy(apply_to_update_replace_policy=False)

        rec = _config.CfnConfigurationRecorder(self, "ConfigRec", name="ConfigRec",
                role_arn=roleConfig.attr_arn,
                recording_group=CfnConfigurationRecorder.RecordingGroupProperty(
                    all_supported=True, include_global_resource_types=True        
                ))
        rec.add_depends_on(roleConfig)

        cfgDC = _config.CfnDeliveryChannel(self, 'aws-config',
            s3_bucket_name=bname, 
            config_snapshot_delivery_properties=CfnDeliveryChannel.ConfigSnapshotDeliveryPropertiesProperty(
                delivery_frequency="Twelve_Hours"),
            name='aws-config')
        cfgDC.add_depends_on(bucketConfig)
Beispiel #3
0
    def __init__(self, app: core.App, id: str) -> None:
        super().__init__(app, id)

        # Setting up a role to represent config service principal
        aws_role = iam.Role(
            self,
            'ConfigRole',
            assumed_by=iam.ServicePrincipal('config.amazonaws.com')
        )

        # Adding a managed policy to the above role
        aws_role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSConfigRole"))

        # Setting up ConfigurationRecorder for AWS Config
        aws_config_recorder = config.CfnConfigurationRecorder(
            self,
            'ConfigRecorder',
            role_arn=aws_role.role_arn,
            recording_group={"allSupported": True}
        )

        # Setting up the S3 bucket for Config to deliver the changes
        aws_config_bucket = s3.Bucket(self, 'ConfigBucket')

        # Adding policies to the S3 bucket
        aws_config_bucket.add_to_resource_policy(iam.PolicyStatement(
            effect=iam.Effect.ALLOW,
            principals=[aws_role],
            resources=[aws_config_bucket.bucket_arn],
            actions=["s3:GetBucketAcl", "s3:ListBucket"]
        ))

        cst_resource = 'AWSLogs/' + core.Stack.of(self).account + '/Config/*'

        aws_config_bucket.add_to_resource_policy(iam.PolicyStatement(
            effect=iam.Effect.ALLOW,
            principals=[aws_role],
            resources=[aws_config_bucket.arn_for_objects(cst_resource)],
            actions=["s3:PutObject"],
            conditions={"StringEquals": {
                "s3:x-amz-acl": "bucket-owner-full-control"}}
        ))

        # Creating the deliverchannel for Config
        config.CfnDeliveryChannel(
            self,
            'ConfigDeliveryChannel',
            s3_bucket_name=aws_config_bucket.bucket_name
        )

        # Create CloulTrail trail
        trail.Trail(self, 'Trail')

        # Create Config managed rule
        aws_config_managed_rule = config.ManagedRule(
            self,
            "restricted-ssh",
            identifier=config.ManagedRuleIdentifiers.EC2_SECURITY_GROUPS_INCOMING_SSH_DISABLED
        )

        # You cant create a rule if recorder is not enabled
        aws_config_managed_rule.node.add_dependency(aws_config_recorder)

        # Event pattern triggered by change in the AWS Config compliance rule
        dtl = """{
                "requestParameters": {
                    "evaluations": {
                        "complianceType": [
                        "NON_COMPLIANT"
                        ]
                }
                },
                "additionalEventData": {
                    "managedRuleIdentifier": [
                        "INCOMING_SSH_DISABLED"
                    ]
                }
            }"""
        # detail needs to be a JSON object
        detail = json.loads(dtl)

        # Create an eventbridge rule to be triggered by AWS Config
        aws_event_rule = events.Rule(
            self,
            "Rule",
            description='rule that triggers a lambda function to revoke SSH public access directly after AWS Config NON COMFORM event',
            event_pattern=events.EventPattern(
                detail=detail,
                source=["aws.config"]
            )
        )

        # Create role for the lambda function
        aws_lambda_se_group_role = iam.Role(
            self,
            'aws_lambda_security_group_role',
            assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'),
            managed_policies=[
                iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole")
            ])

        # Add policy to Lambda role
        aws_lambda_se_group_role.add_to_policy(iam.PolicyStatement(
            effect=iam.Effect.ALLOW,
            resources=["*"],
            actions=["ec2:RevokeSecurityGroupIngress", "config:GetComplianceDetailsByConfigRule", "sts:GetCallerIdentity", "ec2:DescribeSecurityGroups"]))

        # Create lambda function and pass it the above role
        with open("lambda.py", encoding="utf8") as fp:
            handler_code = fp.read()

        aws_lambda_fn = lambda_.Function(
            self, "revoke-ssh-access",
            role=aws_lambda_se_group_role,
            code=lambda_.InlineCode(handler_code),
            handler="index.lambda_handler",
            timeout=core.Duration.seconds(300),
            runtime=lambda_.Runtime.PYTHON_3_7,
        )

        # Add environment variable for lambda function
        aws_lambda_fn.add_environment("SSH_RULE_NAME", aws_config_managed_rule.config_rule_name)

        # Adding the lambda function as a target of the rule
        aws_event_rule.add_target(targets.LambdaFunction(aws_lambda_fn))
Beispiel #4
0
    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        high_cpu_topic = sns.Topic(self, 'high-cpu-topic',
                                   display_name='myHighCpuAlarm')
        # phone number format must be 12225558888 for US
        phone_param = ssm.StringParameter.from_string_parameter_name(self, 'phone-param',
                                                                     'notification-phone')
        high_cpu_topic_sub = sns.Subscription(self, 'high-cpu-topic-sub',
                                              topic=high_cpu_topic,
                                              protocol=sns.SubscriptionProtocol.SMS,
                                              endpoint=phone_param.string_value)

        default_vpc = ec2.Vpc.from_lookup(self, 'default-vpc', is_default=True)
        monitored_instance = ec2.Instance(self, 'monitored-instance',
                                          instance_name='devassoc-monitored',
                                          instance_type=type.R3_XLARGE,
                                          machine_image=ec2.MachineImage.generic_linux(
                                              ami_map=ami_map
                                          ),
                                          vpc=default_vpc)

        high_cpu_metric = cw.Metric(namespace='AWS/EC2',
                                    metric_name='CPUUtilization',
                                    dimensions={
                                        'InstanceId': monitored_instance.instance_id
                                    },
                                    statistic='Average',
                                    unit=cw.Unit.PERCENT,
                                    period=core.Duration.seconds(300))
        high_cpu_alarm = high_cpu_metric.create_alarm(self, 'high-cpu-alarm',
                                                      alarm_name='cpu-mon',
                                                      alarm_description='Alarm when CPU exceeds 70%',
                                                      comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
                                                      evaluation_periods=2,
                                                      period=core.Duration.seconds(300),
                                                      threshold=70,
                                                      actions_enabled=True)
        high_cpu_action = cwa.SnsAction(high_cpu_topic)
        high_cpu_alarm.add_alarm_action(high_cpu_action)

        ec2.CfnEIP(self, 'devassoc-elastic-ip')

        # not really a service role, but there are problems with that, per
        # https://github.com/aws/aws-cdk/issues/3492
        config_service_role = iam.Role(self, 'devassoc-config-service-role',
                                       assumed_by=iam.ServicePrincipal('config.amazonaws.com'),
                                       managed_policies=[
                                           iam.ManagedPolicy.from_aws_managed_policy_name('service-role/AWSConfigRole')
                                       ])
        config_recorder = config.CfnConfigurationRecorder(self, 'devassoc-recorder',
                                                          name='ConfigRecorder',
                                                          role_arn=config_service_role.role_arn,
                                                          recording_group=config.CfnConfigurationRecorder.RecordingGroupProperty(
                                                              all_supported=True)
                                                          )
        config_bucket = s3.Bucket(self, 'config-bucket',
                                  bucket_name='devassoc-config',
                                  removal_policy=core.RemovalPolicy.DESTROY,
                                  auto_delete_objects=True)
        config_bucket.add_to_resource_policy(iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                                                 principals=[iam.ServicePrincipal('config.amazonaws.com')],
                                                                 resources=[config_bucket.bucket_arn],
                                                                 actions=['s3:GetBucketAcl']))
        config_bucket.add_to_resource_policy(iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                                                 principals=[iam.ServicePrincipal('config.amazonaws.com')],
                                                                 resources=[config_bucket.arn_for_objects(
                                                                     f"AWSLogs/{core.Stack.of(self).account}/Config/*")],
                                                                 actions=['s3:PutObject'],
                                                                 conditions={'StringEquals': {
                                                                     's3:x-amz-acl': 'bucket-owner-full-control'}}))
        eip_rule = config.ManagedRule(self, 'devassoc-managed-rule',
                                      identifier=config.ManagedRuleIdentifiers.EIP_ATTACHED,
                                      config_rule_name='devassoc-eip-rule')
        eip_rule.node.add_dependency(config_recorder)
        eip_compliance_topic = sns.Topic(self, 'eip-compliance-topic',
                                         display_name='EIP Compliance Topic')
        eip_compliance_topic_sub = sns.Subscription(self, 'eip-compliance-topic-sub',
                                                    topic=eip_compliance_topic,
                                                    protocol=sns.SubscriptionProtocol.SMS,
                                                    endpoint=phone_param.string_value)
        eip_rule.on_compliance_change('eip-compliance-change',
                                      target=targets.SnsTopic(eip_compliance_topic))
        config.CfnDeliveryChannel(self, 'devassoc-config-delivery',
                                  s3_bucket_name=config_bucket.bucket_name,
                                  sns_topic_arn=eip_compliance_topic.topic_arn)
Beispiel #5
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        security_distribution_list_email = '*****@*****.**'

        # securityhub_instance = securityhub.CfnHub(self, 'SecurityHub')

        # Ensure AWS Config is enabled / Ensure CloudTrail is enabled in all Regions 2.1 - 2.8
        cloudtrail_bucket_accesslogs = s3.Bucket(
            self,
            "CloudTrailS3Accesslogs",
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
            encryption=s3.BucketEncryption.S3_MANAGED,
            removal_policy=core.RemovalPolicy.RETAIN)

        cloudtrail_bucket = s3.Bucket(
            self,
            "CloudTrailS3",
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
            encryption=s3.BucketEncryption.S3_MANAGED,
            removal_policy=core.RemovalPolicy.RETAIN,
            server_access_logs_bucket=cloudtrail_bucket_accesslogs,
        )

        cloudtrail_kms = kms.Key(self,
                                 "CloudTrailKey",
                                 enable_key_rotation=True)

        # CloudTrail - single account, not Organization
        trail = cloudtrail.Trail(
            self,
            "CloudTrail",
            enable_file_validation=True,
            is_multi_region_trail=True,
            include_global_service_events=True,
            send_to_cloud_watch_logs=True,
            cloud_watch_logs_retention=logs.RetentionDays.FOUR_MONTHS,
            bucket=cloudtrail_bucket,
            kms_key=cloudtrail_kms)

        cloudtrail_kms.grant(iam.ServicePrincipal('cloudtrail.amazonaws.com'),
                             'kms:DescribeKey')

        cloudtrail_kms.grant(
            iam.ServicePrincipal(
                'cloudtrail.amazonaws.com',
                conditions={
                    'StringLike': {
                        'kms:EncryptionContext:aws:cloudtrail:arn':
                        'arn:aws:cloudtrail:*:' + core.Stack.of(self).account +
                        ':trail/*'
                    }
                }), 'kms:GenerateDataKey*')

        cloudtrail_kms.add_to_resource_policy(
            iam.PolicyStatement(
                actions=["kms:Decrypt", "kms:ReEncryptFrom"],
                conditions={
                    'StringEquals': {
                        'kms:CallerAccount': core.Stack.of(self).account
                    },
                    'StringLike': {
                        'kms:EncryptionContext:aws:cloudtrail:arn':
                        'arn:aws:cloudtrail:*:' + core.Stack.of(self).account +
                        ':trail/*'
                    }
                },
                effect=iam.Effect.ALLOW,
                principals=[iam.AnyPrincipal()],
                resources=['*']))

        cloudtrail_kms.add_to_resource_policy(
            iam.PolicyStatement(actions=["kms:CreateAlias"],
                                conditions={
                                    'StringEquals': {
                                        'kms:CallerAccount':
                                        core.Stack.of(self).account,
                                        'kms:ViaService':
                                        'ec2.' + core.Stack.of(self).region +
                                        '.amazonaws.com'
                                    }
                                },
                                effect=iam.Effect.ALLOW,
                                principals=[iam.AnyPrincipal()],
                                resources=['*']))

        cloudtrail_kms.add_to_resource_policy(
            iam.PolicyStatement(
                actions=["kms:Decrypt", "kms:ReEncryptFrom"],
                conditions={
                    'StringEquals': {
                        'kms:CallerAccount': core.Stack.of(self).account
                    },
                    'StringLike': {
                        'kms:EncryptionContext:aws:cloudtrail:arn':
                        'arn:aws:cloudtrail:*:' + core.Stack.of(self).account +
                        ':trail/*'
                    }
                },
                effect=iam.Effect.ALLOW,
                principals=[iam.AnyPrincipal()],
                resources=['*']))

        config_role = iam.CfnServiceLinkedRole(
            self,
            id='ServiceLinkedRoleConfig',
            aws_service_name='config.amazonaws.com')

        global_config = config.CfnConfigurationRecorder(self, 'ConfigRecorder',
                                                        name='default',
                                                        # role_arn=config_role.role_arn,
                                                        role_arn="arn:aws:iam::" + \
                                                        core.Stack.of(
                                                            self).account+":role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig",
                                                        # role_arn=config_role.get_att(
                                                        #     attribute_name='resource.arn').to_string(),
                                                        recording_group=config.CfnConfigurationRecorder.RecordingGroupProperty(
                                                            all_supported=True,
                                                            include_global_resource_types=True
                                                        )
                                                        )

        config_bucket = s3.Bucket(
            self,
            "ConfigS3",
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
            encryption=s3.BucketEncryption.S3_MANAGED,
            removal_policy=core.RemovalPolicy.RETAIN,
        )

        config_bucket.add_to_resource_policy(
            iam.PolicyStatement(
                actions=['s3:GetBucketAcl'],
                effect=iam.Effect.ALLOW,
                principals=[iam.ServicePrincipal('config.amazonaws.com')],
                resources=[config_bucket.bucket_arn]))

        config_bucket.add_to_resource_policy(
            iam.PolicyStatement(
                actions=['s3:PutObject'],
                effect=iam.Effect.ALLOW,
                principals=[iam.ServicePrincipal('config.amazonaws.com')],
                resources=[
                    config_bucket.arn_for_objects('AWSLogs/' +
                                                  core.Stack.of(self).account +
                                                  '/Config/*')
                ],
                conditions={
                    "StringEquals": {
                        's3:x-amz-acl': 'bucket-owner-full-control',
                    }
                }))

        config_delivery_stream = config.CfnDeliveryChannel(
            self,
            "ConfigDeliveryChannel",
            s3_bucket_name=config_bucket.bucket_name)

        # Config Aggregator in Organizations account
        # config_aggregator = config.CfnConfigurationAggregator(self, 'ConfigAggregator',
        #                                                       configuration_aggregator_name='ConfigAggregator',
        #                                                       organization_aggregation_source=config.CfnConfigurationAggregator.OrganizationAggregationSourceProperty(
        #                                                           role_arn=iam.Role(self, "AWSConfigRoleForOrganizations",
        #                                                                             assumed_by=iam.ServicePrincipal(
        #                                                                                 'config.amazonaws.com'),
        #                                                                             managed_policies=[iam.ManagedPolicy.from_aws_managed_policy_name(
        #                                                                                 'service-role/AWSConfigRoleForOrganizations')]
        #                                                                             ).role_arn,
        #                                                           all_aws_regions=True
        #                                                       )
        #                                                       )

        # 2.9 – Ensure VPC flow logging is enabled in all VPCs
        # vpc = ec2.Vpc.from_lookup(self, "VPC",
        #                           is_default=True,
        #                           )

        # S3 for VPC flow logs
        # vpc_flow_logs_bucket = s3.Bucket(self, "VPCFlowLogsBucket",
        #                                  block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
        #                                  encryption=s3.BucketEncryption.S3_MANAGED,
        #                                  removal_policy=core.RemovalPolicy.RETAIN
        #                                  )

        # Ensure a log metric filter and alarm exist for 3.1 – 3.14
        security_notifications_topic = sns.Topic(self,
                                                 'CIS_Topic',
                                                 display_name='CIS_Topic',
                                                 topic_name='CIS_Topic')

        sns.Subscription(self,
                         'CIS_Subscription',
                         topic=security_notifications_topic,
                         protocol=sns.SubscriptionProtocol.EMAIL,
                         endpoint=security_distribution_list_email)

        cloudwatch_actions_cis = cloudwatch_actions.SnsAction(
            security_notifications_topic)

        cis_metricfilter_alarms = {
            'CIS-3.1-UnauthorizedAPICalls':
            '($.errorCode="*UnauthorizedOperation") || ($.errorCode="AccessDenied*")',
            'CIS-3.2-ConsoleSigninWithoutMFA':
            '($.eventName="ConsoleLogin") && ($.additionalEventData.MFAUsed !="Yes")',
            'RootAccountUsageAlarm':
            '$.userIdentity.type="Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType !="AwsServiceEvent"',
            'CIS-3.4-IAMPolicyChanges':
            '($.eventName=DeleteGroupPolicy) || ($.eventName=DeleteRolePolicy) || ($.eventName=DeleteUserPolicy) || ($.eventName=PutGroupPolicy) || ($.eventName=PutRolePolicy) || ($.eventName=PutUserPolicy) || ($.eventName=CreatePolicy) || ($.eventName=DeletePolicy) || ($.eventName=CreatePolicyVersion) || ($.eventName=DeletePolicyVersion) || ($.eventName=AttachRolePolicy) || ($.eventName=DetachRolePolicy) || ($.eventName=AttachUserPolicy) || ($.eventName=DetachUserPolicy) || ($.eventName=AttachGroupPolicy) || ($.eventName=DetachGroupPolicy)',
            'CIS-3.5-CloudTrailChanges':
            '($.eventName=CreateTrail) || ($.eventName=UpdateTrail) || ($.eventName=DeleteTrail) || ($.eventName=StartLogging) || ($.eventName=StopLogging)',
            'CIS-3.6-ConsoleAuthenticationFailure':
            '($.eventName=ConsoleLogin) && ($.errorMessage="Failed authentication")',
            'CIS-3.7-DisableOrDeleteCMK':
            '($.eventSource=kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion))',
            'CIS-3.8-S3BucketPolicyChanges':
            '($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))',
            'CIS-3.9-AWSConfigChanges':
            '($.eventSource=config.amazonaws.com) && (($.eventName=StopConfigurationRecorder) || ($.eventName=DeleteDeliveryChannel) || ($.eventName=PutDeliveryChannel) || ($.eventName=PutConfigurationRecorder))',
            'CIS-3.10-SecurityGroupChanges':
            '($.eventName=AuthorizeSecurityGroupIngress) || ($.eventName=AuthorizeSecurityGroupEgress) || ($.eventName=RevokeSecurityGroupIngress) || ($.eventName=RevokeSecurityGroupEgress) || ($.eventName=CreateSecurityGroup) || ($.eventName=DeleteSecurityGroup)',
            'CIS-3.11-NetworkACLChanges':
            '($.eventName=CreateNetworkAcl) || ($.eventName=CreateNetworkAclEntry) || ($.eventName=DeleteNetworkAcl) || ($.eventName=DeleteNetworkAclEntry) || ($.eventName=ReplaceNetworkAclEntry) || ($.eventName=ReplaceNetworkAclAssociation)',
            'CIS-3.12-NetworkGatewayChanges':
            '($.eventName=CreateCustomerGateway) || ($.eventName=DeleteCustomerGateway) || ($.eventName=AttachInternetGateway) || ($.eventName=CreateInternetGateway) || ($.eventName=DeleteInternetGateway) || ($.eventName=DetachInternetGateway)',
            'CIS-3.13-RouteTableChanges':
            '($.eventName=CreateRoute) || ($.eventName=CreateRouteTable) || ($.eventName=ReplaceRoute) || ($.eventName=ReplaceRouteTableAssociation) || ($.eventName=DeleteRouteTable) || ($.eventName=DeleteRoute) || ($.eventName=DisassociateRouteTable)',
            'CIS-3.14-VPCChanges':
            '($.eventName=CreateVpc) || ($.eventName=DeleteVpc) || ($.eventName=ModifyVpcAttribute) || ($.eventName=AcceptVpcPeeringConnection) || ($.eventName=CreateVpcPeeringConnection) || ($.eventName=DeleteVpcPeeringConnection) || ($.eventName=RejectVpcPeeringConnection) || ($.eventName=AttachClassicLinkVpc) || ($.eventName=DetachClassicLinkVpc) || ($.eventName=DisableVpcClassicLink) || ($.eventName=EnableVpcClassicLink)',
        }
        for x, y in cis_metricfilter_alarms.items():
            str_x = str(x)
            str_y = str(y)
            logs.MetricFilter(
                self,
                "MetricFilter_" + str_x,
                log_group=trail.log_group,
                filter_pattern=logs.JsonPattern(json_pattern_string=str_y),
                metric_name=str_x,
                metric_namespace="LogMetrics",
                metric_value='1')
            cloudwatch.Alarm(
                self,
                "Alarm_" + str_x,
                alarm_name=str_x,
                alarm_description=str_x,
                statistic='Sum',
                period=core.Duration.minutes(5),
                comparison_operator=cloudwatch.ComparisonOperator.
                GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
                evaluation_periods=1,
                threshold=1,
                metric=cloudwatch.Metric(metric_name=str_x,
                                         namespace="LogMetrics"),
            ).add_alarm_action(cloudwatch_actions_cis)

        # IAM Password Policy custom resource CIS 1.5 - 1.11
        cfn_template = cfn_inc.CfnInclude(
            self,
            "includeTemplate",
            template_file="account-password-policy.yaml",
            parameters={
                "MaxPasswordAge": 90,
                "MinimumPasswordLength": 14,
                "PasswordReusePrevention": 24,
                "RequireLowercaseCharacters": True,
                "RequireNumbers": True,
                "RequireSymbols": True,
                "RequireUppercaseCharacters": True,
            })

        # CIS 1.20
        support_role = iam.Role(
            self,
            "SupportRole",
            assumed_by=iam.AccountPrincipal(
                account_id=core.Stack.of(self).account),
            managed_policies=[
                iam.ManagedPolicy.from_aws_managed_policy_name(
                    'AWSSupportAccess')
            ],
            role_name='AWSSupportAccess')

        guardduty_detector = guardduty.CfnDetector(self,
                                                   'GuardDutyDetector',
                                                   enable=True)

        guardduty_event = events.Rule(
            self,
            'GuardDutyEvent',
            rule_name='guardduty-notification',
            description='GuardDuty Notification',
            event_pattern=events.EventPattern(
                source=['aws.guardduty'], detail_type=['GuardDuty Finding']),
            targets=[events_targets.SnsTopic(security_notifications_topic)])