def _add_ecs_instance_role_and_profile(self):
        ecs_instance_role = iam.CfnRole(
            self.stack_scope,
            "EcsInstanceRole",
            path=self._cluster_scoped_iam_path(),
            managed_policy_arns=[
                self._format_arn(
                    service="iam",
                    account="aws",
                    region="",
                    resource=
                    "policy/service-role/AmazonEC2ContainerServiceforEC2Role",
                )
            ],
            assume_role_policy_document=get_assume_role_policy_document(
                f"ec2.{self._url_suffix}"),
        )

        iam_instance_profile = iam.CfnInstanceProfile(
            self.stack_scope,
            "IamInstanceProfile",
            path=self._cluster_scoped_iam_path(),
            roles=[ecs_instance_role.ref])

        return ecs_instance_role, iam_instance_profile
 def _add_code_build_role(self):
     return iam.CfnRole(
         self.stack_scope,
         "CodeBuildRole",
         path=self._cluster_scoped_iam_path(),
         assume_role_policy_document=get_assume_role_policy_document(
             "codebuild.amazonaws.com"),
     )
def add_lambda_cfn_role(scope, function_id: str, statements: List[iam.PolicyStatement]):
    """Return a CfnRole to be used for a Lambda function."""
    return iam.CfnRole(
        scope,
        f"{function_id}FunctionExecutionRole",
        path=IAM_ROLE_PATH,
        assume_role_policy_document=get_assume_role_policy_document("lambda.amazonaws.com"),
        policies=[
            iam.CfnRole.PolicyProperty(
                policy_document=iam.PolicyDocument(statements=statements),
                policy_name="LambdaPolicy",
            ),
        ],
    )
Esempio n. 4
0
    def __init__(self, scope: core.Construct, id: str, app_nw_stack: appNwStack, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        # Contexts
        PRJ = self.node.try_get_context("prj")
        AMI_ID = self.node.try_get_context("ami-id")  # Amazon Linux 2

        # Functions
        def nametag(x): return core.CfnTag(
            key="Name", value="{}/{}".format(PRJ, x))

        # ### Resources
        # IAM Role
        ec2_statement = iam.PolicyStatement()
        ec2_statement.add_actions("sts:AssumeRole")
        ec2_statement.add_service_principal(service="ec2.amazonaws.com")
        ec2_document = iam.PolicyDocument(
            statements=[ec2_statement]
        )
        iam_role = iam.CfnRole(
            self, "iamRoleForEc2",
            role_name="{}-ec2-role".format(PRJ),
            description="{}-ec2-role".format(PRJ),
            assume_role_policy_document=ec2_document.to_json(),
            managed_policy_arns=[
                "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
            ]
        )
        ec2_instance_profile = iam.CfnInstanceProfile(
            self, "ec2InstanceProfile",
            roles=[iam_role.ref],
            instance_profile_name="{}-ec2-instance-profile".format(PRJ)
        )
        # Security Group
        sg = ec2.CfnSecurityGroup(
            self, "sg",
            group_description="sg for ec2 instance({})".format(PRJ),
            vpc_id=app_nw_stack.vpc.ref,
            security_group_ingress=[]
        )
        # Instance
        ec2.CfnInstance(
            self, "instance",
            iam_instance_profile=ec2_instance_profile.ref,
            image_id=AMI_ID,
            instance_type="t3.micro",
            security_group_ids=[sg.ref],
            subnet_id=app_nw_stack.ec2_subnet.ref,
            tags=[nametag("instance")]
        )
Esempio n. 5
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)
 def _add_node_role(self, node: Union[HeadNode, BaseQueue], name: str):
     additional_iam_policies = set(node.iam.additional_iam_policy_arns)
     if self._config.monitoring.logs.cloud_watch.enabled:
         additional_iam_policies.add(
             policy_name_to_arn("CloudWatchAgentServerPolicy"))
     if self._config.scheduling.scheduler == "awsbatch":
         additional_iam_policies.add(
             policy_name_to_arn("AWSBatchFullAccess"))
     return iam.CfnRole(
         Stack.of(self),
         name,
         path=self._cluster_scoped_iam_path(),
         managed_policy_arns=list(additional_iam_policies),
         assume_role_policy_document=get_assume_role_policy_document(
             "ec2.{0}".format(Stack.of(self).url_suffix)),
     )
 def _add_spot_fleet_iam_role(self):
     return iam.CfnRole(
         self.stack_scope,
         "BatchSpotRole",
         path=self._cluster_scoped_iam_path(),
         managed_policy_arns=[
             self._format_arn(
                 service="iam",
                 account="aws",
                 region="",
                 resource=
                 "policy/service-role/AmazonEC2SpotFleetTaggingRole",
             )
         ],
         assume_role_policy_document=get_assume_role_policy_document(
             "spotfleet.amazonaws.com"),
     )
Esempio n. 8
0
    def __init__(self, scope: core.Construct, id: str, policies, service,
                 whitelisted_actions):
        super().__init__(scope, id)

        self.role = iam.CfnRole(self,
                                id=id,
                                assume_role_policy_document={
                                    'Statement': [{
                                        'Action': 'sts:AssumeRole',
                                        'Effect': 'Allow',
                                        'Principal': {
                                            'Service': service
                                        }
                                    }]
                                },
                                policies=ServiceRole.add_policies(
                                    policies, whitelisted_actions))
