def provision_buckets(self, name: str, s3: List[S3]): self.buckets = {} for bucket, attrs in s3.buckets.items(): use_sse_kms_key = False if attrs.sse_kms_key_id: use_sse_kms_key = True sse_kms_key = Key.from_key_arn(self, f"{bucket}-kms-key", attrs.sse_kms_key_id) self.buckets[bucket] = Bucket( self.scope, bucket, bucket_name=f"{name}-{bucket}", auto_delete_objects=attrs.auto_delete_objects and attrs.removal_policy_destroy, removal_policy=cdk.RemovalPolicy.DESTROY if attrs.removal_policy_destroy else cdk.RemovalPolicy.RETAIN, enforce_ssl=True, bucket_key_enabled=use_sse_kms_key, encryption_key=(sse_kms_key if use_sse_kms_key else None), encryption=(BucketEncryption.KMS if use_sse_kms_key else BucketEncryption.S3_MANAGED), ) self.buckets[bucket].add_to_resource_policy( iam.PolicyStatement( sid="DenyIncorrectEncryptionHeader", effect=iam.Effect.DENY, principals=[iam.ArnPrincipal("*")], actions=[ "s3:PutObject", ], resources=[f"{self.buckets[bucket].bucket_arn}/*"], conditions={ "StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" if use_sse_kms_key else "AES256" } }, )) self.buckets[bucket].add_to_resource_policy( iam.PolicyStatement( sid="DenyUnEncryptedObjectUploads", effect=iam.Effect.DENY, principals=[iam.ArnPrincipal("*")], actions=[ "s3:PutObject", ], resources=[f"{self.buckets[bucket].bucket_arn}/*"], conditions={ "Null": { "s3:x-amz-server-side-encryption": "true" } }, )) self.s3_api_statement.add_resources( f"{self.buckets[bucket].bucket_arn}*") cdk.CfnOutput(self.scope, f"{bucket}-output", value=self.buckets[bucket].bucket_name)
def vpc_network(self, bucket_arn): vpc = ec2.Vpc(self, "demoVPC", max_azs=2, cidr="10.0.0.0/16", nat_gateways=1, subnet_configuration=[{ "cidrMask": 24, "name": 'private', "subnetType": ec2.SubnetType.PRIVATE }, { "cidrMask": 24, "name": 'public', "subnetType": ec2.SubnetType.PUBLIC }]) subnets = vpc.select_subnets( subnet_type=ec2.SubnetType.PRIVATE).subnets endpoint = vpc.add_gateway_endpoint( 's3Endpoint', service=ec2.GatewayVpcEndpointAwsService.S3, subnets=[{ "subnet_id": subnets[0].subnet_id }, { "subnet_id": subnets[1].subnet_id }]) endpoint.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[bucket_arn, f"{bucket_arn}/*"], principals=[iam.ArnPrincipal("*")], actions=[ "s3:GetObject", "s3:GetObjects", "s3:ListObjects", "S3:ListBucket" ], )) # Provides access to the Amazon S3 bucket containing the layers for each Docker image. endpoint.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=[ f"arn:aws:s3:::prod-{self.region}-starport-layer-bucket/*" ], principals=[iam.ArnPrincipal("*")], actions=["s3:GetObject"], )) return vpc, subnets
def _configure_mutual_assume_role(self, role: iam.Role): self._roles.instance_role.add_to_policy( iam.PolicyStatement(effect=iam.Effect.ALLOW, principals=[iam.ArnPrincipal(role.role_arn)], actions=['sts:AssumeRole'])) role.add_to_policy( iam.PolicyStatement(effect=iam.Effect.ALLOW, principals=[ iam.ArnPrincipal( self._roles.instance_role.role_arn) ], actions=['sts:AssumeRole']))
def __init__(self, scope: core.Construct, name: str, vpc: ec2.IVpc, **kwargs) -> None: super().__init__(scope, name, **kwargs) cluster = eks.Cluster( self, 'jenkins-workshop-eks-control-plane', vpc=vpc, default_capacity=0 ) asg_worker_nodes = cluster.add_capacity( 'worker-node', instance_type=ec2.InstanceType('t3.medium'), desired_capacity=2, ) asg_jenkins_slave = cluster.add_capacity( 'worker-node-jenkins-slave', instance_type=ec2.InstanceType('t3.medium'), desired_capacity=1, bootstrap_options=eks.BootstrapOptions( kubelet_extra_args='--node-labels jenkins=slave --register-with-taints jenkins=slave:NoSchedule', docker_config_json=read_docker_daemon_resource('kubernetes_resources/docker-daemon.json') ) ) asg_jenkins_slave.add_to_role_policy(iam.PolicyStatement( actions=[ 'ecr:CompleteLayerUpload', 'ecr:InitiateLayerUpload', 'ecr:PutImage', 'ecr:UploadLayerPart' ], resources=["*"] ) ) asg_worker_nodes.connections.allow_from( asg_jenkins_slave, ec2.Port.all_traffic() ) asg_jenkins_slave.connections.allow_from( asg_worker_nodes, ec2.Port.all_traffic() ) eks_master_role = iam.Role( self, 'AdminRole', assumed_by=iam.ArnPrincipal(get_eks_admin_iam_username()) ) cluster.aws_auth.add_masters_role(eks_master_role) helm_tiller_rbac = eks.KubernetesResource( self, 'helm-tiller-rbac', cluster=cluster, manifest=read_k8s_resource('kubernetes_resources/helm-tiller-rbac.yaml') )
def _build_kms_key_for_env(self) -> None: administrator_arns: List[str] = [ ] # A place to add other admins if needed for KMS admin_principals = iam.CompositePrincipal( *[iam.ArnPrincipal(arn) for arn in administrator_arns], iam.ArnPrincipal(f"arn:aws:iam::{self.context.account_id}:root"), ) self.env_kms_key: kms.Key = kms.Key( self, id="kms-key", removal_policy=core.RemovalPolicy.RETAIN, enabled=True, enable_key_rotation=True, policy=iam.PolicyDocument(statements=[ iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=["kms:*"], resources=["*"], principals=[admin_principals]) ]), )
def __init__(self, scope: core.Construct, id: str, landing_zone: ILandingZone, **kwargs): """ Configure Dns Resolver """ super().__init__(scope, id, **kwargs) region = core.Stack.of(self).region self.encryption_key = kms.Key( self, 'EncryptionKey', description='Encryption Key for BackupStrategy') self.topic = sns.Topic(self, 'Topic') self.role = iam.Role(self, 'Role', description='Account Backup Role', assumed_by=iam.ServicePrincipal(service='backup')) self.vault = backup.BackupVault( self, 'Vault', encryption_key=self.encryption_key, notification_topic=self.topic, backup_vault_name='{}-Backup-Vault'.format(landing_zone.zone_name), access_policy=iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=["*"], actions=['backup:CopyIntoBackupVault'], principals=[iam.ArnPrincipal(arn=self.role.role_arn)]) ])) self.default_plan = backup.BackupPlan( self, 'DefaultPlan', backup_vault=self.vault, backup_plan_name='Default Plan {} in {}'.format( landing_zone.zone_name, region), backup_plan_rules=[ backup.BackupPlanRule.daily(), backup.BackupPlanRule.weekly(), ]) self.default_plan.add_selection('SelectionPolicy', allow_restores=True, role=self.role, resources=[ backup.BackupResource.from_tag( "landing_zone", landing_zone.zone_name), ])
def _assumed_by(self, principals: typing.Union[aws_iam.IPrincipal, typing.List[str]]) -> aws_iam.IPrincipal: pps = list() for principal in principals: if isinstance(principal, str): if principal.startswith("arn:aws"): pps.append(aws_iam.ArnPrincipal(arn=principal)) else: pps.append(aws_iam.AccountPrincipal(account_id=principal)) else: pps.append(principal) if len(pps) > 1: return aws_iam.CompositePrincipal(*pps) return pps[0]
def __init__(self, scope: cdk.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) trusted_role_arn = "arn:aws:iam::" + MAIN_ACCOUNT_ID + ":role/ConsoleMeTaskRole" spoke_role = iam.Role( self, f"{SPOKE_BASE_NAME}TrustRole", role_name="ConsoleMeTrustRole", assumed_by=iam.ArnPrincipal(arn=trusted_role_arn), ) spoke_role.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ "autoscaling:Describe*", "cloudwatch:Get*", "cloudwatch:List*", "config:BatchGet*", "config:List*", "config:Select*", "ec2:describeregions", "ec2:DescribeSubnets", "ec2:describevpcendpoints", "ec2:DescribeVpcs", "iam:*", "s3:GetBucketPolicy", "s3:GetBucketTagging", "s3:ListAllMyBuckets", "s3:ListBucket", "s3:PutBucketPolicy", "s3:PutBucketTagging", "sns:GetTopicAttributes", "sns:ListTagsForResource", "sns:ListTopics", "sns:SetTopicAttributes", "sns:TagResource", "sns:UnTagResource", "sqs:GetQueueAttributes", "sqs:GetQueueUrl", "sqs:ListQueues", "sqs:ListQueueTags", "sqs:SetQueueAttributes", "sqs:TagQueue", "sqs:UntagQueue", ], resources=["*"], ))
def __init__(self, scope: core.Construct, display_name: str, topic_name: str): super().__init__(scope=scope, id=topic_name, display_name=display_name, topic_name=topic_name) policy_statement = aws_iam.PolicyStatement( actions=['SNS:Subscribe', 'SNS:publish'], conditions=[], effect=aws_iam.Effect.ALLOW, resources=[self.topic_arn], principals=[aws_iam.ArnPrincipal('*')]) self.add_to_resource_policy(policy_statement)
def __init__(self, scope: core.Construct, id: str, vpc: ec2.Vpc, **kwargs) -> None: super().__init__(scope, id, **kwargs) kms_policy = iam.PolicyDocument() kms_policy.add_statements( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["kms:*"], resources=['*'], principals=[iam.AccountPrincipal(account_id=self.account)])) redshift_key = kms.Key(self, "volumeKey", enable_key_rotation=True, policy=kms_policy, removal_policy=core.RemovalPolicy.RETAIN) redshift_bucket = s3.Bucket(self, "redshiftBucket") redshift_bucket.add_to_resource_policy(permission=iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["s3:*"], resources=[ f"{redshift_bucket.bucket_arn}/*", redshift_bucket.bucket_arn ], principals=[ iam.ArnPrincipal(f"arn:aws:iam::193672423079:user/logs") ])) self._cluster = redshift.Cluster( self, id, master_user=redshift.Login(master_username="******", encryption_key=redshift_key), port=5439, vpc=vpc, cluster_name="dwh", cluster_type=redshift.ClusterType.MULTI_NODE, number_of_nodes=2, default_database_name="aml", encrypted=True, encryption_key=redshift_key, logging_bucket=redshift_bucket, logging_key_prefix="dwh", node_type=redshift.NodeType.DC2_LARGE, removal_policy=core.RemovalPolicy.DESTROY, security_groups=[self.redshift_sg(vpc)], vpc_subnets=ec2.SubnetSelection(subnet_group_name="DBS"))
def provide_access_to_artifacts(scope: core.Construct, *, pipeline_def: Pipeline, artifact_bucket: aws_s3.Bucket) -> None: role_arns = set() for role_arn in pipeline_def.get("artifact_access", {}).get("role_arns", []): role_arns.add(role_arn) for stage_def in pipeline_def["stages"]: for action_def in stage_def["actions"]: if "role_arn" in action_def: account = core.Arn.parse(action_def["role_arn"]).account if account != core.Stack.of(scope).account: role_arns.add(action_def["role_arn"]) for role_arn in role_arns: artifact_bucket.add_to_resource_policy( aws_iam.PolicyStatement( actions=["s3:Get*"], resources=[artifact_bucket.arn_for_objects("*")], effect=aws_iam.Effect.ALLOW, principals=[aws_iam.ArnPrincipal(role_arn)], ))
def __create_s3_source_bucket_policy( self, s3_source_bucket: aws_s3.Bucket, cloud_front_origin_access_identity: aws_cloudfront.OriginAccessIdentity ): return aws_s3.CfnBucketPolicy( self, 'S3SourceBucketPolicy', bucket=s3_source_bucket.bucket_name, policy_document=PolicyDocument(statements=[ PolicyStatement( effect=Effect.ALLOW, actions=['s3:GetObject'], sid='1', resources=[ f'arn:aws:s3:::{s3_source_bucket.bucket_name}/*' ], principals=[ aws_iam.ArnPrincipal( f'arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ' f'{cloud_front_origin_access_identity.origin_access_identity_name}' ) ]) ]))
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # CloudFormation Parameters glue_db_name = core.CfnParameter( self, "GlueDatabaseName", type="String", description="Glue Database where the Table belongs.", allowed_pattern="[\w-]+", ) glue_table_name = core.CfnParameter( self, "GlueTableName", type="String", description="Glue Table where access will be granted.", allowed_pattern="[\w-]+", ) grantee_role_arn = core.CfnParameter( self, "GranteeIAMRoleARN", type="String", description="IAM Role's ARN.", allowed_pattern= "arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role\/?[a-zA-Z0-9_+=,.@\-]+") grantee_vpc = core.CfnParameter( self, "GranteeVPC", type="String", description= "VPC ID from where the S3 access point will be accessed.", allowed_pattern="vpc-[a-zA-Z0-9]+") is_lakeformation = core.CfnParameter( self, "LakeFormationParam", type="String", description= "If Lake Formation is used, the stack must be deployed using an IAM role with Lake Formation Admin permissions.", allowed_values=["Yes", "No"]) # CloudFormation Parameter Groups self.template_options.description = "\ This template deploys an S3 Access Point which provides a given IAM Role \ access to the underlying data location for a given Glue Table.\n\ Main use case for this template is to grant an ETL process in another AWS Account, \ access to the S3 objects (e.g., Parquet files) associated to a Glue Table." self.template_options.metadata = { "AWS::CloudFormation::Interface": { "License": "MIT-0", "ParameterGroups": [{ "Label": { "default": "Lake Formation (Producer Account)" }, "Parameters": [is_lakeformation.logical_id] }, { "Label": { "default": "Source Data Catalog Resource (Producer Account)" }, "Parameters": [glue_db_name.logical_id, glue_table_name.logical_id] }, { "Label": { "default": "Grantee IAM Role (Consumer Account)" }, "Parameters": [grantee_role_arn.logical_id, grantee_vpc.logical_id] }], "ParameterLabels": { is_lakeformation.logical_id: { "default": "Are data permissions managed by Lake Formation?" }, glue_db_name.logical_id: { "default": "What is the Glue DB Name for the Table?" }, glue_table_name.logical_id: { "default": "What is the Glue Table Name?" }, grantee_role_arn.logical_id: { "default": "What is the ARN of the IAM Role?" }, grantee_vpc.logical_id: { "default": "What VPC will be used to access the S3 Access Point?" } } } } is_lakeformation_condition = core.CfnCondition( self, "IsLakeFormation", expression=core.Fn.condition_equals("Yes", is_lakeformation)) # Create S3 Access Point to share dataset objects grantee_role = iam.Role.from_role_arn(self, "GranteeIAMRole", grantee_role_arn.value_as_string) glue_table_arn = f"arn:aws:glue:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:table/{glue_db_name.value_as_string}/{glue_table_name.value_as_string}" glue_table = glue.Table.from_table_arn(self, "GlueTable", table_arn=glue_table_arn) # Invoke Lambda to obtain S3 bucket and S3 prefix from Glue Table get_s3_from_table_execution_role = iam.Role( self, "GetS3FromTableServiceRole", assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), managed_policies=[ iam.ManagedPolicy.from_aws_managed_policy_name( "service-role/AWSLambdaBasicExecutionRole"), iam.ManagedPolicy.from_aws_managed_policy_name( "service-role/AWSGlueServiceRole") ]) lf_permission = lf.CfnPermissions( self, "LFPermissionForLambda", data_lake_principal=lf.CfnPermissions.DataLakePrincipalProperty( data_lake_principal_identifier=get_s3_from_table_execution_role .role_arn), resource=lf.CfnPermissions.ResourceProperty( table_resource=lf.CfnPermissions.TableResourceProperty( name=glue_table_name.value_as_string, database_name=glue_db_name.value_as_string)), permissions=["DESCRIBE"]) lf_permission.apply_removal_policy(core.RemovalPolicy.DESTROY, apply_to_update_replace_policy=True) lf_permission.node.add_dependency(get_s3_from_table_execution_role) lf_permission.cfn_options.condition = is_lakeformation_condition lf_wait_condition_handle = cfn.CfnWaitConditionHandle( self, "LFWaitConditionHandle") lf_wait_condition_handle.add_metadata( "WaitForLFPermissionIfExists", core.Fn.condition_if(is_lakeformation_condition.logical_id, lf_permission.logical_id, "")) with open("lambda/get_s3_from_table.py", encoding="utf8") as fp: get_s3_from_table_code = fp.read() get_s3_from_table_fn = _lambda.Function( self, "GetS3FromTableHandler", runtime=_lambda.Runtime.PYTHON_3_7, code=_lambda.InlineCode.from_inline(get_s3_from_table_code), handler="index.handler", role=get_s3_from_table_execution_role, timeout=core.Duration.seconds(600)) get_s3_from_table = core.CustomResource( self, "GetS3FromTable", service_token=get_s3_from_table_fn.function_arn, resource_type="Custom::GetS3FromTable", properties={ "GlueDatabase": glue_db_name.value_as_string, "GlueTable": glue_table_name.value_as_string }) get_s3_from_table.node.add_dependency(lf_wait_condition_handle) table_bucket = get_s3_from_table.get_att_string("TableBucket") table_prefix = get_s3_from_table.get_att_string("TablePrefix") # Create S3 Access Point table_name_normalized = core.Fn.join( "-", core.Fn.split("_", glue_table_name.value_as_string)) random_suffix = core.Fn.select( 0, core.Fn.split( "-", core.Fn.select(2, core.Fn.split("/", core.Aws.STACK_ID)))) s3_accesspoint_name = f"{table_name_normalized}-{random_suffix}" s3_accesspoint_arn = f"arn:aws:s3:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:accesspoint/{s3_accesspoint_name}" glue_table_accesspoint_path = f"{s3_accesspoint_arn}/object/{table_prefix}" # s3_accesspoint_block_config = s3.CfnAccessPoint.PublicAccessBlockConfigurationProperty(block_public_acls=True, block_public_policy=True, ignore_public_acls=True, restrict_public_buckets=True) s3_accesspoint_policy = iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, principals=[iam.ArnPrincipal(arn=grantee_role.role_arn)], actions=["s3:GetObject*"], resources=[f"{glue_table_accesspoint_path}*"]), iam.PolicyStatement( effect=iam.Effect.ALLOW, principals=[iam.ArnPrincipal(arn=grantee_role.role_arn)], actions=["s3:ListBucket*"], resources=[s3_accesspoint_arn], conditions={"StringLike": { "s3:prefix": f"{table_prefix}*" }}) ]) s3_accesspoint = s3.CfnAccessPoint( self, "S3AccessPoint", bucket=f"{table_bucket}", name=s3_accesspoint_name, # network_origin = "Internet", policy=s3_accesspoint_policy, vpc_configuration=s3.CfnAccessPoint.VpcConfigurationProperty( vpc_id=grantee_vpc.value_as_string)) glue_table_accesspoint_path_output = f"arn:aws:s3:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:accesspoint/{s3_accesspoint.name}/object/{table_prefix}" # Output core.CfnOutput(self, "IAMRoleArnOutput", value=grantee_role.role_arn, description="IAM Role Arn") core.CfnOutput(self, "GlueTableOutput", value=glue_table.table_arn, description="Glue Table ARN") core.CfnOutput(self, "S3AccessPointPathOutput", value=glue_table_accesspoint_path_output, description="S3 Access Point Path for Glue Table")
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) Zach_AWSBackupPlanName = self.__class__.__name__ Zach_AWSBackup_Vault = bk.CfnBackupVault( self, id=Zach_AWSBackupPlanName, backup_vault_name=Zach_AWSBackupPlanName) Zach_AWSBackup_IAM_ROLE = "arn:aws:iam::098380756085:role/service-role/AWSBackupDefaultServiceRole" if Zach_AWSBackup_IAM_ROLE == "": IAM_ACCOUNT = self.node.try_get_context( "account") or '098380756085' IAM_Princial = iam.CompositePrincipal( iam.ServicePrincipal("backup.amazonaws.com"), iam.AccountPrincipal(IAM_ACCOUNT), iam.ArnPrincipal("arn:aws:ec2:*")) Zach_AWSBackup_IAM_ROLE = iam.Role( self, id="Zach_" + Zach_AWSBackupPlanName, role_name="Zach_" + Zach_AWSBackupPlanName, assumed_by=IAM_Princial, max_session_duration=core.Duration.hours(6)) # FIXME ''' jsii.errors.JSIIError: Value did not match any type in union: Value did not match any type in union: Expected object reference, got [{"CompletionWindowMinutes":30,"Lifecycle":{"DeleteAfterDays":90,"MoveToColdStorageAfterDays":28},"RuleName":"Zach_AWSBackup_Stack_A" ,"ScheduleExpression":"cron(0 5 ? * * *)","StartWindowMinutes":480,"TargetBackupVault":"Zach_AWSBackup_Stack_A"}],Value did not match any type in union: Expected object reference, got {"CompletionWindowMinutes":30,"Lifecycle":{"DeleteAfterDays":90,"MoveToColdStorag eAfterDays":28},"RuleName":"Zach_AWSBackup_Stack_A","ScheduleExpression":"cron(0 5 ? * * *)","StartWindowMinutes":480,"TargetBackupVault":"Zach_AWSBackup_Stack_A"},Missing required properties for @aws-cdk/aws-backup.CfnBackupPlan.BackupRuleResourceTypeProperty: rul eName,targetBackupVault,Expected object reference, got {"backupPlanName":"Zach_AWSBackup_Stack_A","backupPlanRule":[{"CompletionWindowMinutes":30,"Lifecycle":{"DeleteAfterDays":90,"MoveToColdStorageAfterDays":28},"RuleName":"Zach_AWSBackup_Stack_A","ScheduleExpress ion":"cron(0 5 ? * * *)","StartWindowMinutes":480,"TargetBackupVault":"Zach_AWSBackup_Stack_A"}]} ''' BackupPlanRule = [{ "CompletionWindowMinutes": 30, "Lifecycle": { "DeleteAfterDays": 90, "MoveToColdStorageAfterDays": 28 }, "RuleName": Zach_AWSBackupPlanName, "ScheduleExpression": "cron(0 5 ? * * *)", "StartWindowMinutes": 480, "TargetBackupVault": Zach_AWSBackup_Vault.backup_vault_name }] Zach_AWSBackup = bk.CfnBackupPlan(self, id=Zach_AWSBackupPlanName, backup_plan={ "backupPlanName": Zach_AWSBackupPlanName, "backupPlanRule": BackupPlanRule }) # , backup_plan_tags = ['dev', 'zach', Zach_AWSBackupPlanName] JobList = { "IamRoleArn": "arn:aws:iam::098380756085:role/service-role/AWSBackupDefaultServiceRole", "ListOfTags": [], "Resources": [ "arn:ap-southeast-1:ec2:ap-southeast-1a:098380756085:volume/vol-02a2664501c88e696" ], "SelectionName": Zach_AWSBackupPlanName + "EBS-00001" } Zach_AWSBackup_Job = bk.CfnBackupSelection( self, id=Zach_AWSBackupPlanName + "EBS-00001", backup_plan_id=Zach_AWSBackup.attr_backup_plan_id, backup_selection=JobList) core.CfnOutput(self, "ZachAWSBackupID", value=Zach_AWSBackup.logical_id) core.CfnOutput(self, "ZachAWSBackupPlanID", value=Zach_AWSBackup.attr_backup_plan_id) core.CfnOutput(self, "ZachAWSBackupPlanARN", value=Zach_AWSBackup.attr_backup_plan_arn) core.CfnOutput(self, "ZachAWSBackupPlan", value=Zach_AWSBackup.backup_plan.to_string) core.CfnOutput(self, "ZachAWSBackupRoleARN", value=Zach_AWSBackup_IAM_ROLE.role_arn) core.CfnOutput(self, "ZachAWSBackupVaultARN", value=Zach_AWSBackup_Vault.attr_backup_vault_arn) core.CfnOutput(self, "ZachAWSBackupVaultName", value=Zach_AWSBackup_Vault.backup_vault_name)
def __init__(self, app: App, id: str) -> None: super().__init__(app, id) self.access_point = f"arn:aws:s3:{Aws.REGION}:{Aws.ACCOUNT_ID}:accesspoint/" \ f"{S3_ACCESS_POINT_NAME}" # Set up a bucket bucket = s3.Bucket( self, "example-bucket", access_control=s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL, encryption=s3.BucketEncryption.S3_MANAGED, block_public_access=s3.BlockPublicAccess.BLOCK_ALL) # Delegating access control to access points # https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-points-policies.html bucket.add_to_resource_policy( iam.PolicyStatement( actions=["*"], principals=[iam.AnyPrincipal()], resources=[bucket.bucket_arn, bucket.arn_for_objects('*')], conditions={ "StringEquals": { "s3:DataAccessPointAccount": f"{Aws.ACCOUNT_ID}" } })) # lambda to process our objects during retrieval retrieve_transformed_object_lambda = _lambda.Function( self, "retrieve_transformed_obj_lambda", runtime=_lambda.Runtime.PYTHON_3_8, handler="index.handler", code=_lambda.Code.from_asset( "lambda/retrieve_transformed_object_lambda")) # Object lambda s3 access retrieve_transformed_object_lambda.add_to_role_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=["*"], actions=["s3-object-lambda:WriteGetObjectResponse"])) # Restrict Lambda to be invoked from own account retrieve_transformed_object_lambda.add_permission( "invocationRestriction", action="lambda:InvokeFunction", principal=iam.AccountRootPrincipal(), source_account=Aws.ACCOUNT_ID) # Associate Bucket's access point with lambda get access policy_doc = iam.PolicyDocument() policy_statement = iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["s3:GetObject"], principals=[ iam.ArnPrincipal( retrieve_transformed_object_lambda.role.role_arn) ], resources=[f"{self.access_point}/object/*"]) policy_statement.sid = "AllowLambdaToUseAccessPoint" policy_doc.add_statements(policy_statement) example_bucket_ap = s3.CfnAccessPoint(self, "example-bucket_ap", bucket=bucket.bucket_name, name=S3_ACCESS_POINT_NAME, policy=policy_doc) # Access point to receive GET request and use lambda to process objects object_lambda_ap = s3_object_lambda.CfnAccessPoint( self, "s3_object_lambda_ap", name=OBJECT_LAMBDA_ACCESS_POINT_NAME, object_lambda_configuration=s3_object_lambda.CfnAccessPoint. ObjectLambdaConfigurationProperty( supporting_access_point=self.access_point, transformation_configurations=[ s3_object_lambda.CfnAccessPoint. TransformationConfigurationProperty( actions=["GetObject"], content_transformation={ "AwsLambda": { "FunctionArn": f"{retrieve_transformed_object_lambda.function_arn}" } }) ])) CfnOutput(self, "exampleBucketArn", value=bucket.bucket_arn) CfnOutput(self, "objectLambdaArn", value=retrieve_transformed_object_lambda.function_arn) CfnOutput(self, "objectLambdaAccessPointArn", value=object_lambda_ap.attr_arn) CfnOutput( self, "objectLambdaAccessPointUrl", value=f"https://console.aws.amazon.com/s3/olap/{Aws.ACCOUNT_ID}/" f"{OBJECT_LAMBDA_ACCESS_POINT_NAME}?region={Aws.REGION}")
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # API Gateway needs to have resource policy granting FHIR Works on AWS lambda # execute permissions. Lambda function ARN will be passed during deployment as CDK context variable # FHIR Works lambda will need to have policy attached to its execution role # allowing it to invoke API # From --context resource-router-lambda-role="arn:aws:iam::123456789012:role/rolename" imported_resource_router_lambda_role = self.node.try_get_context( "resource-router-lambda-role" ) # Amazon ECS on AWS Fargate container implementing connection manager # will be launched into a VPC that needs to have private and public subnets # and NAT gateway or instance # From --context vpc-id="vpc-123456" vpc_id = self.node.try_get_context("vpc-id") # The following parameters specify name of the HL7 server # that will be receiving transformed HL7v2 messages and TCP port # that it will be listening on # From --context hl7-server-name="hl7.example.com" # From --context hl7-port="2575" hl7_server_name = self.node.try_get_context("hl7-server-name") hl7_port = self.node.try_get_context("hl7-port") # In this proof of concept source of data for read interactions # is S3 bucket where mock HL7 server stores processed HL7 messages # From --context test-server-output-bucket-name="DOC-EXAMPLE-BUCKET" test_server_output_bucket_name = self.node.try_get_context( "test-server-output-bucket-name" ) # SQS queue # Custom transform lambda communicates with Connectivity Manager using this SQS queue queue = sqs.Queue( self, f"{COMPONENT_PREFIX}Queue", encryption=sqs.QueueEncryption.KMS_MANAGED ) # S3 Bucket to retrieve HL7v2 messages in proof of concept deployment test_server_output_bucket = s3.Bucket.from_bucket_name( self, f"{COMPONENT_PREFIX}OutputBucket", test_server_output_bucket_name ) # Transform Lambda # Reference implementation of Custom Transform component of Transform Execution Environment transform_lambda = lambda_.Function( self, f"{COMPONENT_PREFIX}TransformLambda", handler="transform.handler", runtime=lambda_.Runtime.PYTHON_3_8, code=lambda_.Code.from_asset( path.join(dirname, "../../lambda"), bundling={ "image": lambda_.Runtime.PYTHON_3_8.bundling_docker_image, "command": [ "bash", "-c", " && ".join( [ "pip install --no-cache-dir -r requirements.txt -t /asset-output", "(tar -c --exclude-from=exclude.lst -f - .)|(cd /asset-output; tar -xf -)", ] ), ], }, ), timeout=core.Duration.seconds(60), environment=dict( SQS_QUEUE=queue.queue_url, # The following parameter is optional S3_BUCKET_NAME=test_server_output_bucket_name, ), ) queue.grant_send_messages(transform_lambda) # API Gateway with Lambda construct (using https://aws.amazon.com/solutions/constructs/patterns) # Reference implementation of Custom Transform component of Transform Execution Environment api_lambda = apigw_lambda.ApiGatewayToLambda( self, "ApiGw", existing_lambda_obj=transform_lambda, api_gateway_props=apigw.LambdaRestApiProps( handler=transform_lambda, proxy=False, rest_api_name=f"{COMPONENT_PREFIX_DASHES}-api", endpoint_export_name=f"{COMPONENT_PREFIX}ApiEndPoint", description=f"{COMPONENT_PREFIX} APIGW with Transform Lambda (FHIR to HL7v2)", default_method_options=apigw.MethodOptions( authorization_type=apigw.AuthorizationType.IAM, ), policy=iam.PolicyDocument( statements=[ iam.PolicyStatement( actions=["execute-api:Invoke"], effect=iam.Effect.ALLOW, principals=[ iam.ArnPrincipal(imported_resource_router_lambda_role), ], resources=["execute-api:/*/*/*"], ) ] ), ), ) rest_api = api_lambda.api_gateway persistence = rest_api.root.add_resource("persistence") resource_type = persistence.add_resource("{resource_type}") resource_type.add_method("POST") resource_id = resource_type.add_resource("{id}") resource_id.add_method("GET") resource_id.add_method("PUT") resource_id.add_method("DELETE") # ECS Fargate Container (HL7v2 sender) # This container implements Connectivity Manager component # of Transform Execution Environment vpc = ec2.Vpc.from_lookup(self, "DefaultVpc", vpc_id=vpc_id) cluster = ecs.Cluster(self, f"{COMPONENT_PREFIX}Cluster", vpc=vpc) ecs_patterns.QueueProcessingFargateService( self, f"{COMPONENT_PREFIX}Service", cluster=cluster, image=ecs.ContainerImage.from_asset(path.join(dirname, "../../container")), queue=queue, desired_task_count=1, log_driver=ecs.LogDriver.aws_logs( stream_prefix=f"{COMPONENT_PREFIX}HL7Client", log_retention=logs.RetentionDays.ONE_DAY, ), environment=dict( SERVER_NAME=hl7_server_name, PORT_NUMBER=hl7_port, ), ) # The following permission grants are needed to support # read interactions with integration transform test_server_output_bucket.grant_read(transform_lambda) transform_lambda.add_to_role_policy( iam.PolicyStatement( actions=["s3:ListBucket"], effect=iam.Effect.ALLOW, resources=[test_server_output_bucket.bucket_arn], ) ) transform_lambda.add_to_role_policy( iam.PolicyStatement( actions=["s3:GetObject"], effect=iam.Effect.ALLOW, resources=[test_server_output_bucket.arn_for_objects("*")], ) ) # CloudFormation Stack outputs # The following outputs needed to configure FHIR Works on AWS API interface core.CfnOutput( self, "TransformApiRootUrl", value=rest_api.url, export_name="TransformApiRootUrl", ) core.CfnOutput( self, "TransformApiRegion", value=self.region, export_name="TransformApiRegion", ) core.CfnOutput( self, "TransformApiAccountId", value=self.account, export_name="TransformApiAccountId", )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.current_dir = os.path.dirname(__file__) self.website_bucket = s3.Bucket( self, "qs-embed-bucket", bucket_name=f'quicksight-embed-{core.Aws.ACCOUNT_ID}', block_public_access=s3.BlockPublicAccess.BLOCK_ALL) self.quicksight_embed_lambda_role = iam.Role( self, 'quicksight-embed-lambda-role', description='Role for the Quicksight dashboard embed Lambdas', role_name='quicksight-embed-lambda-role', max_session_duration=core.Duration.seconds(3600), assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'AllowAccess': iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ], resources=[ f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*' ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["secrets:GetSecretValue"], resources=[ f"arn:aws:secretsmanager:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:secret:*" ]), iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=[ "quicksight:GetDashboardEmbedUrl", "quicksight:GetAuthCode" ], resources=["*"]) ]) }) self.quicksight_migration_lambda = _lambda.Function( self, 'quicksight-migration-lambda', handler='quicksight_embed.lambda_handler', runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.from_asset( os.path.join(self.current_dir, '../lambda/quicksight_embed/')), function_name='quicksight_embed_lambda', role=self.quicksight_embed_lambda_role, timeout=core.Duration.minutes(3), memory_size=512, environment={ 'DASHBOARD_ID': 'CHANGEME_DASHBOARD_ID', 'QUICKSIGHT_USER_ARN': f'arn:aws:quicksight:us-east-1:{core.Aws.ACCOUNT_ID}:user/default/quicksight-migration-user' }) self.apigw_lambda = ApiGatewayToLambda( self, "ApiGatewayToLambdaQSEmbed", existing_lambda_obj=self.quicksight_migration_lambda, api_gateway_props=apigw.LambdaRestApiProps( rest_api_name="quicksight-embed", handler=self.quicksight_migration_lambda, deploy=True, proxy=False, default_method_options=apigw.MethodOptions( authorization_type=apigw.AuthorizationType.NONE), policy=iam.PolicyDocument(statements=[ iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=['execute-api:Invoke'], resources=["execute-api:/prod/*"], principals=[iam.ArnPrincipal("*")]) ]))) self.embedurl = self.apigw_lambda.api_gateway.root.add_resource( "embedurl") self.embedurl.add_method( "GET", method_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': True, 'method.response.header.Access-Control-Allow-Methods': True, 'method.response.header.Access-Control-Allow-Origin': True } }], integration=apigw.LambdaIntegration( self.quicksight_migration_lambda, proxy=False, integration_responses=[{ 'statusCode': '200', 'responseTemplates': { "application/json": "" }, 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Methods': "'GET'" } }])) self.embedurl.add_method( 'OPTIONS', apigw.MockIntegration(integration_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Methods': "'GET,OPTIONS'" } }], passthrough_behavior=apigw. PassthroughBehavior.WHEN_NO_MATCH, request_templates={ "application/json": "{\"statusCode\":200}" }), method_responses=[{ 'statusCode': '200', 'responseParameters': { 'method.response.header.Access-Control-Allow-Headers': True, 'method.response.header.Access-Control-Allow-Methods': True, 'method.response.header.Access-Control-Allow-Origin': True } }]) # Cloudfront Distribution for authentication self.embed_auth_lambda_role = iam.Role( self, 'embed-auth-lambda-role', description= 'Role for the Quicksight dashboard embed authentication Lambda', role_name='embed-auth-lambda-role', max_session_duration=core.Duration.seconds(3600), assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'AllowAccess': iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ], resources=[ f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*' ]) ]) }) self.embed_auth_lambda = _lambda.Function( self, 'embed-auth-lambda', handler='index.handler', description= "A Lambda@Edge function for QuickSight embed authentication via CloudFront Distribution", runtime=_lambda.Runtime.NODEJS_14_X, code=_lambda.Code.from_asset( os.path.join(self.current_dir, '../lambda/embed_auth/')), function_name='embed_auth_lambda', role=self.embed_auth_lambda_role, timeout=core.Duration.seconds(5), memory_size=128) self.embed_auth_dist = cloudfront.Distribution( self, "embed-auth-dist", enabled=True, default_root_object="index.html", default_behavior=cloudfront.BehaviorOptions( origin=origins.S3Origin(self.website_bucket), allowed_methods=cloudfront.AllowedMethods.ALLOW_GET_HEAD, edge_lambdas=[{ "functionVersion": self.embed_auth_lambda.current_version, "eventType": cloudfront.LambdaEdgeEventType.VIEWER_REQUEST, "includeBody": True }])) core.CfnOutput(self, "EmbedAPIGatewayURL", value=self.apigw_lambda.api_gateway.url + "embedurl?", description="Embed API GW URL") core.CfnOutput(self, "EmbedCloudFrontURL", value="https://" + self.embed_auth_dist.distribution_domain_name, description="CloudFront Distribution URL")
def __init__(self, scope: Construct, cid: str, application_names: List[str], instance_ids: Dict[str, List[str]], instance_roles_map: Dict[str, _iam.IRole], endpoint_sg: _ec2.ISecurityGroup, vpc: _ec2.Vpc) -> None: super().__init__(scope, cid) principals = [] for application_name in application_names: for instance_id in instance_ids[application_name]: principals.append( _iam.ArnPrincipal( arn="arn:aws:sts::" + self.account + ":assumed-role/" + instance_roles_map[application_name].role_name + "/" + instance_id)) self.create_interface_endpoint( "ssm", security_group=endpoint_sg, interface_endpoint_policy=_iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=[ "ssm:DescribeAssociation", "ssm:GetDeployablePatchSnapshotForInstance", "ssm:GetDocument", "ssm:DescribeDocument", "ssm:GetManifest", "ssm:GetParameter", "ssm:GetParameters", "ssm:ListAssociations", "ssm:ListInstanceAssociations", "ssm:PutInventory", "ssm:PutComplianceItems", "ssm:PutConfigurePackageResult", "ssm:UpdateAssociationStatus", "ssm:UpdateInstanceAssociationStatus", "ssm:UpdateInstanceInformation" ], resources=["*"], principals=principals), vpc=vpc) self.create_interface_endpoint( "ec2", security_group=endpoint_sg, interface_endpoint_policy=_iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=["ec2:Describe*"], resources=["*"], principals=principals), vpc=vpc) self.create_interface_endpoint( "ssmmessages", security_group=endpoint_sg, interface_endpoint_policy=_iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=[ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel" ], resources=["*"], principals=principals), vpc=vpc) self.create_interface_endpoint( "ec2messages", security_group=endpoint_sg, interface_endpoint_policy=_iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=[ "ec2messages:AcknowledgeMessage", "ec2messages:DeleteMessage", "ec2messages:FailMessage", "ec2messages:GetEndpoint", "ec2messages:GetMessages", "ec2messages:SendReply" ], resources=["*"], principals=principals), vpc=vpc) self.create_interface_endpoint( "logs", security_group=endpoint_sg, interface_endpoint_policy=_iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=[ "logs:PutLogEvents", "logs:DescribeLogStreams", "logs:DescribeLogGroups", "logs:CreateLogStream", "logs:CreateLogGroup" ], resources=["*"], principals=principals), vpc=vpc) self.create_interface_endpoint( "monitoring", security_group=endpoint_sg, interface_endpoint_policy=_iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=["cloudwatch:PutMetricData"], resources=["*"], principals=principals), vpc=vpc) self.create_gateway_endpoint( "s3", vpc=vpc, gateway_endpoint_policy=_iam.PolicyStatement( effect=_iam.Effect.ALLOW, actions=["s3:GetObject", "s3:PutObject"], resources=[ "arn:aws:s3:::aws-ssm-" + self.region + "/*", "arn:aws:s3:::aws-windows-downloads-" + self.region + "/*", "arn:aws:s3:::amazon-ssm-" + self.region + "/*", "arn:aws:s3:::amazon-ssm-packages-" + self.region + "/*", "arn:aws:s3:::" + self.region + "-birdwatcher-prod/*", "arn:aws:s3:::aws-ssm-distributor-file-" + self.region + "/*", "arn:aws:s3:::patch-baseline-snapshot-" + self.region + "/*", "arn:aws:s3:::amazoncloudwatch-agent-" + self.region + "/*", "arn:aws:s3:::" + self.node.try_get_context("qs_s3_bucket") + "-" + self.region + "/*" ], principals=[_iam.AnyPrincipal()]))
def __init__( self, scope: Construct, id: str, context: "Context", team_name: str, team_policies: List[str], image: Optional[str], ) -> None: self.scope = scope self.id = id self.context: "Context" = context self.team_name: str = team_name self.team_policies: List[str] = team_policies self.image: Optional[str] = image super().__init__( scope=scope, id=id, stack_name=id, env=Environment(account=self.context.account_id, region=self.context.region), ) Tags.of(scope=cast(IConstruct, self)).add( key="Env", value=f"orbit-{self.context.name}") Tags.of(scope=cast(IConstruct, self)).add(key="TeamSpace", value=self.team_name) if self.context.networking.vpc_id is None: raise ValueError("self.context.networking.vpc_id is None!") self.i_vpc = ec2.Vpc.from_vpc_attributes( scope=self, id="vpc", vpc_id=self.context.networking.vpc_id, availability_zones=cast( List[str], self.context.networking.availability_zones), ) self.i_isolated_subnets = Ec2Builder.build_subnets( scope=self, subnet_manifests=context.networking.isolated_subnets) self.i_private_subnets = Ec2Builder.build_subnets( scope=self, subnet_manifests=context.networking.private_subnets) administrator_arns: List[str] = [ ] # A place to add other admins if needed for KMS admin_principals = iam.CompositePrincipal( *[iam.ArnPrincipal(arn) for arn in administrator_arns], iam.ArnPrincipal(f"arn:aws:iam::{self.context.account_id}:root"), ) self.team_kms_key: kms.Key = kms.Key( self, id="kms-key", removal_policy=core.RemovalPolicy.RETAIN, enabled=True, enable_key_rotation=True, policy=iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["kms:*"], resources=["*"], principals=[cast(iam.IPrincipal, admin_principals)], ) ]), ) self.team_security_group: ec2.SecurityGroup = Ec2Builder.build_team_security_group( scope=self, context=context, team_name=self.team_name, vpc=self.i_vpc) self.policies: List[str] = self.team_policies if self.context.scratch_bucket_arn: self.scratch_bucket: s3.Bucket = cast( s3.Bucket, s3.Bucket.from_bucket_attributes( scope=self, id="scratch_bucket", bucket_arn=self.context.scratch_bucket_arn, bucket_name=self.context.scratch_bucket_arn.split(":::") [1], ), ) else: raise Exception( "Scratch bucket was not provided in Manifest ('ScratchBucketArn')" ) self.role_eks_pod = IamBuilder.build_team_role( scope=self, context=self.context, team_name=self.team_name, policy_names=self.policies, scratch_bucket=cast(s3.IBucket, self.scratch_bucket), team_kms_key=self.team_kms_key, ) shared_fs_name: str = f"orbit-{context.name}-{self.team_name}-shared-fs" if context.shared_efs_fs_id is None: raise Exception( "Shared EFS File system ID was not provided in Manifest ('SharedEfsFsId')" ) if context.shared_efs_sg_id is None: raise Exception( "Shared EFS File system security group ID was not provided in Manifest ('SharedEfsSgId')" ) self.shared_fs: efs.FileSystem = cast( efs.FileSystem, efs.FileSystem.from_file_system_attributes( scope=self, id=shared_fs_name, file_system_id=context.shared_efs_fs_id, security_group=ec2.SecurityGroup.from_security_group_id( scope=self, id="team_sec_group", security_group_id=context.shared_efs_sg_id), ), ) self.efs_ap: efs.AccessPoint = EfsBuilder.build_file_system_access_point( scope=self, team_name=team_name, shared_fs=self.shared_fs) team_ssm_parameter_name: str = f"/orbit/{context.name}/teams/{self.team_name}/team" self.context_parameter: ssm.StringParameter = ssm.StringParameter( scope=self, id=team_ssm_parameter_name, string_value=json.dumps({ "EfsId": self.shared_fs.file_system_id, "EfsApId": self.efs_ap.access_point_id, "EksPodRoleArn": self.role_eks_pod.role_arn, "ScratchBucket": self.scratch_bucket.bucket_name, "TeamKmsKeyArn": self.team_kms_key.key_arn, "TeamSecurityGroupId": self.team_security_group.security_group_id, }), type=ssm.ParameterType.STRING, description="Orbit Workbench Team Context.", parameter_name=team_ssm_parameter_name, simple_name=False, tier=ssm.ParameterTier.INTELLIGENT_TIERING, ) ssm_profile_name = f"/orbit/{self.context.name}/teams/{self.team_name}/user/profiles" self.user_profiles: ssm.StringParameter = ssm.StringParameter( scope=self, id=ssm_profile_name, string_value="[]", type=ssm.ParameterType.STRING, description="Team additional profiles created by the team users", parameter_name=ssm_profile_name, simple_name=False, tier=ssm.ParameterTier.INTELLIGENT_TIERING, )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) sns_principals_mapping = core.CfnMapping( scope=self, id="Inspector SNS Principals", mapping={ "eu-central-1": { "ARN": "arn:aws:iam::537503971621:root" }, "us-east-1": { "ARN": "arn:aws:iam::316112463485:root" }, "eu-west-1": { "ARN": "arn:aws:iam::357557129151:root" }, "us-east-2": { "ARN": "arn:aws:iam::646659390643:root" }, } ) inspector_rules_mapping = core.CfnMapping( scope=self, id="Inspector Rule packages", mapping={ "eu-central-1": { "CVE": "arn:aws:inspector:eu-central-1:537503971621:rulespackage/0-wNqHa8M9", "CIS": "arn:aws:inspector:eu-central-1:537503971621:rulespackage/0-nZrAVuv8", "securityBestPractices": "arn:aws:inspector:eu-central-1:537503971621:rulespackage/0-ZujVHEPB", "runtimeBehaviorAnalysis": "arn:aws:inspector:eu-central-1:537503971621:rulespackage/0-0GMUM6fg" }, "eu-west-1": { "CVE": "arn:aws:inspector:eu-west-1:357557129151:rulespackage/0-ubA5XvBh", "CIS": "arn:aws:inspector:eu-west-1:357557129151:rulespackage/0-sJBhCr0F", "securityBestPractices": "arn:aws:inspector:eu-west-1:357557129151:rulespackage/0-SnojL3Z6", "runtimeBehaviorAnalysis": "arn:aws:inspector:eu-west-1:357557129151:rulespackage/0-lLmwe1zd" }, "us-east-1": { "CVE": "arn:aws:inspector:us-east-1:316112463485:rulespackage/0-gEjTy7T7", "CIS": "arn:aws:inspector:us-east-1:316112463485:rulespackage/0-rExsr2X8", "securityBestPractices": "arn:aws:inspector:us-east-1:316112463485:rulespackage/0-R01qwB5Q", "runtimeBehaviorAnalysis": "arn:aws:inspector:us-east-1:316112463485:rulespackage/0-gBONHN9h" }, "us-east-2": { "CVE": "arn:aws:inspector:us-east-2:646659390643:rulespackage/0-JnA8Zp85", "CIS": "arn:aws:inspector:us-east-2:646659390643:rulespackage/0-m8r61nnh", "securityBestPractices": "arn:aws:inspector:us-east-2:646659390643:rulespackage/0-AxKmMHPX", "runtimeBehaviorAnalysis": "arn:aws:inspector:us-east-2:646659390643:rulespackage/0-UCYZFKPV" }, } ) resource_group = inspector.CfnResourceGroup( scope=self, id="CDK test resource group", resource_group_tags=[core.CfnTag(key="Inspector", value="true")] ) assessment_target = inspector.CfnAssessmentTarget( scope=self, id="CDK test assessment target", resource_group_arn=resource_group.attr_arn ) assessment_template = inspector.CfnAssessmentTemplate( scope=self, id="CDK test assessment template", assessment_target_arn=assessment_target.attr_arn, duration_in_seconds=300, rules_package_arns=[ inspector_rules_mapping.find_in_map(self.region, package) for package in ( "CVE", "CIS", "securityBestPractices", "runtimeBehaviorAnalysis" ) ] ) report_function = aws_lambda.Function( scope=self, id="CDK Inspector test report processor", code=aws_lambda.Code.from_asset("report_function"), handler="report.lambda_handler", runtime=aws_lambda.Runtime.PYTHON_3_7 ) topic = sns.Topic( scope=self, id="CDK Inspector topic" ) topic.add_to_resource_policy( statement=iam.PolicyStatement( actions=["SNS:Publish"], principals=[iam.ArnPrincipal(arn=sns_principals_mapping.find_in_map(self.region, "ARN"))], resources=[topic.topic_arn] ) ) topic.add_subscription( subscription=sns_subs.LambdaSubscription(fn=report_function) ) subscriber = InspectorSubscriberCustomResource( scope=self, id="Inspector SNS Subscriber", Template=assessment_template.attr_arn, Topic=topic.topic_arn )
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.current_dir = os.path.dirname(__file__) self.bucket = s3.Bucket( self, "qs-migration-bucket", bucket_name=f'quicksight-migration-{core.Aws.ACCOUNT_ID}', block_public_access=s3.BlockPublicAccess.BLOCK_ALL, ) self.quicksight_migration_lambda_role = iam.Role( self, 'quicksight-migration-lambda-role', description='Role for the Quicksight dashboard migration Lambdas', role_name='quicksight-migration-lambda-role', max_session_duration=core.Duration.seconds(3600), assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'AllowAccess': iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ], resources=[ f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*' ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["sts:AssumeRole", "iam:ListRoles"], resources=[ "arn:aws:iam::*:role/quicksight-migration-*-assume-role" ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["s3:PutObject", "s3:ListBucket"], resources=[ self.bucket.bucket_arn, f"{self.bucket.bucket_arn}/*" ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["secrets:GetSecretValue"], resources=[ f"arn:aws:secretsmanager:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:secret:*" ]), iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=[ "quicksight:*", ], resources=["*"]) ]) }) # API Gateway to SQS self.apigw_sqs = ApiGatewayToSqs( self, "ApiGatewayToSQSqsMigration", allow_create_operation=True, allow_read_operation=False, allow_delete_operation=False, api_gateway_props=apigw.RestApiProps( rest_api_name="quicksight-migration-sqs", deploy=True, default_method_options=apigw.MethodOptions( authorization_type=apigw.AuthorizationType.NONE), default_cors_preflight_options=apigw.CorsOptions( allow_origins=apigw.Cors.ALL_ORIGINS, allow_methods=apigw.Cors.ALL_METHODS, allow_headers=[ 'Access-Control-Allow-Origin', 'Access-Control-Allow-Headers', 'Content-Type' ]), policy=iam.PolicyDocument(statements=[ iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=['execute-api:Invoke'], resources=["execute-api:/prod/*"], principals=[iam.ArnPrincipal("*")]) ])), queue_props=sqs.QueueProps( queue_name="quicksight-migration-sqs", visibility_timeout=core.Duration.minutes(15))) self.quicksight_migration_lambda = _lambda.Function( self, 'quicksight-migration-lambda', handler='quicksight_migration.lambda_function.lambda_handler', runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.from_asset( os.path.join(self.current_dir, '../lambda/quicksight_migration/')), function_name='quicksight_migration_lambda', role=self.quicksight_migration_lambda_role, timeout=core.Duration.minutes(15), memory_size=1024, environment={ 'BUCKET_NAME': self.bucket.bucket_name, 'S3_KEY': 'None', 'INFRA_CONFIG_PARAM': '/infra/config', 'SQS_URL': self.apigw_sqs.sqs_queue.queue_url }) self.quicksight_migration_lambda.add_event_source( event_sources.SqsEventSource( enabled=True, queue=self.apigw_sqs.sqs_queue, ))
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) self.current_dir = os.path.dirname(__file__) self.website_bucket = s3.Bucket( self, "qs-embed-bucket", bucket_name=f'quicksight-embed-{core.Aws.ACCOUNT_ID}', website_index_document="index.html", public_read_access=True) self.quicksight_embed_lambda_role = iam.Role( self, 'quicksight-embed-lambda-role', description='Role for the Quicksight dashboard embed Lambdas', role_name='quicksight-embed-lambda-role', max_session_duration=core.Duration.seconds(3600), assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'AllowAccess': iam.PolicyDocument(statements=[ iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ 'logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents' ], resources=[ f'arn:aws:logs:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:*' ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["sts:AssumeRole", "iam:ListRoles"], resources=[ "arn:aws:iam::*:role/quicksight-migration-*-assume-role" ]), iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["secrets:GetSecretValue"], resources=[ f"arn:aws:secretsmanager:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:secret:*" ]), iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=[ "quicksight:*", ], resources=["*"]) ]) }) self.quicksight_migration_lambda = _lambda.Function( self, 'quicksight-migration-lambda', handler='quicksight_embed.lambda_handler', runtime=_lambda.Runtime.PYTHON_3_8, code=_lambda.Code.from_asset( os.path.join(self.current_dir, '../lambda/quicksight_embed/')), function_name='quicksight_embed_lambda', role=self.quicksight_embed_lambda_role, timeout=core.Duration.minutes(3), memory_size=512, environment={ 'DASHBOARD_ID': '938b365e-c001-4723-9a27-029654da7531', 'QUICKSIGHT_USER_ARN': f'arn:aws:quicksight:us-east-1:{core.Aws.ACCOUNT_ID}:user/default/quicksight-migration-user' }) self.apigw_lambda = ApiGatewayToLambda( self, "ApiGatewayToLambdaQSEmbed", existing_lambda_obj=self.quicksight_migration_lambda, api_gateway_props=apigw.LambdaRestApiProps( rest_api_name="quicksight-embed", handler=self.quicksight_migration_lambda, deploy=True, proxy=False, default_method_options=apigw.MethodOptions( authorization_type=apigw.AuthorizationType.NONE), default_cors_preflight_options=apigw.CorsOptions( allow_origins=apigw.Cors.ALL_ORIGINS, allow_methods=apigw.Cors.ALL_METHODS, allow_headers=[ 'Access-Control-Allow-Origin', 'Access-Control-Allow-Headers', 'Content-Type' ]), policy=iam.PolicyDocument(statements=[ iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=['execute-api:Invoke'], resources=["execute-api:/prod/*"], principals=[iam.ArnPrincipal("*")]) ]))) self.embedurl = self.apigw_lambda.api_gateway.root.add_resource( "embedurl") self.embedurl.add_method("GET")
def __init__(self, scope: core.Construct, name: str, vpc: ec2.Vpc, **kwargs) -> None: super().__init__(scope, name, **kwargs) cluster = eks.Cluster(self, 'coscup-jenkins-demo-cluster', vpc=vpc, version=eks.KubernetesVersion.V1_16, default_capacity=0) asg_worker_nodes = cluster.add_capacity( 'worker-node', instance_type=ec2.InstanceType('t3a.large'), spot_price='0.0936', desired_capacity=2) asg_jenkins_slave = cluster.add_capacity( 'worker-node-jenkins-slave', instance_type=ec2.InstanceType('t3a.small'), spot_price='0.0234', desired_capacity=1, bootstrap_options=eks.BootstrapOptions( kubelet_extra_args= '--node-labels jenkins=slave --register-with-taints jenkins=slave:NoSchedule' )) asg_worker_nodes.connections.allow_from(asg_jenkins_slave, ec2.Port.all_traffic()) asg_jenkins_slave.connections.allow_from(asg_worker_nodes, ec2.Port.all_traffic()) eks_master_role = iam.Role(self, 'AdminRole', assumed_by=iam.ArnPrincipal( get_eks_admin_iam_username())) cluster.aws_auth.add_masters_role(eks_master_role) stable_chart = 'https://kubernetes-charts.storage.googleapis.com' eks.HelmChart( self, 'jenkins', release='jenkins', cluster=cluster, repository=stable_chart, chart='jenkins', namespace='jenkins', version='2.3.3', values={ 'master': { 'tag': '2.235.1', 'adminPassword': '******', 'serviceType': 'LoadBalancer', 'installPlugins': [ 'kubernetes:1.26.3', 'git:4.3.0', 'workflow-aggregator:2.6', 'credentials-binding:1.23', 'workflow-job:2.39', 'configuration-as-code:1.42', 'job-dsl:1.77' ], 'serviceAnnotations': { 'service.beta.kubernetes.io/aws-load-balancer-type': 'nlb' }, 'JCasC': { 'enabled': True, 'configScripts': { 'settings': read_helm_config( 'eks_cluster/helm_config/jenkins-jcasc-settings.yaml' ) } } } }) eks.HelmChart(self, 'kube-ops-view', release='kube-ops-view', cluster=cluster, repository=stable_chart, chart='kube-ops-view', namespace='monitor', version='1.2.0', values={ 'service': { 'type': 'LoadBalancer' }, 'rbac': { 'create': True } }) eks.HelmChart(self, 'dummy-service', release='dummy-service', cluster=cluster, repository=stable_chart, chart='kibana', namespace='default', version='3.2.6', values={'replicaCount': '60'})
def __init__(self, scope: cdk.Construct, id: str, s3_bucket: s3.Bucket, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Define IAM roles and policies ecs_task_role = iam.Role( self, "TaskRole", role_name="ConsoleMeTaskRole", assumed_by=iam.ServicePrincipal("ecs-tasks.amazonaws.com"), ) ecs_task_role.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ "access-analyzer:*", "cloudtrail:*", "cloudwatch:*", "config:SelectResourceConfig", "config:SelectAggregateResourceConfig", "dynamodb:batchgetitem", "dynamodb:batchwriteitem", "dynamodb:deleteitem", "dynamodb:describe*", "dynamodb:getitem", "dynamodb:getrecords", "dynamodb:getsharditerator", "dynamodb:putitem", "dynamodb:query", "dynamodb:scan", "dynamodb:updateitem", "secretsmanager:GetResourcePolicy", "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds", "secretsmanager:ListSecrets", "sns:createplatformapplication", "sns:createplatformendpoint", "sns:deleteendpoint", "sns:deleteplatformapplication", "sns:getendpointattributes", "sns:getplatformapplicationattributes", "sns:listendpointsbyplatformapplication", "sns:publish", "sns:setendpointattributes", "sns:setplatformapplicationattributes", "sts:assumerole", ], resources=["*"], )) ecs_task_role.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["ses:sendemail", "ses:sendrawemail"], resources=["*"], )) ecs_task_role.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ "autoscaling:Describe*", "cloudwatch:Get*", "cloudwatch:List*", "config:BatchGet*", "config:List*", "config:Select*", "ec2:DescribeSubnets", "ec2:describevpcendpoints", "ec2:DescribeVpcs", "iam:GetAccountAuthorizationDetails", "iam:ListAccountAliases", "iam:ListAttachedRolePolicies", "ec2:describeregions", "s3:GetBucketPolicy", "s3:GetBucketTagging", "s3:ListAllMyBuckets", "s3:ListBucket", "s3:PutBucketPolicy", "s3:PutBucketTagging", "sns:GetTopicAttributes", "sns:ListTagsForResource", "sns:ListTopics", "sns:SetTopicAttributes", "sns:TagResource", "sns:UnTagResource", "sqs:GetQueueAttributes", "sqs:GetQueueUrl", "sqs:ListQueues", "sqs:ListQueueTags", "sqs:SetQueueAttributes", "sqs:TagQueue", "sqs:UntagQueue", ], resources=["*"], )) ecs_task_role.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["s3:GetObject", "s3:ListBucket"], resources=[s3_bucket.bucket_arn, s3_bucket.bucket_arn + "/*"], )) trust_role = iam.Role( self, "TrustRole", role_name="ConsoleMeTrustRole", assumed_by=iam.ArnPrincipal(arn=ecs_task_role.role_arn), ) trust_role.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=[ "access-analyzer:*", "cloudtrail:*", "cloudwatch:*", "config:SelectResourceConfig", "config:SelectAggregateResourceConfig", "dynamodb:batchgetitem", "dynamodb:batchwriteitem", "dynamodb:deleteitem", "dynamodb:describe*", "dynamodb:getitem", "dynamodb:getrecords", "dynamodb:getsharditerator", "dynamodb:putitem", "dynamodb:query", "dynamodb:scan", "dynamodb:updateitem", "sns:createplatformapplication", "sns:createplatformendpoint", "sns:deleteendpoint", "sns:deleteplatformapplication", "sns:getendpointattributes", "sns:getplatformapplicationattributes", "sns:listendpointsbyplatformapplication", "sns:publish", "sns:setendpointattributes", "sns:setplatformapplicationattributes", "sts:assumerole", "autoscaling:Describe*", "cloudwatch:Get*", "cloudwatch:List*", "config:BatchGet*", "config:List*", "config:Select*", "ec2:DescribeSubnets", "ec2:describevpcendpoints", "ec2:DescribeVpcs", "iam:GetAccountAuthorizationDetails", "iam:ListAccountAliases", "iam:ListAttachedRolePolicies", "ec2:describeregions", "s3:GetBucketPolicy", "s3:GetBucketTagging", "s3:ListAllMyBuckets", "s3:ListBucket", "s3:PutBucketPolicy", "s3:PutBucketTagging", "sns:GetTopicAttributes", "sns:ListTagsForResource", "sns:ListTopics", "sns:SetTopicAttributes", "sns:TagResource", "sns:UnTagResource", "sqs:GetQueueAttributes", "sqs:GetQueueUrl", "sqs:ListQueues", "sqs:ListQueueTags", "sqs:SetQueueAttributes", "sqs:TagQueue", "sqs:UntagQueue", ], resources=["*"], )) ecs_task_execution_role = iam.Role( self, "TaskExecutionRole", assumed_by=iam.ServicePrincipal("ecs-tasks.amazonaws.com"), ) ecs_task_execution_role.add_managed_policy( iam.ManagedPolicy.from_managed_policy_arn( self, "ServiceRole", managed_policy_arn= "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy", )) create_configuration_lambda_role = iam.Role( self, "CreateConfigurationFileLambdaRole", assumed_by=iam.ServicePrincipal(service="lambda.amazonaws.com"), ) create_configuration_lambda_role.add_managed_policy( iam.ManagedPolicy.from_managed_policy_arn( self, "ConfigurationBasicExecution", managed_policy_arn= "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", )) create_configuration_lambda_role.add_to_policy( iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["s3:PutObject", "s3:DeleteObject"], resources=[s3_bucket.bucket_arn + "/*"], )) self.ecs_task_role = ecs_task_role self.ecs_task_execution_role = ecs_task_execution_role self.create_configuration_lambda_role = create_configuration_lambda_role