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", ), ], )
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")] )
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"), )
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))
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")
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")
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)
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")
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' } }, )
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")