Esempio n. 9
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # IAMロールを作成
        my_role_ec2 = iam.CfnRole(
            self,
            id="my-role-ec2",
            assume_role_policy_document={
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Action": "sts:AssumeRole",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "ec2.amazonaws.com"
                    }
                }]
            },
            description="the ec2 role",
            managed_policy_arns=[
                # "arn:aws:iam::aws:policy/AmazonS3FullAccess" # 付与したいアクセス権をリストする
            ],
            role_name="my-role-ec2",
            tags=[{
                "key": "Name",
                "value": "my-role-ec2"
            }])
        # Instance Profileを作成
        my_instance_profile = iam.CfnInstanceProfile(self,
                                                     id="my-instance-profile",
                                                     roles=[my_role_ec2.ref])

        # VPCを作成
        my_vpc = ec2.CfnVPC(self,
                            id="my-vpc",
                            cidr_block="192.168.0.0/16",
                            enable_dns_hostnames=True,
                            tags=[{
                                "key": "Name",
                                "value": "my-vpc"
                            }])

        # Subnetを作成
        my_subnet_1 = ec2.CfnSubnet(self,
                                    id="my-subnet",
                                    cidr_block="192.168.0.0/24",
                                    vpc_id=my_vpc.ref,
                                    availability_zone=core.Fn.select(
                                        0, core.Fn.get_azs("")),
                                    tags=[{
                                        "key": "Name",
                                        "value": "my-subnet-1"
                                    }])

        # Internet Gatewayを作成
        my_igw = ec2.CfnInternetGateway(self,
                                        id="my-igw",
                                        tags=[{
                                            "key": "Name",
                                            "value": "my-igw"
                                        }])
        # Internet Gatewayをアタッチ
        ec2.CfnVPCGatewayAttachment(self,
                                    id="my-igw-attachment",
                                    vpc_id=my_vpc.ref,
                                    internet_gateway_id=my_igw.ref)

        # Routetableを作成
        my_rtb = ec2.CfnRouteTable(self,
                                   id="my-rtb",
                                   vpc_id=my_vpc.ref,
                                   tags=[{
                                       "key": "Name",
                                       "value": "my-rtb"
                                   }])
        # Routetableとサブネットの関連付け
        ec2.CfnSubnetRouteTableAssociation(self,
                                           id="my-rtb-association",
                                           route_table_id=my_rtb.ref,
                                           subnet_id=my_subnet_1.ref)

        # Routeの設定
        my_rt = ec2.CfnRoute(self,
                             id="my-rt",
                             route_table_id=my_rtb.ref,
                             destination_cidr_block="0.0.0.0/0",
                             gateway_id=my_igw.ref)

        # Security Groupの作成
        my_sg_ec2 = ec2.CfnSecurityGroup(
            self,
            id="my-sg-ec2",
            vpc_id=my_vpc.ref,
            group_description="my-sg-ec2",
            group_name="my-sg-ec2",
            security_group_ingress=[
                ec2.CfnSecurityGroup.IngressProperty(ip_protocol="tcp",
                                                     cidr_ip="0.0.0.0/0",
                                                     from_port=22,
                                                     to_port=22)
            ],
            tags=[{
                "key": "Name",
                "value": "my-sg-ec2"
            }])

        #  AMIを指定してimage_idを取得
        amzn_linux = ec2.MachineImage.latest_amazon_linux(
            generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX,
            edition=ec2.AmazonLinuxEdition.STANDARD,
            virtualization=ec2.AmazonLinuxVirt.HVM,
            storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE,
            cpu_type=ec2.AmazonLinuxCpuType.X86_64).get_image(self).image_id

        # EC2を作成
        my_ec2 = ec2.CfnInstance(
            self,
            id="my-ec2",
            availability_zone=core.Fn.select(0, core.Fn.get_azs("")),
            block_device_mappings=[
                ec2.CfnInstance.BlockDeviceMappingProperty(
                    device_name="/dev/sda1",
                    ebs=ec2.CfnInstance.EbsProperty(delete_on_termination=True,
                                                    encrypted=False,
                                                    volume_size=10,
                                                    volume_type="gp2"))
            ],
            credit_specification=ec2.CfnInstance.CreditSpecificationProperty(
                cpu_credits="standard"),
            iam_instance_profile=my_instance_profile.ref,
            image_id=amzn_linux,
            instance_type="t2.micro",
            security_group_ids=[my_sg_ec2.ref],
            subnet_id=my_subnet_1.ref,
            tags=[{
                "key": "Name",
                "value": "my-ec2"
            }])
    def __init__(self, scope, id, **kwargs):
        super().__init__(scope, id, **kwargs)

        # Create random string to be used as suffix on some resource names
        resource_suffix = ''.join(
            random.choice(string.ascii_lowercase) for i in range(8))

        # Save it as SSM parameter to be used in runtime
        ssm.StringParameter(self,
                            "RESOURCE_SUFFIX",
                            string_value=resource_suffix,
                            parameter_name="RESOURCE_SUFFIX")

        # ====================================== VPC ======================================
        # Create VPC
        vpc = ec2.Vpc(self,
                      "sorterbot-vpc",
                      cidr="10.0.0.0/16",
                      enable_dns_support=True,
                      enable_dns_hostnames=True,
                      max_azs=2,
                      nat_gateways=0,
                      subnet_configuration=[
                          {
                              "subnetType": ec2.SubnetType.PUBLIC,
                              "name": "sorterbot-public-subnet-a",
                              "cidrMask": 24,
                          },
                          {
                              "subnetType": ec2.SubnetType.PUBLIC,
                              "name": "sorterbot-public-subnet-b",
                              "cidrMask": 24,
                          },
                      ])

        # Create security groups
        sg_vpc = ec2.SecurityGroup(self,
                                   "sorterbot-vpc-sg",
                                   vpc=vpc,
                                   allow_all_outbound=True,
                                   security_group_name="sorterbot-vpc-sg")
        sg_vpc.add_ingress_rule(sg_vpc, ec2.Port.all_traffic())

        sg_control = ec2.SecurityGroup(
            self,
            "sorterbot-control-sg",
            vpc=vpc,
            allow_all_outbound=True,
            security_group_name="sorterbot-control-sg")
        sg_control.add_ingress_rule(ec2.Peer.any_ipv4(), ec2.Port.tcp(22))
        sg_control.add_ingress_rule(ec2.Peer.any_ipv4(), ec2.Port.tcp(5432))
        sg_control.add_ingress_rule(ec2.Peer.any_ipv4(), ec2.Port.tcp(80))

        # ====================================== IAM ======================================
        cloud_role = iam.CfnRole(
            self,
            "SorterBotCloudRole",
            role_name="SorterBotCloudRole",
            assume_role_policy_document={
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Sid": "",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "ecs-tasks.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }]
            },
            managed_policy_arns=[
                "arn:aws:iam::aws:policy/AmazonS3FullAccess",
                "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
            ])

        # Create IAM policies
        iam.ManagedPolicy(self,
                          "SorterBotSecretsForECSPolicy",
                          managed_policy_name="SorterBotSecretsForECSPolicy",
                          roles=[cloud_role],
                          statements=[
                              iam.PolicyStatement(
                                  resources=["*"],
                                  actions=[
                                      "ssm:GetParameter", "ssm:GetParameters",
                                      "secretsmanager:GetSecretValue",
                                      "kms:Decrypt"
                                  ])
                          ])

        # ====================================== S3 ======================================
        # Create S3 buckets
        s3.Bucket(self,
                  f"sorterbot-{resource_suffix}",
                  bucket_name=f"sorterbot-{resource_suffix}",
                  removal_policy=core.RemovalPolicy.DESTROY)
        s3.Bucket(self,
                  f"sorterbot-weights-{resource_suffix}",
                  bucket_name=f"sorterbot-weights-{resource_suffix}",
                  removal_policy=core.RemovalPolicy.DESTROY)
        s3.Bucket(self,
                  f"sorterbot-static-{resource_suffix}",
                  bucket_name=f"sorterbot-static-{resource_suffix}",
                  removal_policy=core.RemovalPolicy.DESTROY,
                  cors=[
                      s3.CorsRule(allowed_methods=[s3.HttpMethods.GET],
                                  allowed_origins=["*"],
                                  allowed_headers=["*"])
                  ])

        # ====================================== EC2 ======================================
        # Create EC2 instance for Control Panel
        control_panel_instance = ec2.Instance(
            self,
            f"sorterbot-control-panel-{resource_suffix}",
            instance_name=
            f"sorterbot-control-panel-{resource_suffix}",  # Since deleted instances stay around for a while in terminated state, random suffix is needed to prevent errors when destroying stack # noqa: E501
            instance_type=ec2.InstanceType("t2.micro"),
            machine_image=ec2.MachineImage.latest_amazon_linux(
                generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2),
            vpc=vpc,
            key_name="sorterbot",
            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
            security_group=sg_control)

        control_panel_instance.add_to_role_policy(
            iam.PolicyStatement(resources=["*"],
                                actions=[
                                    "ec2:DescribeNetworkInterfaces",
                                    "ssm:GetParameter", "ecs:*", "s3:*"
                                ]))

        # ====================================== RDS ======================================
        # Declare connection details
        master_username = "******"
        master_user_password = core.SecretValue.ssm_secure("PG_PASS",
                                                           version="1")
        port = 5432

        # Create postgres database
        database = rds.DatabaseInstance(
            self,
            "sorterbot_postgres",
            allocated_storage=10,
            backup_retention=core.Duration.days(
                0
            ),  # Don't save backups since storing them is not covered by the Free Tier
            database_name="sorterbot",
            delete_automated_backups=True,
            deletion_protection=False,
            engine=rds.DatabaseInstanceEngine.POSTGRES,
            engine_version="11",
            instance_class=ec2.InstanceType("t2.micro"),  # Stay in Free Tier
            instance_identifier="sorterbot-postgres",
            master_username=master_username,
            master_user_password=master_user_password,
            port=port,
            storage_type=rds.StorageType.GP2,
            vpc=vpc,
            vpc_placement=ec2.SubnetSelection(
                subnet_type=ec2.SubnetType.PUBLIC
            ),  # Make DB publicly accessible (with credentials)
            removal_policy=core.RemovalPolicy.DESTROY)

        # Add ingress rule to allow external connections
        database.connections.allow_default_port_from_any_ipv4()

        # ====================================== ECR ======================================
        # Create ECR repository for Docker images
        ecr.Repository(self,
                       "sorterbot-ecr",
                       repository_name="sorterbot-ecr",
                       removal_policy=core.RemovalPolicy.DESTROY)

        # ====================================== ECS ======================================
        # Create ECS Cluster, Task Definition and Fargate Service
        ecs_cluster = ecs.Cluster(self,
                                  "sorterbot-ecs-cluster",
                                  vpc=vpc,
                                  cluster_name="sorterbot-ecs-cluster")
        task_definition = ecs.FargateTaskDefinition(
            self, "sorterbot-fargate-service", cpu=512, memory_limit_mib=4096)
        task_definition.add_container(
            "sorterbot-cloud-container",
            image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample"))
        ecs.FargateService(self,
                           "sorterbot-ecs-service",
                           cluster=ecs_cluster,
                           task_definition=task_definition,
                           assign_public_ip=True,
                           service_name="sorterbot-ecs-service",
                           desired_count=0,
                           security_group=sg_vpc)

        # Save resource suffix to disk to be used when destroying
        with open(
                Path(__file__).parents[1].joinpath("scripts", "variables",
                                                   "RESOURCE_SUFFIX"),
                "w") as outfile:
            outfile.write(resource_suffix)
    def _add_default_instance_role(self, cleanup_policy_statements,
                                   build_tags):
        """Set default instance role in imagebuilder cfn template."""
        managed_policy_arns = [
            Fn.sub(
                "arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore"
            ),
            Fn.sub(
                "arn:${AWS::Partition}:iam::aws:policy/EC2InstanceProfileForImageBuilder"
            ),
        ]
        if self.config.build.iam and self.config.build.iam.additional_iam_policies:
            for policy in self.config.build.iam.additional_iam_policy_arns:
                managed_policy_arns.append(policy)

        instancerole_policy_document = iam.PolicyDocument(statements=[
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                resources=[
                    self.format_arn(
                        service="ec2",
                        account="",
                        resource="image",
                        resource_name="*",
                    )
                ],
                actions=["ec2:CreateTags", "ec2:ModifyImageAttribute"],
            )
        ])

        if self.config.build.components:
            for custom_component in self.config.build.components:
                # Check custom component is script, and the url is S3 url
                if custom_component.type == "script" and utils.get_url_scheme(
                        custom_component.value) == "s3":
                    bucket_info = parse_bucket_url(custom_component.value)
                    bucket_name = bucket_info.get("bucket_name")
                    object_key = bucket_info.get("object_key")
                    instancerole_policy_document.add_statements(
                        iam.PolicyStatement(
                            actions=["s3:GetObject"],
                            effect=iam.Effect.ALLOW,
                            resources=[
                                self.format_arn(
                                    region="",
                                    service="s3",
                                    account="",
                                    resource=bucket_name,
                                    resource_name=object_key,
                                )
                            ],
                        ), )

        instancerole_policy = iam.CfnRole.PolicyProperty(
            policy_name="InstanceRoleInlinePolicy",
            policy_document=instancerole_policy_document,
        )

        instance_role_resource = iam.CfnRole(
            self,
            "InstanceRole",
            path=IAM_ROLE_PATH,
            managed_policy_arns=managed_policy_arns,
            assume_role_policy_document=get_assume_role_policy_document(
                "ec2.{0}".format(self.url_suffix)),
            policies=[
                instancerole_policy,
            ],
            tags=build_tags,
            role_name=self._build_resource_name(
                IMAGEBUILDER_RESOURCE_NAME_PREFIX),
        )
        if not self.custom_cleanup_lambda_role:
            self._add_resource_delete_policy(
                cleanup_policy_statements,
                ["iam:DeleteRole"],
                [
                    self.format_arn(
                        service="iam",
                        region="",
                        resource="role",
                        resource_name="{0}/{1}".format(
                            IAM_ROLE_PATH.strip("/"),
                            self._build_resource_name(
                                IMAGEBUILDER_RESOURCE_NAME_PREFIX),
                        ),
                    )
                ],
            )

        return instance_role_resource
    def __init__(
        self, 
        scope: core.Construct, 
        id: str, 
        vpc: ec2.Vpc,
        lambda_sg: ec2.SecurityGroup,
        **kwargs
    ) -> None:
        super().__init__(scope, id, **kwargs)

        self.PREFIX = id

        ## **************** Create Knowledge Analyzer Service Role **************** 
        self.service_role = aws_iam.Role.from_role_arn(
            self, f'{self.PREFIX}-IAMROLE-ServiceRole',
            f"arn:aws:iam::{self.account}:role/HEALTHLAKE-KNOWLEDGE-ANALYZER-IAMROLE-ServiceRole"
        )

        ## **************** Create a notebook Instance ****************

        self.notebook_instance_role = aws_iam.Role(
            self,
            "AmazonSageMaker-ExecutionRole-20210318",
            role_name=f'AmazonSageMaker-ExecutionRole-20210318',
            assumed_by=aws_iam.ServicePrincipal("sagemaker.amazonaws.com")
        )

        roleStmt1=aws_iam.PolicyStatement(
                effect=aws_iam.Effect.ALLOW,
                resources=["arn:aws:s3:::*"],
                actions=["s3:PutObject", "s3:ListObjects", "s3:GetObject"]
            )
        roleStmt2=aws_iam.PolicyStatement(
                effect=aws_iam.Effect.ALLOW,
                resources=["arn:aws:s3:::*"],
                actions=["s3:ListBucket", "s3:GetBucketPublicAccessBlock", "s3:GetEncryptionConfiguration"]
            )
        
        self.notebook_instance_role.add_to_policy( roleStmt1 )
        self.notebook_instance_role.add_to_policy( roleStmt2 )
        
        self.notebook_instance_role.add_managed_policy(aws_iam.ManagedPolicy.from_aws_managed_policy_name("AmazonSageMakerFullAccess"))

        
        self.nbInstance = sagemaker.CfnNotebookInstance(
            self,
            f'{self.PREFIX}-HealtLake-Blog-Run',
            instance_type = 'ml.t2.medium',
            notebook_instance_name=f'{self.PREFIX}-HealtLake-Blog-Run',
            role_arn = self.notebook_instance_role.role_arn,
            )


        ## **************** Inherit VPC & Security Group **************** 
        self.vpc = vpc
        self.lambda_sg = lambda_sg


        self.comprehend_complete_sqs = sqs.CfnQueue(
            self, f'{self.PREFIX}-comprehendCompleteQueue',
            visibility_timeout = 900,
            queue_name= f'{self.PREFIX}-comprehendCompleteQueue'
        )
        self.s3export = _s3.Bucket(self, "hl-synthea-export", bucket_name = "hl-synthea-export-%s" % (core.Aws.ACCOUNT_ID), block_public_access=_s3.BlockPublicAccess.BLOCK_ALL, encryption=_s3.BucketEncryption.S3_MANAGED, removal_policy = core.RemovalPolicy.DESTROY, auto_delete_objects= True,)
        self.s3_loc = _s3.Bucket(self, "hl-synthea-source", bucket_name = "hl-synthea-source-%s" % (core.Aws.ACCOUNT_ID), block_public_access=_s3.BlockPublicAccess.BLOCK_ALL, removal_policy = core.RemovalPolicy.DESTROY, auto_delete_objects= True,)
        
        self.kendra_instance_role = aws_iam.CfnRole(
            self,
            f'{self.PREFIX}-Kendra-ServiceRole',
            role_name=f'{self.PREFIX}-Kendra-ServiceRole',
            assume_role_policy_document=aws_iam.PolicyDocument(
                statements=[
                    aws_iam.PolicyStatement(
                        effect=aws_iam.Effect.ALLOW,
                        actions=[ "sts:AssumeRole" ],
                        principals=[ aws_iam.ServicePrincipal("kendra.amazonaws.com") ]
                    )
                ]
            ),
            policies=[
                aws_iam.CfnRole.PolicyProperty(
                    policy_document=aws_iam.PolicyDocument(
                        statements=[
                            aws_iam.PolicyStatement(
                                effect=aws_iam.Effect.ALLOW,
                                actions=[
                                    "s3:GetObject",
                                    "s3:ListBucket",
                                    "s3:GetBucketPublicAccessBlock",
                                    "s3:GetEncryptionConfiguration"                                    
                                ],
                                resources=["*"]
                            )
                        ]
                    ),
                    policy_name="KendraAllowS3GetListObject"
                ),
                aws_iam.CfnRole.PolicyProperty(
                    policy_document=aws_iam.PolicyDocument(
                        statements=[
                            aws_iam.PolicyStatement(
                                effect=aws_iam.Effect.ALLOW,
                                actions=[
                                    "cloudwatch:PutMetricData"
                                ],
                                resources=["*"],
                                conditions = {
                                    "StringEquals": {
                                        'cloudwatch:namespace': 'AWS/Kendra',
                                    },                                    
                                }
                            )
                        ]
                    ),
                    policy_name="KendraAllowMetricObject"
                ),                
                aws_iam.CfnRole.PolicyProperty(
                    policy_document=aws_iam.PolicyDocument(
                        statements=[
                            aws_iam.PolicyStatement(
                                effect=aws_iam.Effect.ALLOW,
                                actions=[
                                    'logs:DescribeLogGroups',
                                    'logs:CreateLogGroup',
                                ],
                                resources=[
                                    "arn:" + "aws" + ":logs:" + core.Aws.REGION + ":" + core.Aws.ACCOUNT_ID + ":log-group:" + "/aws/kendra/*"
                                ],
                            )
                        ]
                    ),
                    policy_name="KendraAllowLogObject"
                ),   
                aws_iam.CfnRole.PolicyProperty(
                    policy_document=aws_iam.PolicyDocument(
                        statements=[
                            aws_iam.PolicyStatement(
                                effect=aws_iam.Effect.ALLOW,
                                actions=[
                                    'logs:DescribeLogStreams',
                                    'logs:CreateLogStream',
                                    'logs:PutLogEvents',
                                ],
                                resources=[
                                    "arn:" + "aws" + ":logs:" + core.Aws.REGION + ":" + core.Aws.ACCOUNT_ID + ":log-group:" + "/aws/kendra/*:log-stream:*" 
                                ],
                            )
                        ]
                    ),
                    policy_name="KendraAllowLogStreamsObject"
                ), 
            ],
        )   

    
        self.indexKendra = kendra.CfnIndex(
            self, f'{self.PREFIX}-KendraIndex',
            edition = 'DEVELOPER_EDITION',
            name = f'{self.PREFIX}-HealthLakeNotes',
            role_arn = self.kendra_instance_role.attr_arn,
        )


#--------
    # kendra data source role
    
        self.kendra_data_source_instance_role = aws_iam.Role(
            self,
            f'{self.PREFIX}-KDSrc-ServiceRole', 
            role_name=f'{self.PREFIX}-KDSrc-ServiceRole',
            assumed_by=aws_iam.ServicePrincipal('kendra.amazonaws.com'))
    
    
        self.kendra_data_source_instance_role.add_to_policy(aws_iam.PolicyStatement(
            effect=aws_iam.Effect.ALLOW,
            actions=[
                'kendra:BatchPutDocument',
                'kendra:BatchDeleteDocument',
                ],
            resources=[self.indexKendra.attr_arn]
        ))
        


        self.s3_loc.grant_read(self.kendra_data_source_instance_role)

        # print(dir(kendra.CfnDataSource.DataSourceInclusionsExclusionsStringsProperty))
        
        self.datasourceKendra = kendra.CfnDataSource(
            self, f'{self.PREFIX}-Data-S3-HealthLake',
            name = f'{self.PREFIX}-Data-S3-HealthLake',
            index_id = self.indexKendra.attr_id,
            type = 'S3',
            data_source_configuration=kendra.CfnDataSource.DataSourceConfigurationProperty(
                s3_configuration=kendra.CfnDataSource.S3DataSourceConfigurationProperty(
                    bucket_name=self.s3_loc.bucket_name,
                    # inclusion_prefixes=kendra.CfnDataSource.DataSourceInclusionsExclusionsStringsProperty(
                    #     data_source_inclusions_exclusions_strings=["source/"]
                    # ),
                )
            ),
            role_arn = self.kendra_data_source_instance_role.role_arn,
        )
        
        self.datasourceKendra.add_override("Properties.DataSourceConfiguration.S3Configuration.InclusionPrefixes", ['source/'])
  


        ## **************** Create resources **************** 
        self.createLambdaFunctions()
        self.setLambdaTriggers()

        

        # QueuePolicy
        self.queue_policy = sqs.CfnQueuePolicy(self, "QueuePolicy", 
            queues = [self.comprehend_complete_sqs.ref],
            policy_document = {
                "Version" : "2008-10-17",
                "Id" : "__default_policy_ID",
                "Statement" : [{
                    "Sid" : "__owner_statement",
                    "Effect" : "Allow",
                    "Principal" : {
                        "AWS": "*"
                    },
                    "Action" : "SQS:SendMessage",
                    "Resource" : f'arn:aws:sqs:us-east-1:{core.Aws.ACCOUNT_ID}:{self.comprehend_complete_sqs.queue_name}', # self.comprehend_complete_sqs.ref
                    "Condition": {
                        "StringEquals": {
                        "aws:SourceAccount": f'{core.Aws.ACCOUNT_ID}'
                        },
                        "ArnLike": {
                        "aws:SourceArn": f'arn:aws:s3:*:*:{self.s3_loc.bucket_name}'
                        }
                    }
                }]                    
            }
        )
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Parameters
        parameters = core.CfnParameter(
            self, "SourceBucket",
            description="Building on AWS Cognito Stack Modified https://github.com/rosberglinhares/CloudFormationCognitoCustomResources",
            default="default"
        )

        LogoutURL = core.CfnParameter(
            self, "LogoutURL",
            type="String",
            default="http://localhost"
        )

        CallbackURL = core.CfnParameter(
            self, "CallbackURL",
            type="String",
            default="http://localhost/callback"
        )

        AppDomain = core.CfnParameter(
            self, "AppDomain",
            type="String",
            default="default"
        )
        
        # CognitoSNSPolicy
        CognitoSNSPolicy = iam.CfnManagedPolicy(
            self, 'CognitoSNSPolicy',
            description='Managed policy to allow Amazon Cognito to access SNS',
            policy_document={
                "Version": "2012-10-17",
                "Statement": {
                    "Effect": "Allow",
                    "Action": ["sns:publish"],
                    "Resource": "*"
                }
            })

        # SNSRole
        SNSRole = iam.CfnRole(
            self, "SNSRole",
            role_name="SNSRole",
            managed_policy_arns=[CognitoSNSPolicy.ref],
            assume_role_policy_document={
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Action": ["sts:AssumeRole"],
                        "Principal": {"Service": ["cognito-idp.amazonaws.com"]}
                    }]
            }
        )
        SNSRole.add_depends_on(CognitoSNSPolicy)

        # CognitoUserPool
        CognitoUserPool = cognito.CfnUserPool(
            self, 'UserPool',
            user_pool_name='photos-pool',
            alias_attributes=[
                "email", "phone_number"],
            auto_verified_attributes=[
                "email"],
            email_verification_message="Hi, Your verification code is <br/>{####}\n",
            email_verification_subject="EDX Email Verification",
            mfa_configuration="OPTIONAL",
            policies={
                "passwordPolicy": {
                    "minimumLength": 8,
                    "requireLowercase": True,
                    "requireNumbers": True,
                    "requireSymbols": True,
                    "requireUppercase": True
                }
            },
            schema=[{
                "attributeDataType": "String",
                "mutable": False,
                "name": "nickname",
                "required": True
            },
                {
                "attributeDataType": "String",
                "mutable": False,
                "name": "email",
                "required": True
            },
                {
                "attributeDataType": "String",
                "mutable": False,
                "name": "phone_number",
                "required": True
            }],
            sms_configuration={
                "externalId": "%s-external" % (core.Aws.STACK_NAME),
                "snsCallerArn": SNSRole.attr_arn
            }
        )

        # CognitoUserPoolClient
        CognitoUserPoolClient = cognito.CfnUserPoolClient(
            self, "UserPoolClient",
            client_name="WebsiteClient",
            generate_secret=True,
            user_pool_id=CognitoUserPool.ref
        )

        # CognitoCustomResourceRole
        CustomResourceRole = iam.CfnRole(
            self, "CustomResourceRole",
            role_name="cognito-resource-role",
            assume_role_policy_document={
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": [
                                "lambda.amazonaws.com"
                            ]
                        },
                        "Action": [
                            "sts:AssumeRole"
                        ]
                    }
                ]
            },
            policies=[
                {
                    "policyName": "writeCloudWatchLogs",
                    "policyDocument": {
                        "Version": "2012-10-17",
                        "Statement": [
                            {
                                "Effect": "Allow",
                                "Action": "logs:CreateLogGroup",
                                "Resource": "arn:aws:logs:*:*:*"
                            },
                            {
                                "Effect": "Allow",
                                "Action": "logs:CreateLogStream",
                                "Resource": "arn:aws:logs:*:*:*"
                            },
                            {
                                "Effect": "Allow",
                                "Action": "logs:PutLogEvents",
                                "Resource": "arn:aws:logs:*:*:*"
                            }
                        ]
                    }
                },
                {
                    "policyName": "updateUserPoolClient",
                    "policyDocument": {
                        "Version": "2012-10-17",
                        "Statement": [
                            {
                                "Effect": "Allow",
                                "Action": "cognito-idp:UpdateUserPoolClient",
                                "Resource": "arn:aws:cognito-idp:*:*:userpool/*"
                            }
                        ]
                    }
                },
                {
                    "policyName": "manageUserPoolDomain",
                    "policyDocument": {
                        "Version": "2012-10-17",
                        "Statement": [
                            {
                                "Effect": "Allow",
                                "Action": "cognito-idp:CreateUserPoolDomain",
                                "Resource": "arn:aws:cognito-idp:*:*:userpool/*"
                            },
                            {
                                "Effect": "Allow",
                                "Action": "cognito-idp:DeleteUserPoolDomain",
                                "Resource": "arn:aws:cognito-idp:*:*:userpool/*"
                            },
                            {
                                "Effect": "Allow",
                                "Action": "cognito-idp:DescribeUserPoolDomain",
                                "Resource": "*"
                            },
                            {
                                "Effect": "Allow",
                                "Action": "cognito-idp:DescribeUserPoolClient",
                                "Resource": "*"
                            }
                        ]
                    }
                },
                {
                    "policyName": "invokeLambdaFunction",
                    "policyDocument": {
                        "Version": "2012-10-17",
                        "Statement": [
                            {
                                "Effect": "Allow",
                                "Action": "lambda:InvokeFunction",
                                "Resource": "arn:aws:lambda:*:*:function:*"
                            }
                        ]
                    }
                },
            ]
        )

        # CognitoUserPoolClientClientSettings
        with open("./cdk/CognitoUserPoolClientClientSettings/index.js", encoding="utf-8") as fp:
            code_body = fp.read()

        CognitoUserPoolClientClientSettings = cfn.CustomResource(
            self, "CognitoUserPoolClientClientSettings",
            provider=cfn.CustomResourceProvider.lambda_(
                lambda_.SingletonFunction(
                    self, "CognitoUserPoolClientClientSettingsLambda",
                    uuid="f7d4f730-4ee1-11e8-9c2d-fa7ae01bbebc",
                    code=lambda_.InlineCode(code_body),
                    handler="index.handler",
                    runtime=lambda_.Runtime.NODEJS_8_10,
                    role=iam.Role.from_role_arn(
                        self, 'CustomResourceRoleiam', role_arn=CustomResourceRole.attr_arn)
                )
            ),
            properties={"UserPoolId": CognitoUserPool.ref,
                        "UserPoolClientId": CognitoUserPoolClient.ref,
                        "AppDomain": AppDomain.value_as_string,
                        "SupportedIdentityProviders": ['COGNITO'],
                        "CallbackURL": CallbackURL.value_as_string,
                        "LogoutURL": LogoutURL.value_as_string,
                        "AllowedOAuthFlowsUserPoolClient": True,
                        "AllowedOAuthFlows": ['code'],
                        "AllowedOAuthScopes": ['openid']
                        },
        )

        # CognitoIdPool
        CognitoIdPool = cognito.CfnIdentityPool(
            self, 'CognitoIdPool',
            identity_pool_name='edxcognitoidpool',
            cognito_identity_providers=[{
                "clientId": CognitoUserPoolClient.ref,
                "providerName": CognitoUserPool.attr_provider_name
            }],
            allow_unauthenticated_identities=False
        )

        # Output
        core.CfnOutput(self, "CognitoUserPoolIdOutput",
                       value=CognitoUserPool.ref,
                       description="The Pool ID of the Cognito User Pool",
                       export_name="CognitoUserPoolId"
                       )
        core.CfnOutput(self, "CognitoUserPoolProviderURLOutput",
                       value=CognitoUserPool.attr_provider_url,
                       description="The Pool ProviderURL of the Cognito User Pool",
                       export_name="CognitoUserPoolProviderURL"
                       )
        core.CfnOutput(self, "CognitoUserPoolArnOutput",
                       value=CognitoUserPool.attr_arn,
                       description="The Pool Arn of the Cognito User Pool",
                       export_name="CognitoUserPoolArn"
                       )
        core.CfnOutput(self, "CognitoUserPoolClientIdOutput",
                       value=CognitoUserPoolClient.ref,
                       description="The App Client ID ",
                       export_name="CognitoUserPoolClientId"
                       )
        core.CfnOutput(self, "ClientSecretOutput",
                       value=core.Fn.get_att(
                           "CognitoUserPoolClientClientSettings", "ClientSecret").to_string(),
                       description="The Client Secret ",
                       export_name="ClientSecret"
                       )
    def _add_batch_user_role(self):
        batch_user_role_statement = iam.PolicyStatement(
            effect=iam.Effect.ALLOW, actions=["sts:AssumeRole"])
        batch_user_role_statement.add_account_root_principal()

        return iam.CfnRole(
            self.stack_scope,
            "PclusterBatchUserRole",
            path=self._cluster_scoped_iam_path(),
            max_session_duration=36000,
            assume_role_policy_document=iam.PolicyDocument(
                statements=[batch_user_role_statement]),
            policies=[
                iam.CfnRole.PolicyProperty(
                    policy_name="BatchUserPolicy",
                    policy_document=iam.PolicyDocument(
                        statements=[
                            iam.PolicyStatement(
                                actions=[
                                    "batch:SubmitJob",
                                    "cloudformation:DescribeStacks",
                                    "ecs:ListContainerInstances",
                                    "ecs:DescribeContainerInstances",
                                    "logs:GetLogEvents",
                                    "logs:FilterLogEvents",
                                    "s3:PutObject",
                                    "s3:Get*",
                                    "s3:DeleteObject",
                                    "iam:PassRole",
                                ],
                                effect=iam.Effect.ALLOW,
                                resources=[
                                    self._job_definition_serial.ref,
                                    self._job_definition_mnp.ref,
                                    self._job_queue.ref,
                                    self._job_role.attr_arn,
                                    self._format_arn(
                                        service="cloudformation",
                                        resource=f"stack/{self.stack_name}/*"),
                                    # ToDo: This resource is for substack. Check if this is necessary for pcluster3
                                    self._format_arn(
                                        service="cloudformation",
                                        resource=f"stack/{self.stack_name}-*/*"
                                    ),
                                    self._format_arn(
                                        service="s3",
                                        resource=
                                        f"{self.bucket.name}/{self.bucket.artifact_directory}/batch/*",
                                        region="",
                                        account="",
                                    ),
                                    self._format_arn(
                                        service="ecs",
                                        resource=
                                        f"cluster/AWSBatch-{self._get_compute_env_prefix()}*",
                                        region=self._stack_region,
                                        account=self._stack_account,
                                    ),
                                    self._format_arn(
                                        service="ecs",
                                        resource="container-instance/*",
                                        region=self._stack_region,
                                        account=self._stack_account,
                                    ),
                                    self._format_arn(
                                        service="logs",
                                        resource=
                                        "log-group:/aws/batch/job:log-stream:*",
                                        region=self._stack_region,
                                        account=self._stack_account,
                                    ),
                                ],
                            ),
                            iam.PolicyStatement(
                                effect=iam.Effect.ALLOW,
                                actions=["s3:List*"],
                                resources=[
                                    self._format_arn(service="s3",
                                                     resource=self.bucket.name,
                                                     region="",
                                                     account=""),
                                ],
                            ),
                            iam.PolicyStatement(
                                effect=iam.Effect.ALLOW,
                                actions=[
                                    "batch:DescribeJobQueues",
                                    "batch:TerminateJob",
                                    "batch:DescribeJobs",
                                    "batch:CancelJob",
                                    "batch:DescribeJobDefinitions",
                                    "batch:ListJobs",
                                    "batch:DescribeComputeEnvironments",
                                    "ec2:DescribeInstances",
                                ],
                                resources=["*"],
                            ),
                        ], ),
                ),
                iam.CfnRole.PolicyProperty(
                    policy_name="cfnDescribeStacks",
                    policy_document=iam.PolicyDocument(
                        statements=[
                            iam.PolicyStatement(
                                actions=["cloudformation:DescribeStacks"],
                                effect=iam.Effect.ALLOW,
                                resources=[
                                    self._format_arn(
                                        service="cloudformation",
                                        resource=f"stack/{self.stack_name}/*",
                                    ),
                                    self._format_arn(
                                        # ToDo: This resource is for substack. Check if this is necessary for pcluster3
                                        service="cloudformation",
                                        resource=f"stack/{self.stack_name}-*/*",
                                    ),
                                ],
                                sid="CloudWatchLogsPolicy",
                            ),
                        ], ),
                ),
            ],
        )
 def _add_job_role(self):
     return iam.CfnRole(
         self.stack_scope,
         "JobRole",
         path=self._cluster_scoped_iam_path(),
         managed_policy_arns=[
             self._format_arn(service="iam",
                              account="aws",
                              region="",
                              resource="policy/AmazonS3ReadOnlyAccess"),
             self._format_arn(
                 service="iam",
                 account="aws",
                 region="",
                 resource=
                 "policy/service-role/AmazonECSTaskExecutionRolePolicy",
             ),
         ],
         assume_role_policy_document=get_assume_role_policy_document(
             "ecs-tasks.amazonaws.com"),
         policies=[
             iam.CfnRole.PolicyProperty(
                 policy_name="s3PutObject",
                 policy_document=iam.PolicyDocument(statements=[
                     iam.PolicyStatement(
                         actions=["s3:PutObject"],
                         effect=iam.Effect.ALLOW,
                         resources=[
                             self._format_arn(
                                 service="s3",
                                 resource=
                                 f"{self.bucket.name}/{self.bucket.artifact_directory}/batch/*",
                                 region="",
                                 account="",
                             ),
                         ],
                         sid="CloudWatchLogsPolicy",
                     ),
                 ], ),
             ),
             iam.CfnRole.PolicyProperty(
                 policy_name="cfnDescribeStacks",
                 policy_document=iam.PolicyDocument(
                     statements=[
                         iam.PolicyStatement(
                             actions=["cloudformation:DescribeStacks"],
                             effect=iam.Effect.ALLOW,
                             resources=[
                                 self._format_arn(
                                     service="cloudformation",
                                     resource=f"stack/{self.stack_name}/*",
                                 ),
                                 self._format_arn(
                                     # ToDo: This resource is for substack. Check if this is necessary for pcluster3
                                     service="cloudformation",
                                     resource=f"stack/{self.stack_name}-*/*",
                                 ),
                             ],
                             sid="CloudWatchLogsPolicy",
                         ),
                     ], ),
             ),
         ],
     )
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Exercise 9
        # LambdaExecutionRole
        lambda_execution_role = iam.CfnRole(
            self,
            "LambdaExecutionRole",
            role_name="lambda-execution-role",
            assume_role_policy_document={
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "Service": ["lambda.amazonaws.com"]
                    },
                    "Action": ["sts:AssumeRole"]
                }]
            },
            path="/",
            policies=[{
                "policyName": "root",
                "policyDocument": {
                    "Version":
                    "2012-10-17",
                    "Statement": [{
                        "Effect":
                        "Allow",
                        "Action": [
                            "logs:CreateLogGroup", "logs:CreateLogStream",
                            "logs:PutLogEvents"
                        ],
                        "Resource":
                        "arn:aws:logs:*:*:*"
                    }, {
                        "Effect": "Allow",
                        "Action": ["ec2:Describe*"],
                        "Resource": "*"
                    }]
                }
            }])

        # EdxProjectCloud9
        edx_project_cloud9 = cloud9.CfnEnvironmentEC2(
            self,
            "EdxProjectCloud9",
            automatic_stop_time_minutes=30,
            instance_type="t2.micro",
            name="BuildingOnAWS%s" % (core.Aws.STACK_NAME),
            subnet_id=core.Fn.import_value("PublicSubnet1"))
        edx_project_cloud9.apply_removal_policy(core.RemovalPolicy.DESTROY)

        # CustomFunction
        custom_function = lambda_.CfnFunction(
            self,
            "CustomFunction",
            runtime="nodejs8.10",
            handler="index.handler",
            code={
                "zipFile":
                "const response = require('cfn-response');\n"
                "const AWS = require('aws-sdk');\n"
                "exports.handler = (event, context) => {\n"
                "let params = {\n"
                "Filters: [\n"
                "{\n"
                "Name: 'tag:aws:cloud9:environment',\n"
                "Values: [\n"
                "event.ResourceProperties.EdxProjectCloud9\n"
                "]\n"
                "}\n"
                "]\n"
                "};\n"
                "let ec2 = new AWS.EC2();\n"
                "ec2.describeInstances(params, (err, data) => {\n"
                "if (err) {\n"
                "console.log(err, err.stack); // an error occurred\n"
                "response.send(event, context, response.FAILED, {});\n"
                "}else{\n"
                "let responseData = {Value: data.Reservations[0].Instances[0].SecurityGroups[0].GroupId};\n"
                "console.log(responseData);\n"
                "response.send(event, context, response.SUCCESS, responseData);\n"
                "}\n"
                "});\n"
                "};"
            },
            timeout=30,
            role=lambda_execution_role.attr_arn)

        # CustomResource
        custom_resource = cfn.CfnCustomResource(
            self,
            "CustomResource",
            service_token=custom_function.attr_arn,
        )
        custom_resource.add_override("Properties.EdxProjectCloud9",
                                     edx_project_cloud9.ref)

        # Output
        core.CfnOutput(self,
                       "EdxProjectCloud9Output",
                       value=edx_project_cloud9.ref,
                       description="Edx User Cloud9",
                       export_name="EdxProjectCloud9")

        core.CfnOutput(self,
                       "EdxProjectCloud9SgOutput",
                       value=core.Fn.get_att(custom_resource.logical_id,
                                             "Value").to_string(),
                       description="Edx User Cloud9 Security Group ID",
                       export_name="EdxProjectCloud9Sg")
Esempio n. 17
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Set Parameters
        db_password_parameters = core.CfnParameter(
            self,
            "DBPassword",
            no_echo=True,
            description="New account and RDS password",
            min_length=1,
            max_length=41,
            constraint_description=
            "the password must be between 1 and 41 characters",
            default="DBPassword")

        # LambdaExecutionRole
        LambdaExecutionRole = iam.CfnRole(
            self,
            "LabelsLambdaExecutionRole",
            assume_role_policy_document={
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "Service": ["lambda.amazonaws.com"]
                    },
                    "Action": ["sts:AssumeRole"]
                }]
            },
            managed_policy_arns=[
                "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",
                "arn:aws:iam::aws:policy/AmazonRekognitionReadOnlyAccess",
                "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",
                "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"
            ],
            policies=[{
                "policyName": "root",
                "policyDocument": {
                    "Version":
                    "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": ["logs:*"],
                            "Resource": "arn:aws:logs:*:*:*"
                        },
                    ]
                }
            }])

        # S3 Bucket
        source_bucket = "sourcebucketname%s" % (core.Aws.ACCOUNT_ID)

        # LabelsLambda
        LabelsLambda = lambda_.CfnFunction(
            self,
            "LabelsLambda",
            handler="lambda_function.lambda_handler",
            role=LambdaExecutionRole.attr_arn,
            code={
                "s3Bucket": source_bucket,
                "s3Key": "lambda.zip"
            },
            runtime="python3.6",
            timeout=120,
            tracing_config={"mode": "Active"},
            vpc_config={
                "securityGroupIds":
                [core.Fn.import_value("LambdaSecurityGroupOutput")],
                "subnetIds": [
                    core.Fn.import_value("PrivateSubnet1"),
                    core.Fn.import_value("PrivateSubnet2")
                ]
            },
            environment={
                "variables": {
                    "DATABASE_HOST": core.Fn.import_value("MyDBEndpoint"),
                    "DATABASE_USER": "******",
                    "DATABASE_PASSWORD":
                    db_password_parameters.value_as_string,
                    "DATABASE_DB_NAME": "Photos"
                }
            })

        # UploadQueue
        upload_queue = sqs.CfnQueue(self,
                                    "UploadQueue",
                                    queue_name="uploads-queue",
                                    message_retention_period=12800,
                                    visibility_timeout=300)

        # UploadSNSTopic
        upload_sns_topic = sns.CfnTopic(
            self,
            "UploadSNSTopic",
            display_name="uploads-topic",
            subscription=[{
                "endpoint": upload_queue.attr_arn,
                "protocol": "sqs"
            }, {
                "endpoint": LabelsLambda.attr_arn,
                "protocol": "lambda"
            }],
        )

        # QueuePolicy
        queue_policy = sqs.CfnQueuePolicy(
            self,
            "QueuePolicy",
            queues=[upload_queue.ref],
            policy_document={
                "Version":
                "2012-10-17",
                "Id":
                "QueuePolicy",
                "Statement": [{
                    "Sid": "Allow-SendMessage-To-Queues-From-SNS-Topic",
                    "Effect": "Allow",
                    "Principal": "*",
                    "Action": ["SQS:SendMessage"],
                    "Resource": "*",
                    "Condition": {
                        "ArnEquals": {
                            "aws:SourceArn": "%s" % (upload_sns_topic.ref)
                        }
                    }
                }]
            })

        # UploadTopicPolicy
        upload_topic_policy = sns.CfnTopicPolicy(
            self,
            "UploadTopicPolicy",
            policy_document={
                "Version":
                "2012-10-17",
                "Id":
                "QueuePolicy",
                "Statement": [{
                    "Sid": "Allow-S3-Publish",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "s3.amazonaws.com"
                    },
                    "Action": ["SNS:Publish"],
                    "Resource": upload_sns_topic.ref,
                    "Condition": {
                        "StringEquals": {
                            "aws:SourceAccount": "!Sub '${AWS::AccountId}'"
                        },
                        "ArnLike": {
                            "aws:SourceArn": {
                                "Fn::Join": [
                                    "",
                                    [
                                        "arn:aws:s3:*:*:",
                                        "!Sub 'imagebucketsns${AWS::AccountId}'"
                                    ]
                                ]
                            }
                        }
                    },
                }]
            },
            topics=[upload_sns_topic.ref])

        # ImageS3Bucket
        image_s3_bucket = s3.CfnBucket(self,
                                       "ImageS3Bucket",
                                       bucket_name="imagebucketsns%s" %
                                       (core.Aws.ACCOUNT_ID),
                                       notification_configuration={
                                           "topicConfigurations": [{
                                               "event":
                                               's3:ObjectCreated:*',
                                               "topic":
                                               upload_sns_topic.ref
                                           }]
                                       })
        image_s3_bucket.add_depends_on(upload_topic_policy)
        image_s3_bucket.apply_removal_policy(core.RemovalPolicy.DESTROY)

        # ImageS3BucketPermission
        ImageS3BucketPermission = lambda_.CfnPermission(
            self,
            "ImageS3BucketPermission",
            action="lambda:InvokeFunction",
            function_name=LabelsLambda.attr_arn,
            principal="sns.amazonaws.com",
            source_arn=upload_sns_topic.ref)

        # Outputs
        core.CfnOutput(self,
                       "ImageS3BucketOutput",
                       value=image_s3_bucket.ref,
                       description="Image S3 Bucket",
                       export_name="ImageS3Bucket")

        core.CfnOutput(self,
                       "LabelsLambdaOutput",
                       value=LabelsLambda.ref,
                       description="Labels Lambda",
                       export_name="LabelsLambda")
Esempio n. 18
0
 def __init__(self, scope: core.Construct, id: str, data, iam_vars) -> None:
     super().__init__(scope, id)
     # VPC
     vpc = ec2.CfnVPC(self, "cdk-vpc", cidr_block=data["vpc"])
     igw = ec2.CfnInternetGateway(self, id="igw")
     ec2.CfnVPCGatewayAttachment(self,
                                 id="igw-attach",
                                 vpc_id=vpc.ref,
                                 internet_gateway_id=igw.ref)
     public_route_table = ec2.CfnRouteTable(self,
                                            id="public_route_table",
                                            vpc_id=vpc.ref)
     ec2.CfnRoute(self,
                  id="public_route",
                  route_table_id=public_route_table.ref,
                  destination_cidr_block="0.0.0.0/0",
                  gateway_id=igw.ref)
     public_subnets = []
     for i, s in enumerate(data["subnets"]["public"]):
         subnet = ec2.CfnSubnet(self,
                                id="public_{}".format(s),
                                cidr_block=s,
                                vpc_id=vpc.ref,
                                availability_zone=core.Fn.select(
                                    i, core.Fn.get_azs()),
                                map_public_ip_on_launch=True)
         public_subnets.append(subnet)
         ec2.CfnSubnetRouteTableAssociation(
             self,
             id="public_{}_association".format(s),
             route_table_id=public_route_table.ref,
             subnet_id=subnet.ref)
     eip = ec2.CfnEIP(self, id="natip")
     nat = ec2.CfnNatGateway(self,
                             id="nat",
                             allocation_id=eip.attr_allocation_id,
                             subnet_id=public_subnets[0].ref)
     private_route_table = ec2.CfnRouteTable(self,
                                             id="private_route_table",
                                             vpc_id=vpc.ref)
     ec2.CfnRoute(self,
                  id="private_route",
                  route_table_id=private_route_table.ref,
                  destination_cidr_block="0.0.0.0/0",
                  nat_gateway_id=nat.ref)
     private_subnets = []
     for i, s in enumerate(data["subnets"]["private"]):
         subnet = ec2.CfnSubnet(self,
                                id="private_{}".format(s),
                                cidr_block=s,
                                vpc_id=vpc.ref,
                                availability_zone=core.Fn.select(
                                    i, core.Fn.get_azs()),
                                map_public_ip_on_launch=False)
         private_subnets.append(subnet)
         ec2.CfnSubnetRouteTableAssociation(
             self,
             id="private_{}_association".format(s),
             route_table_id=private_route_table.ref,
             subnet_id=subnet.ref)
     # Security groups
     lb_sg = ec2.CfnSecurityGroup(self,
                                  id="lb",
                                  group_description="LB SG",
                                  vpc_id=vpc.ref)
     lambda_sg = ec2.CfnSecurityGroup(self,
                                      id="lambda",
                                      group_description="Lambda SG",
                                      vpc_id=vpc.ref)
     public_prefix = ec2.CfnPrefixList(self,
                                       id="cidr_prefix",
                                       address_family="IPv4",
                                       max_entries=1,
                                       prefix_list_name="public",
                                       entries=[{
                                           "cidr": "0.0.0.0/0",
                                           "description": "Public"
                                       }])
     _sg_rules = [{
         'sg':
         lb_sg.attr_group_id,
         'rules': [{
             "direction": "ingress",
             "description": "HTTP from Internet",
             "from_port": 80,
             "to_port": 80,
             "protocol": "tcp",
             "cidr_blocks": public_prefix.ref
         }, {
             "direction": "egress",
             "description": "LB to Lambda",
             "from_port": 80,
             "to_port": 80,
             "protocol": "tcp",
             "source_security_group_id": lambda_sg.attr_group_id
         }]
     }, {
         "sg":
         lambda_sg.attr_group_id,
         "rules": [{
             "direction": "ingress",
             "description": "HTTP from LB",
             "from_port": 80,
             "to_port": 80,
             "protocol": "tcp",
             "source_security_group_id": lb_sg.attr_group_id
         }, {
             "direction": "egress",
             "description": "All to Internet",
             "from_port": 0,
             "to_port": 65535,
             "protocol": "tcp",
             "cidr_blocks": public_prefix.ref
         }]
     }]
     for ruleset in _sg_rules:
         for rule in ruleset["rules"]:
             if rule["direction"] == "ingress":
                 ec2.CfnSecurityGroupIngress(
                     self,
                     id=rule["description"].replace(" ", "_"),
                     description=rule["description"],
                     to_port=rule["to_port"],
                     from_port=rule["from_port"],
                     ip_protocol=rule["protocol"],
                     group_id=ruleset["sg"],
                     source_prefix_list_id=rule["cidr_blocks"]
                     if "cidr_blocks" in rule else None,
                     source_security_group_id=rule[
                         "source_security_group_id"]
                     if "source_security_group_id" in rule else None)
             else:
                 ec2.CfnSecurityGroupEgress(
                     self,
                     id=rule["description"].replace(" ", "_"),
                     description=rule["description"],
                     to_port=rule["to_port"],
                     from_port=rule["from_port"],
                     ip_protocol=rule["protocol"],
                     group_id=ruleset["sg"],
                     destination_prefix_list_id=rule["cidr_blocks"]
                     if "cidr_blocks" in rule else None,
                     destination_security_group_id=rule[
                         "source_security_group_id"]
                     if "source_security_group_id" in rule else None)
     # IAM
     assume_policy_doc = iam.PolicyDocument()
     for statement in iam_vars["assume"]["Statement"]:
         _statement = iam.PolicyStatement(actions=[statement["Action"]], )
         _statement.add_service_principal(statement["Principal"]["Service"])
         assume_policy_doc.add_statements(_statement)
     role = iam.CfnRole(self,
                        id="iam_role",
                        path="/",
                        assume_role_policy_document=assume_policy_doc)
     role_policy_doc = iam.PolicyDocument()
     for statement in iam_vars["policy"]["Statement"]:
         _statement = iam.PolicyStatement(actions=statement["Action"],
                                          resources=["*"])
         role_policy_doc.add_statements(_statement)
     policy = iam.CfnPolicy(self,
                            id="iam_policy",
                            policy_document=role_policy_doc,
                            policy_name="cdkPolicy",
                            roles=[role.ref])
     # Lambda
     shutil.make_archive("../lambda", 'zip', "../lambda/")
     s3_client = boto3.client('s3')
     s3_client.upload_file("../lambda.zip", "cloudevescops-zdays-demo",
                           "cdk.zip")
     function = lmd.CfnFunction(self,
                                id="lambda_function",
                                handler="lambda.lambda_handler",
                                role=role.attr_arn,
                                runtime="python3.7",
                                code={
                                    "s3Bucket": "cloudevescops-zdays-demo",
                                    "s3Key": "cdk.zip"
                                },
                                vpc_config={
                                    "securityGroupIds": [lambda_sg.ref],
                                    "subnetIds":
                                    [s.ref for s in private_subnets]
                                },
                                environment={"variables": {
                                    "TOOL": "CDK"
                                }})
     # LB
     lb = alb.CfnLoadBalancer(self,
                              id="alb",
                              name="lb-cdk",
                              scheme="internet-facing",
                              type="application",
                              subnets=[s.ref for s in public_subnets],
                              security_groups=[lb_sg.ref])
     lmd.CfnPermission(self,
                       id="lambda_permis",
                       action="lambda:InvokeFunction",
                       function_name=function.ref,
                       principal="elasticloadbalancing.amazonaws.com")
     tg = alb.CfnTargetGroup(self,
                             id="alb_tg",
                             name="lambda-cdk",
                             target_type="lambda",
                             health_check_enabled=True,
                             health_check_interval_seconds=40,
                             health_check_path="/",
                             health_check_timeout_seconds=30,
                             targets=[{
                                 "id":
                                 function.get_att("Arn").to_string()
                             }],
                             matcher={"httpCode": "200"})
     alb.CfnListener(self,
                     id="listener",
                     default_actions=[{
                         "type": "forward",
                         "targetGroupArn": tg.ref
                     }],
                     load_balancer_arn=lb.ref,
                     port=80,
                     protocol="HTTP")
     core.CfnOutput(self, id="fqdn", value=lb.attr_dns_name)
Esempio n. 19
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        current_directory = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
        allowed_values = yaml.load(open(
            os.path.join(current_directory, "..", "..",
                         "allowed_values.yaml")),
                                   Loader=yaml.SafeLoader)
        ami_mapping = {"AMI": {"OEJITSI": AMI_NAME}}
        for region in generated_ami_ids.keys():
            ami_mapping[region] = {"OEJITSI": generated_ami_ids[region]}
        aws_ami_region_map = core.CfnMapping(self,
                                             "AWSAMIRegionMap",
                                             mapping=ami_mapping)

        # utility function to parse the unique id from the stack id for
        # shorter resource names  using cloudformation functions
        def append_stack_uuid(name):
            return core.Fn.join("-", [
                name,
                core.Fn.select(
                    0,
                    core.Fn.split(
                        "-",
                        core.Fn.select(2, core.Fn.split(
                            "/", core.Aws.STACK_ID))))
            ])

        #
        # PARAMETERS
        #

        cidr_block_param = core.CfnParameter(
            self,
            "IngressCidrBlock",
            allowed_pattern="((\d{1,3})\.){3}\d{1,3}/\d{1,2}",
            default="0.0.0.0/0",
            description=
            "Required: A CIDR block to restrict access to the Jitsi application. Leave as 0.0.0.0/0 to allow public access from internet."
        )
        ec2_instance_type_param = core.CfnParameter(
            self,
            "InstanceType",
            allowed_values=allowed_values["allowed_instance_types"],
            default="t3.xlarge",
            description=
            "Required: The EC2 instance type for the application Auto Scaling Group."
        )
        jitsi_hostname_param = core.CfnParameter(
            self,
            "JitsiHostname",
            description=
            "Required: The hostname to access Jitsi. E.G. 'jitsi.internal.mycompany.com'"
        )
        jitsi_interface_app_name_param = core.CfnParameter(
            self,
            "JitsiInterfaceAppName",
            default="Jitsi Meet",
            description=
            "Optional: Customize the app name on the Jitsi interface.")
        jitsi_interface_default_remote_display_name_param = core.CfnParameter(
            self,
            "JitsiInterfaceDefaultRemoteDisplayName",
            default="Fellow Jitster",
            description=
            "Optional: Customize the default display name for Jitsi users.")
        jitsi_interface_native_app_name_param = core.CfnParameter(
            self,
            "JitsiInterfaceNativeAppName",
            default="Jitsi Meet",
            description=
            "Optional: Customize the native app name on the Jitsi interface.")
        jitsi_interface_show_brand_watermark_param = core.CfnParameter(
            self,
            "JitsiInterfaceShowBrandWatermark",
            allowed_values=["true", "false"],
            default="true",
            description=
            "Optional: Display the watermark logo image in the upper left corner."
        )
        jitsi_interface_show_watermark_for_guests_param = core.CfnParameter(
            self,
            "JitsiInterfaceShowWatermarkForGuests",
            allowed_values=["true", "false"],
            default="true",
            description=
            "Optional: Display the watermark logo image in the upper left corner for guest users. This can be set to override the general setting behavior for guest users."
        )
        jitsi_interface_brand_watermark_param = core.CfnParameter(
            self,
            "JitsiInterfaceBrandWatermark",
            default="",
            description=
            "Optional: Provide a URL to a PNG image to be used as the brand watermark logo image in the upper right corner. File should be publically available for download."
        )
        jitsi_interface_brand_watermark_link_param = core.CfnParameter(
            self,
            "JitsiInterfaceBrandWatermarkLink",
            default="http://jitsi.org",
            description=
            "Optional: Provide a link destination for the brand watermark logo image in the upper right corner."
        )
        jitsi_interface_watermark_param = core.CfnParameter(
            self,
            "JitsiInterfaceWatermark",
            default="",
            description=
            "Optional: Provide a URL to a PNG image to be used as the watermark logo image in the upper left corner. File should be publically available for download."
        )
        jitsi_interface_watermark_link_param = core.CfnParameter(
            self,
            "JitsiInterfaceWatermarkLink",
            default="http://jitsi.org",
            description=
            "Optional: Provide a link destination for the Jitsi watermark logo image in the upper left corner."
        )
        route_53_hosted_zone_name_param = core.CfnParameter(
            self,
            "Route53HostedZoneName",
            description=
            "Required: Route 53 Hosted Zone name in which a DNS record will be created by this template. Must already exist and be the domain part of the Jitsi Hostname parameter, without trailing dot. E.G. 'internal.mycompany.com'"
        )
        notification_email_param = core.CfnParameter(
            self,
            "NotificationEmail",
            default="",
            description=
            "Optional: Specify an email address to get emails about deploys, Let's Encrypt, and other system events."
        )

        #
        # CONDITIONS
        #

        notification_email_exists_condition = core.CfnCondition(
            self,
            "NotificationEmailExistsCondition",
            expression=core.Fn.condition_not(
                core.Fn.condition_equals(notification_email_param.value, "")))

        #
        # RESOURCES
        #

        # vpc
        vpc = Vpc(self, "Vpc")

        # sns
        sns_notification_topic = aws_sns.CfnTopic(
            self,
            "NotificationTopic",
            topic_name="{}-notifications".format(core.Aws.STACK_NAME))
        sns_notification_subscription = aws_sns.CfnSubscription(
            self,
            "NotificationSubscription",
            protocol="email",
            topic_arn=sns_notification_topic.ref,
            endpoint=notification_email_param.value_as_string)
        sns_notification_subscription.cfn_options.condition = notification_email_exists_condition
        iam_notification_publish_policy = aws_iam.PolicyDocument(statements=[
            aws_iam.PolicyStatement(effect=aws_iam.Effect.ALLOW,
                                    actions=["sns:Publish"],
                                    resources=[sns_notification_topic.ref])
        ])

        # cloudwatch
        app_log_group = aws_logs.CfnLogGroup(
            self, "JitsiAppLogGroup", retention_in_days=TWO_YEARS_IN_DAYS)
        app_log_group.cfn_options.update_replace_policy = core.CfnDeletionPolicy.RETAIN
        app_log_group.cfn_options.deletion_policy = core.CfnDeletionPolicy.RETAIN
        system_log_group = aws_logs.CfnLogGroup(
            self, "JitsiSystemLogGroup", retention_in_days=TWO_YEARS_IN_DAYS)
        system_log_group.cfn_options.update_replace_policy = core.CfnDeletionPolicy.RETAIN
        system_log_group.cfn_options.deletion_policy = core.CfnDeletionPolicy.RETAIN

        # iam
        iam_jitsi_instance_role = aws_iam.CfnRole(
            self,
            "JitsiInstanceRole",
            assume_role_policy_document=aws_iam.PolicyDocument(statements=[
                aws_iam.PolicyStatement(
                    effect=aws_iam.Effect.ALLOW,
                    actions=["sts:AssumeRole"],
                    principals=[aws_iam.ServicePrincipal("ec2.amazonaws.com")])
            ]),
            policies=[
                aws_iam.CfnRole.PolicyProperty(
                    policy_document=aws_iam.PolicyDocument(statements=[
                        aws_iam.PolicyStatement(
                            effect=aws_iam.Effect.ALLOW,
                            actions=[
                                "logs:CreateLogStream",
                                "logs:DescribeLogStreams", "logs:PutLogEvents"
                            ],
                            resources=[
                                app_log_group.attr_arn,
                                system_log_group.attr_arn
                            ])
                    ]),
                    policy_name="AllowStreamLogsToCloudWatch"),
                aws_iam.CfnRole.PolicyProperty(
                    policy_document=aws_iam.PolicyDocument(statements=[
                        aws_iam.PolicyStatement(
                            effect=aws_iam.Effect.ALLOW,
                            actions=[
                                "ec2:AssociateAddress", "ec2:DescribeVolumes",
                                "ec2:DescribeTags",
                                "cloudwatch:GetMetricStatistics",
                                "cloudwatch:ListMetrics",
                                "cloudwatch:PutMetricData"
                            ],
                            resources=["*"])
                    ]),
                    policy_name="AllowStreamMetricsToCloudWatch"),
                aws_iam.CfnRole.PolicyProperty(
                    policy_document=aws_iam.PolicyDocument(statements=[
                        aws_iam.PolicyStatement(
                            effect=aws_iam.Effect.ALLOW,
                            actions=["autoscaling:Describe*"],
                            resources=["*"])
                    ]),
                    policy_name="AllowDescribeAutoScaling"),
            ],
            managed_policy_arns=[
                "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
            ])

        # ec2
        jitsi_sg = aws_ec2.CfnSecurityGroup(
            self,
            "JitsiSg",
            group_description="Jitsi security group",
            vpc_id=vpc.id())

        eip = aws_ec2.CfnEIP(self, "Eip", domain="vpc")
        core.Tags.of(eip).add("Name", "{}/Eip".format(core.Aws.STACK_NAME))

        ec2_instance_profile = aws_iam.CfnInstanceProfile(
            self, "JitsiInstanceProfile", roles=[iam_jitsi_instance_role.ref])
        with open("jitsi/jitsi_launch_config_user_data.sh") as f:
            jitsi_launch_config_user_data = f.read()
        ec2_launch_config = aws_autoscaling.CfnLaunchConfiguration(
            self,
            "JitsiLaunchConfig",
            image_id=core.Fn.find_in_map("AWSAMIRegionMap", core.Aws.REGION,
                                         "OEJITSI"),
            instance_type=ec2_instance_type_param.value_as_string,
            iam_instance_profile=ec2_instance_profile.ref,
            security_groups=[jitsi_sg.ref],
            user_data=(core.Fn.base64(
                core.Fn.sub(
                    jitsi_launch_config_user_data, {
                        "JitsiHostname":
                        jitsi_hostname_param.value_as_string,
                        "JitsiPublicIP":
                        eip.ref,
                        "LetsEncryptCertificateEmail":
                        notification_email_param.value_as_string
                    }))))

        # autoscaling
        asg = aws_autoscaling.CfnAutoScalingGroup(
            self,
            "JitsiAsg",
            launch_configuration_name=ec2_launch_config.ref,
            desired_capacity="1",
            max_size="1",
            min_size="1",
            vpc_zone_identifier=vpc.public_subnet_ids())
        asg.cfn_options.creation_policy = core.CfnCreationPolicy(
            resource_signal=core.CfnResourceSignal(count=1, timeout="PT15M"))
        asg.cfn_options.update_policy = core.CfnUpdatePolicy(
            auto_scaling_rolling_update=core.CfnAutoScalingRollingUpdate(
                max_batch_size=1,
                min_instances_in_service=0,
                pause_time="PT15M",
                wait_on_resource_signals=True))
        core.Tags.of(asg).add("Name",
                              "{}/JitsiAsg".format(core.Aws.STACK_NAME))

        jitsi_http_ingress = aws_ec2.CfnSecurityGroupIngress(
            self,
            "JitsiHttpSgIngress",
            cidr_ip=cidr_block_param.value_as_string,
            from_port=80,
            group_id=jitsi_sg.ref,
            ip_protocol="tcp",
            to_port=80)
        jitsi_https_ingress = aws_ec2.CfnSecurityGroupIngress(
            self,
            "JitsiHttpsSgIngress",
            cidr_ip=cidr_block_param.value_as_string,
            from_port=443,
            group_id=jitsi_sg.ref,
            ip_protocol="tcp",
            to_port=443)
        jitsi_fallback_network_audio_video_ingress = aws_ec2.CfnSecurityGroupIngress(
            self,
            "JitsiFallbackNetworkAudioVideoSgIngress",
            cidr_ip=cidr_block_param.value_as_string,
            from_port=4443,
            group_id=jitsi_sg.ref,
            ip_protocol="tcp",
            to_port=4443)
        jitsi_general_network_audio_video_ingress = aws_ec2.CfnSecurityGroupIngress(
            self,
            "JitsiGeneralNetworkAudioVideoSgIngress",
            cidr_ip=cidr_block_param.value_as_string,
            from_port=10000,
            group_id=jitsi_sg.ref,
            ip_protocol="udp",
            to_port=10000)

        # route 53
        record_set = aws_route53.CfnRecordSet(
            self,
            "RecordSet",
            hosted_zone_name=
            f"{route_53_hosted_zone_name_param.value_as_string}.",
            name=jitsi_hostname_param.value_as_string,
            resource_records=[eip.ref],
            type="A")
        # https://github.com/aws/aws-cdk/issues/8431
        record_set.add_property_override("TTL", 60)

        # AWS::CloudFormation::Interface
        self.template_options.metadata = {
            "OE::Patterns::TemplateVersion": template_version,
            "AWS::CloudFormation::Interface": {
                "ParameterGroups": [{
                    "Label": {
                        "default": "Infrastructure Config"
                    },
                    "Parameters": [
                        jitsi_hostname_param.logical_id,
                        route_53_hosted_zone_name_param.logical_id,
                        cidr_block_param.logical_id,
                        ec2_instance_type_param.logical_id,
                        notification_email_param.logical_id
                    ]
                }, {
                    "Label": {
                        "default": "Jitsi Config"
                    },
                    "Parameters": [
                        jitsi_interface_app_name_param.logical_id,
                        jitsi_interface_default_remote_display_name_param.
                        logical_id,
                        jitsi_interface_native_app_name_param.logical_id,
                        jitsi_interface_show_brand_watermark_param.logical_id,
                        jitsi_interface_show_watermark_for_guests_param.
                        logical_id,
                        jitsi_interface_brand_watermark_param.logical_id,
                        jitsi_interface_brand_watermark_link_param.logical_id,
                        jitsi_interface_watermark_param.logical_id,
                        jitsi_interface_watermark_link_param.logical_id,
                    ]
                }, *vpc.metadata_parameter_group()],
                "ParameterLabels": {
                    cidr_block_param.logical_id: {
                        "default": "Ingress CIDR Block"
                    },
                    ec2_instance_type_param.logical_id: {
                        "default": "EC2 instance type"
                    },
                    jitsi_hostname_param.logical_id: {
                        "default": "Jitsi Hostname"
                    },
                    jitsi_interface_app_name_param.logical_id: {
                        "default": "Jitsi Interface App Name"
                    },
                    jitsi_interface_default_remote_display_name_param.logical_id:
                    {
                        "default":
                        "Jitsi Interface Default Remote Display Name"
                    },
                    jitsi_interface_native_app_name_param.logical_id: {
                        "default": "Jitsi Interface Native App Name"
                    },
                    jitsi_interface_show_brand_watermark_param.logical_id: {
                        "default": "Jitsi Interface Show Watermark"
                    },
                    jitsi_interface_show_watermark_for_guests_param.logical_id:
                    {
                        "default": "Jitsi Interface Show Watermark For Guests"
                    },
                    jitsi_interface_brand_watermark_param.logical_id: {
                        "default": "Jitsi Interface Watermark"
                    },
                    jitsi_interface_brand_watermark_link_param.logical_id: {
                        "default": "Jitsi Interface Watermark Link"
                    },
                    jitsi_interface_watermark_param.logical_id: {
                        "default": "Jitsi Interface Watermark"
                    },
                    jitsi_interface_watermark_link_param.logical_id: {
                        "default": "Jitsi Interface Watermark Link"
                    },
                    notification_email_param.logical_id: {
                        "default": "Notification Email"
                    },
                    route_53_hosted_zone_name_param.logical_id: {
                        "default": "AWS Route 53 Hosted Zone Name"
                    },
                    **vpc.metadata_parameter_labels()
                }
            }
        }

        #
        # OUTPUTS
        #

        eip_output = core.CfnOutput(
            self,
            "EipOutput",
            description=
            "The Elastic IP address dynamically mapped to the autoscaling group instance.",
            value=eip.ref)
        endpoint_output = core.CfnOutput(
            self,
            "JitsiUrl",
            description="The URL for the Jitsi instance.",
            value=core.Fn.join(
                "", ["https://", jitsi_hostname_param.value_as_string]))
    def _add_lambda_cleanup(self, policy_statements, build_tags):
        lambda_cleanup_execution_role = None
        if self.custom_cleanup_lambda_role:
            execution_role = self.custom_cleanup_lambda_role
        else:
            # LambdaCleanupPolicies
            self._add_resource_delete_policy(
                policy_statements,
                ["cloudformation:DeleteStack"],
                [
                    self.format_arn(
                        service="cloudformation",
                        resource="stack",
                        resource_name="{0}/{1}".format(
                            self.image_id, self._stack_unique_id()),
                    )
                ],
            )

            self._add_resource_delete_policy(
                policy_statements,
                ["ec2:CreateTags"],
                [
                    self.format_arn(
                        service="ec2",
                        account="",
                        resource="image",
                        region=region,
                        resource_name="*",
                    ) for region in self._get_distribution_regions()
                ],
            )

            self._add_resource_delete_policy(
                policy_statements,
                ["tag:TagResources"],
                ["*"],
            )

            self._add_resource_delete_policy(
                policy_statements,
                [
                    "iam:DetachRolePolicy", "iam:DeleteRole",
                    "iam:DeleteRolePolicy"
                ],
                [
                    self.format_arn(
                        service="iam",
                        resource="role",
                        region="",
                        resource_name="{0}/{1}".format(
                            IAM_ROLE_PATH.strip("/"),
                            self._build_resource_name(
                                IMAGEBUILDER_RESOURCE_NAME_PREFIX + "Cleanup"),
                        ),
                    )
                ],
            )

            self._add_resource_delete_policy(
                policy_statements,
                ["lambda:DeleteFunction", "lambda:RemovePermission"],
                [
                    self.format_arn(
                        service="lambda",
                        resource="function",
                        sep=":",
                        resource_name=self._build_resource_name(
                            IMAGEBUILDER_RESOURCE_NAME_PREFIX),
                    )
                ],
            )

            self._add_resource_delete_policy(
                policy_statements,
                ["logs:DeleteLogGroup"],
                [
                    self.format_arn(
                        service="logs",
                        resource="log-group",
                        sep=":",
                        resource_name="/aws/lambda/{0}:*".format(
                            self._build_resource_name(
                                IMAGEBUILDER_RESOURCE_NAME_PREFIX)),
                    )
                ],
            )

            self._add_resource_delete_policy(
                policy_statements,
                ["iam:RemoveRoleFromInstanceProfile"],
                [
                    self.format_arn(
                        service="iam",
                        resource="instance-profile",
                        region="",
                        resource_name="{0}/{1}".format(
                            IAM_ROLE_PATH.strip("/"),
                            self._build_resource_name(
                                IMAGEBUILDER_RESOURCE_NAME_PREFIX),
                        ),
                    )
                ],
            )

            self._add_resource_delete_policy(
                policy_statements,
                ["iam:DetachRolePolicy", "iam:DeleteRolePolicy"],
                [
                    self.format_arn(
                        service="iam",
                        resource="role",
                        region="",
                        resource_name="{0}/{1}".format(
                            IAM_ROLE_PATH.strip("/"),
                            self._build_resource_name(
                                IMAGEBUILDER_RESOURCE_NAME_PREFIX),
                        ),
                    )
                ],
            )

            self._add_resource_delete_policy(
                policy_statements,
                [
                    "SNS:GetTopicAttributes", "SNS:DeleteTopic",
                    "SNS:Unsubscribe"
                ],
                [
                    self.format_arn(
                        service="sns",
                        resource="{0}".format(
                            self._build_resource_name(
                                IMAGEBUILDER_RESOURCE_NAME_PREFIX)),
                    )
                ],
            )

            policy_document = iam.PolicyDocument(statements=policy_statements)
            managed_lambda_policy = [
                Fn.sub(
                    "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
                ),
            ]

            # LambdaCleanupExecutionRole
            lambda_cleanup_execution_role = iam.CfnRole(
                self,
                "DeleteStackFunctionExecutionRole",
                managed_policy_arns=managed_lambda_policy,
                assume_role_policy_document=get_assume_role_policy_document(
                    "lambda.amazonaws.com"),
                path=IAM_ROLE_PATH,
                policies=[
                    iam.CfnRole.PolicyProperty(
                        policy_document=policy_document,
                        policy_name="LambdaCleanupPolicy",
                    ),
                ],
                tags=build_tags,
                role_name=self._build_resource_name(
                    IMAGEBUILDER_RESOURCE_NAME_PREFIX + "Cleanup"),
            )

            execution_role = lambda_cleanup_execution_role.attr_arn

        # LambdaCleanupEnv
        lambda_env = awslambda.CfnFunction.EnvironmentProperty(
            variables={"IMAGE_STACK_ARN": self.stack_id})

        # LambdaCWLogGroup
        lambda_log = logs.CfnLogGroup(
            self,
            "DeleteStackFunctionLog",
            log_group_name="/aws/lambda/{0}".format(
                self._build_resource_name(IMAGEBUILDER_RESOURCE_NAME_PREFIX)),
        )

        # LambdaCleanupFunction
        lambda_cleanup = awslambda.CfnFunction(
            self,
            "DeleteStackFunction",
            function_name=self._build_resource_name(
                IMAGEBUILDER_RESOURCE_NAME_PREFIX),
            code=awslambda.CfnFunction.CodeProperty(
                s3_bucket=self.config.custom_s3_bucket
                or S3Bucket.get_bucket_name(
                    AWSApi.instance().sts.get_account_id(), get_region()),
                s3_key=self.bucket.get_object_key(S3FileType.CUSTOM_RESOURCES,
                                                  "artifacts.zip"),
            ),
            handler="delete_image_stack.handler",
            memory_size=128,
            role=execution_role,
            runtime="python3.8",
            timeout=900,
            environment=lambda_env,
            tags=build_tags,
        )
        permission = awslambda.CfnPermission(
            self,
            "DeleteStackFunctionPermission",
            action="lambda:InvokeFunction",
            principal="sns.amazonaws.com",
            function_name=lambda_cleanup.attr_arn,
            source_arn=Fn.ref("BuildNotificationTopic"),
        )
        lambda_cleanup.add_depends_on(lambda_log)

        return lambda_cleanup, permission, lambda_cleanup_execution_role, lambda_log
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Exercise 11
        # WebServerRole
        web_server_role = iam.CfnRole(
            self,
            "WebServerRole",
            role_name="ec2-webserver-role",
            assume_role_policy_document={
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "Service": ["ec2.amazonaws.com"]
                    },
                    "Action": ["sts:AssumeRole"]
                }]
            },
            managed_policy_arns=[
                "arn:aws:iam::aws:policy/AmazonS3FullAccess",
                "arn:aws:iam::aws:policy/AmazonRekognitionReadOnlyAccess",
                "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM",
                "arn:aws:iam::aws:policy/AmazonPollyReadOnlyAccess",
                "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
            ],
            path="/",
            policies=[{
                "policyName": "SystemsManagerParameters",
                "policyDocument": {
                    "Version":
                    "2012-10-17",
                    "Statement": [{
                        "Effect": "Allow",
                        "Action": ["ssm:DescribeParameters"],
                        "Resource": "*"
                    }, {
                        "Effect": "Allow",
                        "Action": ["ssm:GetParameters"],
                        "Resource": {
                            "Fn::Sub":
                            "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/edx-*"
                        }
                    }]
                }
            }, {
                "policyName": "LogRolePolicy",
                "policyDocument": {
                    "Version":
                    "2012-10-17",
                    "Statement": [{
                        "Effect":
                        "Allow",
                        "Action": [
                            'logs:CreateLogGroup', 'logs:CreateLogStream',
                            'logs:PutLogEvents', 'logs:DescribeLogStreams'
                        ],
                        "Resource": {
                            "Fn::Sub": "arn:aws:logs::${AWS::Region}:*:*"
                        }
                    }]
                }
            }])

        # WebServerInstanceProfile
        web_server_instance_profile = iam.CfnInstanceProfile(
            self,
            "WebServerInstanceProfile",
            instance_profile_name="webserverinstanceprofile",
            path="/",
            roles=[web_server_role.role_name])

        # WebSecurityGroup
        web_security_group = ec2.CfnSecurityGroup(
            self,
            "WebSecurityGroup",
            group_name="web-server-sg",
            group_description="HTTP traffic",
            vpc_id=core.Fn.import_value("VPC"),
            security_group_ingress=[{
                "ipProtocol": "tcp",
                "fromPort": 80,
                "toPort": 80,
                "cidrIp": "0.0.0.0/0"
            }],
            security_group_egress=[{
                "ipProtocol": "tcp",
                "fromPort": 0,
                "toPort": 65535,
                "cidrIp": "0.0.0.0/0"
            }],
        )

        # LambdaSecurityGroup
        lambda_security_group = ec2.CfnSecurityGroup(
            self,
            "LambdaSecurityGroup",
            group_name="labels-lambda-sg",
            group_description="HTTP traffic",
            vpc_id=core.Fn.import_value("VPC"),
            security_group_egress=[{
                "ipProtocol": "tcp",
                "fromPort": 0,
                "toPort": 65535,
                "cidrIp": "0.0.0.0/0"
            }],
        )

        # Output
        core.CfnOutput(self,
                       "WebServerInstanceProfileOutput",
                       value=web_server_instance_profile.ref,
                       description="Web Server Instance Profile",
                       export_name="WebServerInstanceProfileOutput")

        core.CfnOutput(self,
                       "WebServerRoleOutput",
                       value=web_server_role.attr_arn,
                       description="Web Server Role",
                       export_name="WebServerRoleOutput")

        core.CfnOutput(self,
                       "WebSecurityGroupOutput",
                       value=web_security_group.ref,
                       description="Web Security Group",
                       export_name="WebSecurityGroupOutput")

        core.CfnOutput(self,
                       "LambdaSecurityGroupOutput",
                       value=lambda_security_group.ref,
                       description="Lambda Security Group",
                       export_name="LambdaSecurityGroupOutput")
Esempio n. 22
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # The code that defines your stack goes here

        role01 = iam.CfnRole(
            self,
            id="firehose01_role",
            assume_role_policy_document={
                "Statement": [{
                    "Action": "sts:AssumeRole",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    }
                }],
                "Version":
                "2012-10-17"
            },
            managed_policy_arns=[
                "arn:aws:iam::aws:policy/service-role/AWSLambdaKinesisExecutionRole"
            ])

        policy01 = iam.CfnPolicy(self,
                                 id="firehose01_policy",
                                 policy_name="firehose01_policy",
                                 policy_document={
                                     'Version':
                                     "2012-10-17",
                                     'Statement': [{
                                         "Action": [
                                             's3:AbortMultipartUpload',
                                             's3:GetBucketLocation',
                                             's3:GetObject', 's3:ListBucket',
                                             's3:ListBucketMultipartUploads',
                                             's3:PutObject'
                                         ],
                                         "Resource": ['*'],
                                         "Effect":
                                         "Allow"
                                     }]
                                 },
                                 roles=[role01.ref])

        delivery_stream = kinesisfirehose.CfnDeliveryStream(
            self,
            id="firehose01",
            delivery_stream_name="firehose01",
            extended_s3_destination_configuration={
                # s3桶信息
                'bucketArn': 'arn:aws:s3:::fluent-bit-s3',

                # 压缩设置,老方案:gzip,新方案待定
                'compressionFormat': 'GZIP',
                # 格式转换,是否转换为orc,parquet,默认无
                'DataFormatConversionConfiguration': "Disabled",
                # 是否加密:默认无
                'EncryptionConfiguration': "NoEncryption",
                # 错误输出前缀
                'bufferingHints': {
                    'intervalInSeconds': 600,
                    'sizeInMBs': 128
                },
                'ProcessingConfiguration': {
                    "Enabled": True,
                    "Processor": {
                        "Type":
                        "Lambda",
                        "Parameters": [{
                            "ParameterName": "BufferIntervalInSeconds",
                            "ParameterValue": "60"
                        }, {
                            "ParameterName": "BufferSizeInMBs",
                            "ParameterValue": "3"
                        }, {
                            "ParameterName":
                            "LambdaArn",
                            "ParameterValue":
                            "arn:aws:lambda:ap-southeast-1:596030579944:function:firehose-test"
                        }]
                    }
                },
                'roleArn':
                'arn:aws:iam::596030579944:role/avalon_lambda_kinesis_role',
                'S3BackupConfiguration': {
                    "BucketARN":
                    'arn:aws:s3:::fluent-bit-s3',
                    'bufferingHints': {
                        'intervalInSeconds': 600,
                        'sizeInMBs': 128
                    },
                    'compressionFormat':
                    'GZIP',
                    'EncryptionConfiguration':
                    "NoEncryption",
                    'Prefix':
                    "/backup",
                    'roleArn':
                    'arn:aws:iam::596030579944:role/avalon_lambda_kinesis_role'
                }
            },
        )
Esempio n. 23
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Api
        api = apigw.CfnRestApi(self,
                               "Api",
                               name="WebProxyApi",
                               binary_media_types=["*"])

        # WebpageCDN
        webpage_cdn = cloudfront.CfnDistribution(
            self,
            'WebpageCdn',
            distribution_config={
                "defaultCacheBehavior": {
                    "allowedMethods": [
                        "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST",
                        "PUT"
                    ],
                    "maxTTL":
                    0,
                    "minTTL":
                    0,
                    "defaultTTL":
                    0,
                    "forwardedValues": {
                        "queryString":
                        True,
                        "cookies": {
                            "forward": "all"
                        },
                        "headers": [
                            "Accept",
                            "Referer",
                            "Athorization",
                            "Content",
                        ]
                    },
                    "targetOriginId":
                    "website",
                    "viewerProtocolPolicy":
                    "redirect-to-https",
                },
                "enabled":
                True,
                "origins": [{
                    "domainName":
                    "%s.execute-api.%s.amazonaws.com" %
                    (api.ref, core.Aws.REGION),
                    "id":
                    "website",
                    "originPath":
                    "/Prod",
                    "customOriginConfig": {
                        "originProtocolPolicy": "https-only"
                    },
                }],
                "priceClass":
                "PriceClass_All"
            })

        # LoadBalancer
        loadbalancer = elv2.CfnLoadBalancer(
            self,
            'LoadBalancer',
            subnets=[
                core.Fn.import_value("PublicSubnet1"),
                core.Fn.import_value("PublicSubnet2"),
            ],
            load_balancer_attributes=[{
                "key": "idle_timeout.timeout_seconds",
                "value": "50"
            }],
            security_groups=[
                core.Fn.import_value("WebSecurityGroupOutput"),
            ])

        # CloudWatchRole
        cloud_watch_role = iam.CfnRole(
            self,
            "CloudWatchRole",
            role_name="cloud-watch-lambda-execution-role",
            assume_role_policy_document={
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "Service": ["apigateway.amazonaws.com"]
                    },
                    "Action": ["sts:AssumeRole"]
                }]
            },
            path="/",
            managed_policy_arns=[
                "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs",
                "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"
            ],
        )

        # Account
        account = apigw.CfnAccount(
            self, "Account", cloud_watch_role_arn=cloud_watch_role.attr_arn)

        #Resource
        resource = apigw.CfnResource(self,
                                     "Resource",
                                     parent_id=api.attr_root_resource_id,
                                     rest_api_id=api.ref,
                                     path_part="{proxy+}")

        # RootMethod
        root_method = apigw.CfnMethod(self,
                                      "RootMethod",
                                      http_method="ANY",
                                      resource_id=api.attr_root_resource_id,
                                      rest_api_id=api.ref,
                                      authorization_type="None",
                                      integration={
                                          "integrationHttpMethod":
                                          "ANY",
                                          "type":
                                          "HTTP_PROXY",
                                          "uri":
                                          "http://" +
                                          loadbalancer.attr_dns_name,
                                          "passthroughBehavior":
                                          "WHEN_NO_MATCH",
                                          "integrationResponses": [{
                                              "statusCode":
                                              "200"
                                          }]
                                      })

        # ProxyMethod
        proxy_method = apigw.CfnMethod(
            self,
            "ProxyMethod",
            http_method="ANY",
            resource_id=resource.ref,
            rest_api_id=api.ref,
            authorization_type="None",
            request_parameters={"method.request.path.proxy": True},
            integration={
                "cacheKeyParameters": ["method.request.path.proxy"],
                "requestParameters": {
                    "integration.request.path.proxy":
                    "method.request.path.proxy"
                },
                "integrationHttpMethod": "ANY",
                "type": "HTTP_PROXY",
                "uri": "http://" + loadbalancer.attr_dns_name + "/{proxy}",
                "passthroughBehavior": "WHEN_NO_MATCH",
                "integrationResponses": [{
                    "statusCode": "200"
                }]
            })

        # Deployment
        deployment = apigw.CfnDeployment(self,
                                         "Deployment",
                                         rest_api_id=api.ref)
        deployment.add_depends_on(root_method)
        deployment.add_depends_on(proxy_method)

        # ProdStage
        prod_stage = apigw.CfnStage(self,
                                    "ProdStage",
                                    stage_name="Prod",
                                    description="Prod Stage",
                                    rest_api_id=api.ref,
                                    deployment_id=deployment.ref,
                                    tracing_enabled=True)

        # Output
        core.CfnOutput(self,
                       "AlbDNSName",
                       value=loadbalancer.attr_dns_name,
                       description="ALB DNSName",
                       export_name="AlbDNSName")

        core.CfnOutput(self,
                       "DomainName",
                       value=webpage_cdn.attr_domain_name,
                       description="Webpage CloudFront Domain name.",
                       export_name="DomainName")

        core.CfnOutput(self,
                       "LoadBalancerArn",
                       value=loadbalancer.ref,
                       export_name="LoadBalancerArn")