Пример #1
0
    def configure_dns(self, zone: r53.IHostedZone) -> None:
        # Add FSX Records
        r53.ARecord(self,
                    'DnsRecord',
                    zone=zone,
                    comment='Name Record for ' +
                    NetworkFileSystemsConstruct.__name__,
                    record_name='winfs.{}'.format(zone.zone_name),
                    ttl=core.Duration.seconds(60),
                    target=r53.RecordTarget(values=['10.10.35.85']))

        # This is only required for parity with devbox
        # r53.ARecord(self,'TempDnsRecord',
        #   zone=zone,
        #   comment='Name Record for '+NetworkFileSystemsConstruct.__name__,
        #   record_name='amznfsxkw4byw3j.{}'.format(zone.zone_name),
        #   ttl=core.Duration.seconds(60),
        #   target=r53.RecordTarget(
        #     values= ['10.10.35.85'] ))

        # Add efs sources...
        for entry in [
                # ('homenet.efs.virtual.world', self.homenet.file_system_id),
            ('app-data.efs.virtual.world', self.app_data.file_system_id)
        ]:
            name, target = entry
            r53.CnameRecord(self,
                            name,
                            domain_name='{}.efs.{}.amazonaws.com'.format(
                                target,
                                core.Stack.of(self).region),
                            zone=zone,
                            record_name=name,
                            ttl=core.Duration.minutes(1))
Пример #2
0
    def setup_etcd(self, vpc, zone, sg, key):
        for n in range(0, 3):
            # cdk bug?
            (cloud_user_data, )= ec2.UserData.for_linux(),
            cloud_user_data.add_commands('apt update',
                                         'apt install -y etcd-server etcd-client',
                                         "echo ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd%d.int.emqx:2380 >> /etc/default/etcd" % n,
                                         'echo ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 >> /etc/default/etcd',
                                         'echo ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 >> /etc/default/etcd',
                                         "echo ETCD_ADVERTISE_CLIENT_URLS=http://etcd%d.int.emqx:2379 >> /etc/default/etcd" % n,
                                         "echo ETCD_NAME=infra%d >> /etc/default/etcd" % n,
                                         'echo ETCD_INITIAL_CLUSTER_STATE=new >> /etc/default/etcd',
                                         'echo ETCD_INITIAL_CLUSTER_TOKEN=emqx-cluster-1 >> /etc/default/etcd',
                                         'echo ETCD_INITIAL_CLUSTER="infra0=http://etcd0.int.emqx:2380,infra1=http://etcd1.int.emqx:2380,infra2=http://etcd2.int.emqx:2380" >> /etc/default/etcd',
                                         'systemctl restart etcd'
            )
            ins = ec2.Instance(self, id = "etsd.%d" % n,
                               instance_type=ec2.InstanceType(instance_type_identifier="t3a.nano"),
                               machine_image=linux_ami,
                               user_data=cloud_user_data,
                               security_group = sg,
                               key_name=key,
                               vpc = vpc
            )

            r53.ARecord(self, id = "etcd%d.int.emqx" % n,
                        record_name = "etcd%d.int.emqx" % n,
                        zone = zone,
                        target = r53.RecordTarget([ins.instance_private_ip])
            )

            if self.user_defined_tags:
                core.Tags.of(ins).add(*self.user_defined_tags)
            core.Tags.of(ins).add('service', 'etcd')
Пример #3
0
    def setup_emqx(self, N, vpc, zone, sg, key):
        self.emqx_vms = []
        for n in range(0, N):
            name = "emqx-%d" % n
            vm = ec2.Instance(self, id = name,
                              instance_type = ec2.InstanceType(instance_type_identifier=emqx_ins_type),
                              machine_image = linux_ami,
                              user_data = ec2.UserData.custom(user_data),
                              security_group = sg,
                              key_name = key,
                              vpc = vpc,
                              vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
            )

            self.emqx_vms.append(vm)

            r53.ARecord(self, id = name + '.int.emqx',
                        record_name = name + '.int.emqx',
                        zone = zone,
                        target = r53.RecordTarget([vm.instance_private_ip])
            )

            # tagging
            if self.user_defined_tags:
                core.Tags.of(vm).add(*self.user_defined_tags)
            core.Tags.of(vm).add('service', 'emqx')
Пример #4
0
 def configure_dns(self,zone:r53.IHostedZone):
   r53.ARecord(self,'HostRecord',
     zone=zone,
     record_name='rtsp-connector.{}'.format(zone.zone_name),
     ttl = core.Duration.minutes(1),
     target= r53.RecordTarget(
       values=[self.instance.instance_private_ip]
     ))
Пример #5
0
    def setup_loadgen(self, N, vpc, zone, sg, key, target):
        for n in range(0, N):
            name = "loadgen-%d" % n
            src_ips = ','.join([ "192.168.%d.%d" % (n, x) for x in range(10, 20)])
            bootScript = ec2.UserData.custom(loadgen_user_data)
            configIps = ec2.UserData.for_linux()
            configIps.add_commands("for x in $(seq 2 250); do ip addr add 192.168.%d.$x dev ens5; done" % n)
            runscript = ec2.UserData.for_linux()
            runscript.add_commands("""cat << EOF > /root/emqtt_bench/run.sh
            #!/bin/bash
            ulimit -n 1000000
            ipaddrs=`for n in $(seq 2 13); do printf "192.168.%d.%%d," $n; done `
            _build/default/bin/emqtt_bench sub -h %s -t "root/%%c/1/+/abc/#" -c 200000 --prefix "prefix%d" --ifaddr %s -i 5
EOF
            """ % (n, target, n, src_ips)
            )
            multipartUserData = ec2.MultipartUserData()
            multipartUserData.add_part(ec2.MultipartBody.from_user_data(bootScript))
            multipartUserData.add_part(ec2.MultipartBody.from_user_data(configIps))
            multipartUserData.add_part(ec2.MultipartBody.from_user_data(runscript))
            lg_vm = ec2.Instance(self, id = name,
                                 instance_type=ec2.InstanceType(instance_type_identifier=loadgen_ins_type),
                                 machine_image=linux_ami,
                                 user_data = multipartUserData,
                                 security_group = sg,
                                 key_name=key,
                                 vpc = vpc,
                                 source_dest_check = False
            )
            i=1
            for net in vpc.private_subnets:
                net.add_route(id=name+str(i),
                              router_id = lg_vm.instance_id,
                              router_type = ec2.RouterType.INSTANCE,
                              destination_cidr_block = "192.168.%d.0/24" % n)
                i+=1

            r53.ARecord(self, id = name + '.int.emqx',
                        record_name = name + '.int.emqx',
                        zone = zone,
                        target = r53.RecordTarget([lg_vm.instance_private_ip])
            )

            if self.user_defined_tags:
                core.Tags.of(ins).add(*self.user_defined_tags)
            core.Tags.of(lg_vm).add('service', 'loadgen')
Пример #6
0
    def __init__(self, scope: cdk.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        environment = self.node.try_get_context('environment')
        server_domain = self.node.try_get_context('server_domain')
        hosted_zone_id = self.node.try_get_context('hosted_zone_id')

        if environment == 'prod':
            self.domain_name = f'start.{server_domain}'
        else:
            self.domain_name = f'start.{environment}.{server_domain}'

        hosted_zone = r53.HostedZone.from_hosted_zone_attributes(
            self,
            'Zone',
            hosted_zone_id=hosted_zone_id,
            zone_name=server_domain)
        certificate = acm.Certificate(
            self,
            'StartCert',
            domain_name=self.domain_name,
            validation=acm.CertificateValidation.from_dns(
                hosted_zone=hosted_zone))
        self.rest_api = apigw.RestApi(
            self,
            'api',
            domain_name=apigw.DomainNameOptions(certificate=certificate,
                                                domain_name=self.domain_name),
            deploy_options=apigw.StageOptions(stage_name=environment))
        arecord = r53.ARecord(
            self,
            'StartARecord',
            zone=hosted_zone,
            record_name=self.domain_name,
            target=r53.RecordTarget(
                alias_target=r53_targets.ApiGateway(self.rest_api)))
        cdk.CfnOutput(self, 'DNSName', value=arecord.domain_name)
Пример #7
0
    def __init__(
        self,
        scope: cdk.Construct,
        id: str,
        consoleme_alb: lb.ApplicationLoadBalancer,
        **kwargs
    ) -> None:
        super().__init__(scope, id, **kwargs)

        hosted_zone = route53.PublicHostedZone.from_hosted_zone_attributes(
            self,
            "HostedZone",
            hosted_zone_id=HOSTED_ZONE_ID,
            zone_name=HOSTED_ZONE_NAME,
        )

        route53_record = route53.ARecord(
            self,
            "LBRecord",
            zone=hosted_zone,
            record_name=APPLICATION_PREFIX,
            target=route53.RecordTarget(
                alias_target=(route53_targets.LoadBalancerTarget(consoleme_alb))
            ),
        )

        verify_ses_identity = cr.AwsCustomResource(
            self,
            "VerifySESIdentityResource",
            policy=cr.AwsCustomResourcePolicy.from_statements(
                statements=[
                    iam.PolicyStatement(
                        effect=iam.Effect.ALLOW,
                        actions=["ses:VerifyDomainIdentity", "ses:DeleteIdentity"],
                        resources=["*"],
                    )
                ]
            ),
            on_create=cr.AwsSdkCall(
                service="SES",
                action="verifyDomainIdentity",
                parameters={"Domain": route53_record.domain_name},
                physical_resource_id=cr.PhysicalResourceId.from_response(
                    "VerificationToken"
                ),
            ),
            on_delete=cr.AwsSdkCall(
                service="SES",
                action="deleteIdentity",
                parameters={"Identity": route53_record.domain_name},
            ),
            install_latest_aws_sdk=True,
            log_retention=logs.RetentionDays.ONE_WEEK,
        )

        add_ses_dkim = cr.AwsCustomResource(
            self,
            "VerifySESDKIMResource",
            policy=cr.AwsCustomResourcePolicy.from_statements(
                statements=[
                    iam.PolicyStatement(
                        effect=iam.Effect.ALLOW,
                        actions=["ses:VerifyDomainDkim"],
                        resources=["*"],
                    )
                ]
            ),
            on_create=cr.AwsSdkCall(
                service="SES",
                action="verifyDomainDkim",
                parameters={"Domain": route53_record.domain_name},
                physical_resource_id=cr.PhysicalResourceId.of(
                    HOSTED_ZONE_ID + "VerifyDomainDKIM"
                ),
            ),
            install_latest_aws_sdk=True,
            log_retention=logs.RetentionDays.ONE_WEEK,
        )

        add_ses_dkim.node.add_dependency(verify_ses_identity)

        certificate = acm.Certificate(
            self,
            "Certificate",
            domain_name="*." + hosted_zone.zone_name,
            validation=acm.CertificateValidation.from_dns(hosted_zone=hosted_zone),
        )

        self.hosted_zone = hosted_zone
        self.certificate = certificate
        self.route53_record = route53_record
Пример #8
0
    def __init__(self, scope: core.Construct, id: str, props,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        pearson_vpn_connection = ec2.Peer.ipv4('159.182.0.0/16')

        # Props Setup
        stage = scope.node.try_get_context('stage')
        my_service_name = scope.node.try_get_context('serviceName')
        api_health_path = props['apiHealthPath']
        tca_health_path = props['tcaHealthPath']

        # Setup IAM user for logs
        vpc_flow_role = iam.Role(
            self,
            'FlowLog',
            assumed_by=iam.ServicePrincipal('vpc-flow-logs.amazonaws.com'))

        vpc_flow_role.add_to_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                actions=[
                                    'iam:PassRole', 'logs:CreateLogGroup',
                                    'logs:DescribeLogGroups',
                                    'logs:CreateLogStream', 'logs:PutLogEvents'
                                ],
                                resources=["*"]))

        # Create Cloudwatch log group
        log_group = logs.LogGroup(self,
                                  'LogGroup',
                                  log_group_name="{0}-{1}".format(
                                      my_service_name, stage),
                                  retention=logs.RetentionDays('ONE_YEAR'),
                                  removal_policy=core.RemovalPolicy('DESTROY'))

        # Setup VPC resource
        vpc = ec2.Vpc(self,
                      '{0}-{1}-vpc'.format(my_service_name, stage),
                      cidr=props['cidr'],
                      max_azs=props['vpcAzCount'])

        # Setup VPC flow logs
        vpc_log = ec2.CfnFlowLog(
            self,
            'FlowLogs',
            resource_id=vpc.vpc_id,
            resource_type='VPC',
            traffic_type='ALL',
            deliver_logs_permission_arn=vpc_flow_role.role_arn,
            log_destination_type='cloud-watch-logs',
            log_group_name="{0}-{1}".format(log_group.log_group_name, stage))

        # Setup Security Group in VPC
        vpc_sg = ec2.SecurityGroup(self,
                                   'EcSSG',
                                   vpc=vpc,
                                   allow_all_outbound=None,
                                   description="Security Group for Oculus vpc",
                                   security_group_name="{0}-{1}-vpc-sg".format(
                                       my_service_name, stage))

        # Add Rules to Security Group
        vpc_sg.add_ingress_rule(peer=pearson_vpn_connection,
                                connection=ec2.Port.tcp(22))

        # ALB Security Group
        alb_sg = ec2.SecurityGroup(self,
                                   'AlbSG',
                                   vpc=vpc,
                                   allow_all_outbound=None,
                                   description="Security group for oculus ALB",
                                   security_group_name="{0}-{1}-alb-sg".format(
                                       my_service_name, stage))

        # Add HTTPS Rule to Security Group
        alb_sg.add_ingress_rule(peer=pearson_vpn_connection,
                                connection=ec2.Port.tcp(443))

        # Setup ALB
        alb = elbv2.ApplicationLoadBalancer(self,
                                            'ALB',
                                            vpc=vpc,
                                            internet_facing=True,
                                            security_group=alb_sg)

        # Setup API Target Group
        api_tg = elbv2.ApplicationTargetGroup(
            self,
            'ApiTargetGroup',
            port=8080,
            protocol=elbv2.ApplicationProtocol.HTTP,
            vpc=vpc)

        # Setup Web Target Group
        web_tg = elbv2.ApplicationTargetGroup(
            self,
            'WebTargetGroup',
            port=3030,
            protocol=elbv2.ApplicationProtocol.HTTP,
            vpc=vpc)

        # Setup API Target Group
        tca_tg = elbv2.ApplicationTargetGroup(
            self,
            'TcaTargetGroup',
            port=8080,
            protocol=elbv2.ApplicationProtocol.HTTP,
            vpc=vpc)

        # Setup ECS Cluster
        ecs_cluster = ecs.Cluster(self,
                                  'ECSCluster',
                                  vpc=vpc,
                                  cluster_name="{0}-{1}".format(
                                      my_service_name, stage))

        # ECS Execution Role - Grants ECS agent to call AWS APIs
        ecs_execution_role = iam.Role(
            self,
            'ECSExecutionRole',
            assumed_by=iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
            role_name="{0}-{1}-execution-role".format(my_service_name, stage))

        # Setup Role Permissions
        ecs_execution_role.add_to_policy(
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                actions=[
                    'elasticloadbalancing:DeregisterInstancesFromLoadBalancer',
                    'elasticloadbalancing:DeregisterTargets',
                    'elasticloadbalancing:Describe*',
                    'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
                    'elasticloadbalancing:RegisterTargets', 'ec2:Describe*',
                    'ec2:AuthorizeSecurityGroupIngress', 'sts:AssumeRole',
                    'ssm:GetParameters', 'secretsmanager:GetSecretValue',
                    'ecr:GetAuthorizationToken',
                    'ecr:BatchCheckLayerAvailability',
                    'ecr:GetDownloadUrlForLayer', 'ecr:BatchGetImage',
                    'logs:CreateLogStream', 'logs:PutLogEvents',
                    "application-autoscaling:*", "cloudwatch:DescribeAlarms",
                    "cloudwatch:PutMetricAlarm"
                ],
                resources=["*"]))

        # ECS Task Role - Grants containers in task permission to AWS APIs
        ecs_task_role = iam.Role(
            self,
            'ECSTaskRole',
            assumed_by=iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
            role_name="{0}-{1}-task-role".format(my_service_name, stage))

        # Setup Role Permissions
        ecs_task_role.add_to_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                actions=[
                                    'logs:CreateLogStream',
                                    'logs:PutLogEvents', 'dynamodb:Query',
                                    'dynamodb:ListTables',
                                    'secretsmanager:GetSecretValue',
                                    'kms:Decrypt'
                                ],
                                resources=["*"]))

        # Setup API Task Definition
        api_taskdef = ecs.FargateTaskDefinition(
            self,
            'APIFargateTask',
            memory_limit_mib=512,
            cpu=256,
            execution_role=ecs_execution_role,
            task_role=ecs_task_role,
            family="{0}-{1}-api".format(my_service_name, stage))

        # Setup Web Task Definition
        web_taskdef = ecs.FargateTaskDefinition(
            self,
            'WebFargateTask',
            memory_limit_mib=512,
            cpu=256,
            execution_role=ecs_execution_role,
            task_role=ecs_task_role,
            family="{0}-{1}-web".format(my_service_name, stage))

        # # Setup TCA Task Definition
        tca_taskdef = ecs.FargateTaskDefinition(
            self,
            'TcaFargateTask',
            memory_limit_mib=512,
            cpu=256,
            execution_role=ecs_execution_role,
            task_role=ecs_task_role,
            family="{0}-{1}-tca".format(my_service_name, stage))

        api_repo = ecr.Repository.from_repository_arn(
            self,
            'ApiImage',
            repository_arn=
            "arn:aws:ecr:us-east-1:346147488134:repository/oculus-api")

        web_repo = ecr.Repository.from_repository_arn(
            self,
            'WebImage',
            repository_arn=
            "arn:aws:ecr:us-east-1:346147488134:repository/oculus-web")

        tca_repo = ecr.Repository.from_repository_arn(
            self,
            'TcaImage',
            repository_arn=
            "arn:aws:ecr:us-east-1:346147488134:repository/oculus-tca-api")

        # Add Container API to Task
        api_container = api_taskdef.add_container(
            "oculus-cdk-{}-api".format(stage),
            image=ecs.EcrImage(repository=api_repo, tag="devqaurl"),
            logging=ecs.LogDriver.aws_logs(stream_prefix="{0}-{1}-api".format(
                my_service_name, stage),
                                           log_group=log_group))

        # Add Container Web to Task
        web_container = web_taskdef.add_container(
            "oculus-cdk-{}-web".format(stage),
            image=ecs.EcrImage(repository=web_repo, tag="removeMetaMockup"),
            logging=ecs.LogDriver.aws_logs(stream_prefix="{0}-{1}-web".format(
                my_service_name, stage),
                                           log_group=log_group))

        # # Add Container TCA to Task
        tca_container = tca_taskdef.add_container(
            "oculus-cdk-{}-tca".format(stage),
            image=ecs.EcrImage(repository=tca_repo, tag="ocu-1109"),
            logging=ecs.LogDriver.aws_logs(stream_prefix="{0}-{1}-tca".format(
                my_service_name, stage),
                                           log_group=log_group))

        # Setup API Port Mappings
        api_container.add_port_mappings(
            ecs.PortMapping(container_port=8080,
                            host_port=8080,
                            protocol=ecs.Protocol.TCP))

        # Setup Web Port Mappings
        web_container.add_port_mappings(
            ecs.PortMapping(container_port=3030,
                            host_port=3030,
                            protocol=ecs.Protocol.TCP))

        # # Setup TCA Port Mappings
        tca_container.add_port_mappings(
            ecs.PortMapping(container_port=8080,
                            host_port=8080,
                            protocol=ecs.Protocol.TCP))

        # Setup API Fargate Service
        api_service = ecs.FargateService(self,
                                         "FargateServiceAPI",
                                         task_definition=api_taskdef,
                                         cluster=ecs_cluster,
                                         desired_count=1,
                                         service_name="{0}-{1}-api".format(
                                             my_service_name, stage))

        api_scaling = api_service.auto_scale_task_count(max_capacity=5)
        api_scaling.scale_on_cpu_utilization('ApiCpuScaling',
                                             target_utilization_percent=50)

        # Setup Web Fargate Service
        web_service = ecs.FargateService(self,
                                         "FargateServiceWeb",
                                         task_definition=web_taskdef,
                                         cluster=ecs_cluster,
                                         desired_count=1,
                                         service_name="{0}-{1}-web".format(
                                             my_service_name, stage))

        web_scaling = web_service.auto_scale_task_count(max_capacity=5)
        web_scaling.scale_on_cpu_utilization('WebCpuScaling',
                                             target_utilization_percent=50)

        # # Setup TCA Fargate Service
        tca_service = ecs.FargateService(self,
                                         "FargateServiceTCA",
                                         task_definition=tca_taskdef,
                                         cluster=ecs_cluster,
                                         desired_count=1,
                                         service_name="{0}-{1}-tca".format(
                                             my_service_name, stage))

        tca_scaling = tca_service.auto_scale_task_count(max_capacity=5)
        tca_scaling.scale_on_cpu_utilization('TcaCpuScaling',
                                             target_utilization_percent=50)

        # Setup ALB Listener
        alb_listener = alb.add_listener(
            'Listener',
            certificate_arns=[
                "arn:aws:acm:us-east-1:829809672214:certificate/a84bb369-03ce-4e5e-9d32-8c84609cad1e"
            ],
            port=443,
            open=False,
            protocol=elbv2.ApplicationProtocol.HTTPS)

        # Attach ALB to ECS API Service
        api_target = alb_listener.add_targets(
            'ECSAPI',
            port=8080,
            priority=1,
            targets=[api_service],
            health_check=elbv2.HealthCheck(path=api_health_path),
            path_pattern='/oculus-api/*')

        # # Attach ALB to ECS TCA Service
        tca_target = alb_listener.add_targets(
            'ECSTCA',
            port=8080,
            priority=2,
            targets=[tca_service],
            health_check=elbv2.HealthCheck(path=tca_health_path),
            path_pattern='/tca/*')

        # Attach ALB to ECS Web Service
        web_target = alb_listener.add_targets(
            'ECSWeb',
            port=3030,
            protocol=elbv2.ApplicationProtocol.HTTP,
            targets=[web_service],
            health_check=elbv2.HealthCheck(path='/'),
        )

        core.CfnOutput(self,
                       'LoadBalancerDNS',
                       value=alb.load_balancer_dns_name)

        zone = route53.HostedZone.from_lookup(self,
                                              'MyHostedZone',
                                              domain_name=props['zoneDomain'])

        route53.ARecord(
            self,
            'ServiceAliasRecord',
            record_name=props['siteDomain'],
            target=route53.RecordTarget(
                alias_target=aws_route53_targets.LoadBalancerTarget(
                    load_balancer=alb)),
            zone=zone)
Пример #9
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Global variables to import cdk contexts from cdk.json
        _vpcID = self.node.try_get_context("VpcId")
        _sm_password = self.node.try_get_context("Secret_domain_password_arn")
        _dname = self.node.try_get_context("Domain_name")
        _subnet1 = self.node.try_get_context("Subnet1")
        _subnet2 = self.node.try_get_context("Subnet2")
        _sm_ec2keypair = self.node.try_get_context("Secret_keypair_arn")
        _ec2instance = self.node.try_get_context("Instance_type")

        # Import Vpc from the existing one in the AWS Account
        Vpc = _ec2.Vpc.from_lookup(self, "ImportVPC", vpc_id=_vpcID)
        Subnet1 = _ec2.Subnet.from_subnet_attributes(
            self,
            "subnetfromADManagedAD",
            subnet_id=_subnet1[0],
            availability_zone=_subnet1[1])

        # Import a Secret Manager Secret for Domain Password
        secret_adpassword = _sm.Secret.from_secret_arn(self,
                                                       "AdPasswordSecretStore",
                                                       secret_arn=_sm_password)

        #Import a Secret Manager Secre for EC2 KeyPair
        secret_ec2keypair = _sm.Secret.from_secret_arn(
            self, "ImportEC2KeyPairSecretStore", secret_arn=_sm_ec2keypair)

        # Create an AWS Managed AD Service in STANDARD Version
        ad = _ds.CfnMicrosoftAD(
            self,
            "ManagedAD",
            name=_dname,
            password=secret_adpassword.secret_value_from_json(
                "Key").to_string(),
            edition="Standard",
            vpc_settings={
                "vpcId": _vpcID,
                "subnetIds": [_subnet1[0], _subnet2[0]]
            })

        self.directory = ad

        # Create r53 hosted Zone for DNS DomainName
        hostedzone = _r53.HostedZone(self,
                                     "HostedZoneforAD",
                                     zone_name=_dname,
                                     vpcs=[Vpc])

        # Get the DNS IPs from AWS Managed AD
        targetip = _r53.RecordTarget(values=ad.attr_dns_ip_addresses)

        # Create A Record on Route 53 to point to AWS Managed AD IPs to later EC2 to join Domain
        r53Arecord = _r53.ARecord(self,
                                  "RecordAforAD",
                                  target=targetip,
                                  zone=hostedzone)

        # Create Policy to EC2JoinDomain Role
        ec2ssmpolicy = _iam.PolicyDocument(statements=[
            _iam.PolicyStatement(actions=[
                "ssm:DescribeAssociation", "ssm:GetDocument",
                "ssm:DescribeDocument", "ssm:GetManifest", "ssm:GetParameters",
                "ssm:ListAssociations", "ssm:ListInstanceAssociations",
                "ssm:UpdateAssociationStatus",
                "ssm:UpdateInstanceAssociationStatus",
                "ssm:UpdateInstanceInformation"
            ],
                                 resources=["*"]),
            _iam.PolicyStatement(actions=[
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel"
            ],
                                 resources=["*"]),
            _iam.PolicyStatement(actions=[
                "ec2messages:AcknowledgeMessage", "ec2messages:DeleteMessage",
                "ec2messages:FailMessage", "ec2messages:GetEndpoint",
                "ec2messages:GetMessages", "ec2messages:SendReply"
            ],
                                 resources=["*"]),
            _iam.PolicyStatement(actions=["ec2:DescribeInstanceStatus"],
                                 resources=["*"]),
            _iam.PolicyStatement(actions=["secretsmanager:GetSecretValue"],
                                 resources=["{}".format(_sm_password)])
        ])

        # Create role "EC2JoinDomain" to apply on Windows EC2JoinDomain (EC2)
        ssmrole = _iam.Role(
            self,
            "SSMRoleforEC2",
            assumed_by=_iam.ServicePrincipal('ec2.amazonaws.com'),
            inline_policies={"EC2SSMPolicy": ec2ssmpolicy},
            role_name="EC2JoinDomain")

        # Create Policy to workspaces_DefaultRole Role
        wsdefaultpolicy = _iam.PolicyDocument(statements=[
            _iam.PolicyStatement(actions=[
                "ec2:CreateNetworkInterface", "ec2:DeleteNetworkInterface",
                "ec2:DescribeNetworkInterfaces"
            ],
                                 resources=["*"]),
            _iam.PolicyStatement(actions=[
                "workspaces:RebootWorkspaces", "workspaces:RebuildWorkspaces",
                "workspaces:ModifyWorkspaceProperties"
            ],
                                 resources=["*"])
        ])

        # Create role workspaces_DefaultRole for later WorkSpaces API usage
        wsrole = _iam.Role(
            self,
            "WorkSpacesDefaultRole",
            assumed_by=_iam.ServicePrincipal('workspaces.amazonaws.com'),
            inline_policies={"WorkSpacesDefaultPolicy": wsdefaultpolicy},
            role_name="workspaces_DefaultRole")

        # Create a security group for RDP access on Windows EC2JoinDomain (EC2)
        rdpsg = _ec2.SecurityGroup(
            self,
            "SGForRDP",
            vpc=Vpc,
            description=
            "The Secrurity Group from local environment to Windows EC2 Instance"
        )

        rdpsg.add_ingress_rule(peer=_ec2.Peer.ipv4("192.168.1.1/32"),
                               connection=_ec2.Port.tcp(3389))

        # Create Windows EC2JoinDomain (EC2) as AD Admin server
        adadminEC2 = _ec2.Instance(
            self,
            "WindowsEC2",
            instance_type=_ec2.InstanceType(
                instance_type_identifier=_ec2instance),
            machine_image=_ec2.MachineImage.latest_windows(
                version=_ec2.WindowsVersion.
                WINDOWS_SERVER_2016_ENGLISH_FULL_BASE),
            vpc=Vpc,
            key_name=secret_ec2keypair.secret_value_from_json(
                "Key").to_string(),
            role=ssmrole,
            security_group=rdpsg,
            vpc_subnets=_ec2.SubnetSelection(subnets=[Subnet1]))

        adadminEC2.instance.add_depends_on(ad)

        # Create a SSM Parameter Store for Domain Name
        domain = _ssm.StringParameter(self,
                                      "ADDomainName",
                                      parameter_name="ad_join_domain_name",
                                      string_value=ad.name)

        # Create a SSM Parameter Store for Domain User
        aduser = _ssm.StringParameter(self,
                                      "ADDomainUser",
                                      parameter_name="ad_join_domain_user",
                                      string_value="Admin")

        domain.node.add_dependency(ad)
        aduser.node.add_dependency(ad)

        # Create SSM Document to join Window EC2 into AD
        ssmdocument = _ssm.CfnDocument(
            self,
            "SSMDocumentJoinAD",
            document_type="Command",
            name="SSMDocumentJoinAD",
            content={
                "description":
                "Run a PowerShell script to domain join a Windows instance securely",
                "schemaVersion":
                "2.0",
                "mainSteps": [{
                    "action": "aws:runPowerShellScript",
                    "name": "runPowerShellWithSecureString",
                    "inputs": {
                        "runCommand": [
                            "# Example PowerShell script to domain join a Windows instance securely",
                            "# Adopt the document from AWS Blog Join a Microsoft Active Directory Domain with Parameter Store and Amazon EC2 Systems Manager Documents",
                            "", "$ErrorActionPreference = 'Stop'", "", "try{",
                            "    # Parameter names",
                            "    # $dnsParameterStore = ([System.Net.Dns]::GetHostAddresses({}).IPAddressToString[0])"
                            .format(domain.parameter_name),
                            "    $domainNameParameterStore = \"{}\"".format(
                                domain.parameter_name),
                            "    $domainJoinUserNameParameterStore = \"{}\"".
                            format(aduser.parameter_name),
                            "    $domainJoinPasswordParameterStore = \"{}\"".
                            format(secret_adpassword.secret_arn), "",
                            "    # Retrieve configuration values from parameters",
                            "    $ipdns = ([System.Net.Dns]::GetHostAddresses(\"{}\").IPAddressToString[0])"
                            .format(_dname),
                            "    $domain = (Get-SSMParameterValue -Name $domainNameParameterStore).Parameters[0].Value",
                            "    $username = $domain + \"\\\" + (Get-SSMParameterValue -Name $domainJoinUserNameParameterStore).Parameters[0].Value",
                            "    $password = ((Get-SECSecretValue -SecretId $domainJoinPasswordParameterStore ).SecretString | ConvertFrom-Json ).Key | ConvertTo-SecureString -asPlainText -Force ",
                            "",
                            "    # Create a System.Management.Automation.PSCredential object",
                            "    $credential = New-Object System.Management.Automation.PSCredential($username, $password)",
                            "",
                            "    # Determine the name of the Network Adapter of this machine",
                            "    $networkAdapter = Get-WmiObject Win32_NetworkAdapter -Filter \"AdapterType = 'Ethernet 802.3'\"",
                            "    $networkAdapterName = ($networkAdapter | Select-Object -First 1).NetConnectionID",
                            "",
                            "    # Set up the IPv4 address of the AD DNS server as the first DNS server on this machine",
                            "    netsh.exe interface ipv4 add dnsservers name=$networkAdapterName address=$ipdns index=1",
                            "", "    # Join the domain and reboot",
                            "    Add-Computer -DomainName $domain -Credential $credential",
                            "    Restart-Computer -Force", "}",
                            "catch [Exception]{",
                            "    Write-Host $_.Exception.ToString()",
                            "    Write-Host 'Command execution failed.'",
                            "    $host.SetShouldExit(1)", "}"
                        ]
                    }
                }]
            })

        # Create SSM Associate to trigger SSM doucment to let Windows EC2JoinDomain (EC2) join Domain
        ssmjoinad = _ssm.CfnAssociation(self,
                                        "WindowJoinAD",
                                        name=ssmdocument.name,
                                        targets=[{
                                            "key":
                                            "InstanceIds",
                                            "values": [adadminEC2.instance_id]
                                        }])

        ssmjoinad.add_depends_on(ssmdocument)

        # Create a Policy for Lambda Role
        lambdapolicy = _iam.PolicyDocument(statements=[
            _iam.PolicyStatement(actions=["logs:CreateLogGroup"],
                                 resources=[
                                     "arn:aws:logs:{}:{}:*".format(
                                         self.region, self.account)
                                 ]),
            _iam.PolicyStatement(
                actions=["logs:CreateLogStream", "logs:PutLogEvents"],
                resources=[
                    "arn:aws:logs:{}:{}:log-group:/aws/lambda/*".format(
                        self.region, self.account)
                ]),
            _iam.PolicyStatement(actions=[
                "workspaces:RegisterWorkspaceDirectory",
                "workspaces:DeregisterWorkspaceDirectory",
                "ds:DescribeDirectories", "ds:AuthorizeApplication",
                "ds:UnauthorizeApplication", "iam:GetRole",
                "ec2:DescribeInternetGateways", "ec2:DescribeVpcs",
                "ec2:DescribeRouteTables", "ec2:DescribeSubnets",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribeAvailabilityZones", "ec2:CreateSecurityGroup",
                "ec2:CreateTags"
            ],
                                 resources=["*"])
        ])

        # Creare a IAM Role for Lambda
        lambdarole = _iam.Role(
            self,
            "LambdaRoleForRegisterDS",
            assumed_by=_iam.ServicePrincipal('lambda.amazonaws.com'),
            inline_policies={"LambdaActicateDS": lambdapolicy},
            role_name="LambdaActivateDirectoryService")

        # Create a Lambda function to Register Directory Service on WorkSpaces
        dslambda = _lambda.Function(self,
                                    "LambdaStackForDSFunction",
                                    runtime=_lambda.Runtime.PYTHON_3_7,
                                    handler="workspaceds.handler",
                                    role=lambdarole,
                                    code=_lambda.Code.asset('lambda'),
                                    environment={"DIRECTORY_ID": ad.ref},
                                    timeout=core.Duration.seconds(120))
        # Create a customResource to trigger Lambda function after Lambda function is created
        _cf.CfnCustomResource(self,
                              "InvokeLambdaFunction",
                              service_token=dslambda.function_arn)
Пример #10
0
    def __init__(self, scope: core.Construct, id: str, region, domain,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # VPC , we need one for ECS cluster ( sadly )
        vpc = ec2.Vpc.from_lookup(self, 'vpc', is_default=True)

        cluster = ecs.Cluster(self, 'Cluster', vpc=vpc)

        # Route53 & SSL Certificate
        zone = dns.HostedZone(self, "dns", zone_name=domain)

        dns.ARecord(self,
                    'MinecraftRecord',
                    zone=zone,
                    record_name='minecraft',
                    target=dns.RecordTarget(values=['1.2.3.4']))

        cert = acm.Certificate(
            self,
            'cert',
            domain_name=f'*.{domain}',
            validation=acm.CertificateValidation.from_dns(zone))

        # ECS ( Cluster, EFS, Task Def)
        fs = efs.FileSystem(self,
                            'EFS',
                            vpc=vpc,
                            removal_policy=core.RemovalPolicy.DESTROY)

        task_definition = ecs.FargateTaskDefinition(self,
                                                    'TaskDef',
                                                    memory_limit_mib=4096,
                                                    cpu=1024)

        container = task_definition.add_container(
            'MinecraftDocker',
            image=ecs.ContainerImage.from_registry('darevee/minecraft-aws'),
            logging=ecs.AwsLogDriver(stream_prefix='Minecraf'),
            cpu=1024,
            memory_limit_mib=4096)
        container.add_mount_points(
            ecs.MountPoint(container_path='/minecraft',
                           source_volume='efs',
                           read_only=False))
        cfn_task = container.task_definition.node.default_child
        cfn_task.add_property_override("Volumes", [{
            "EFSVolumeConfiguration": {
                "FilesystemId": fs.file_system_id
            },
            "Name": "efs"
        }])

        container.add_port_mappings(ecs.PortMapping(container_port=25565))

        sg = ec2.SecurityGroup(self, 'sg', vpc=vpc)
        sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(),
                            connection=ec2.Port.tcp(25565),
                            description='Minecraft Access')
        sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(),
                            connection=ec2.Port.tcp(25575),
                            description='RCONN Access')

        fs.connections.allow_default_port_from(sg)

        subnets = ",".join(vpc.select_subnets().subnet_ids)

        # Cognito ( For ApiGW Authentication)
        userpool = cognito.UserPool(
            self,
            'UserPool',
            user_invitation=cognito.UserInvitationConfig(
                email_body=
                """No cześć {username}, zostałeś zaproszony do naszego Minecraft!
                Twoje tymczasowe hasło to {####}
                """,
                email_subject="Zaproszenie do minecrafta"))

        # APIGW (Gateway, Lambdas, S3 Static content)

        # Lambda Starter
        starter = _lambda.Function(self,
                                   'Starter',
                                   runtime=_lambda.Runtime.PYTHON_3_8,
                                   handler='index.lambda_handler',
                                   code=_lambda.Code.asset('lambda/starter'),
                                   timeout=core.Duration.seconds(300),
                                   environment={
                                       'cluster': cluster.cluster_name,
                                       'subnets': subnets,
                                       'security_groups': sg.security_group_id,
                                       'task_definition':
                                       task_definition.task_definition_arn,
                                       'region': region,
                                       'zone_id': zone.hosted_zone_id,
                                       'domain': domain
                                   })

        starter.add_to_role_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                resources=["*"],
                                actions=[
                                    "ecs:ListTasks", "ecs:DescribeTasks",
                                    "ec2:DescribeNetworkInterfaces"
                                ]))
        starter.add_to_role_policy(
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                resources=[task_definition.task_definition_arn],
                actions=["ecs:RunTask", "ecs:DescribeTasks"]))
        starter.add_to_role_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                resources=[
                                    task_definition.task_role.role_arn,
                                    task_definition.execution_role.role_arn
                                ],
                                actions=["iam:PassRole"]))

        starter.add_to_role_policy(
            iam.PolicyStatement(effect=iam.Effect.ALLOW,
                                resources=[zone.hosted_zone_arn],
                                actions=["route53:ChangeResourceRecordSets"]))

        # S3 static webpage
        bucket = s3.Bucket(self,
                           "S3WWW",
                           public_read_access=True,
                           removal_policy=core.RemovalPolicy.DESTROY,
                           website_index_document="index.html")
        s3d.BucketDeployment(self,
                             "S3Deploy",
                             destination_bucket=bucket,
                             sources=[s3d.Source.asset("static_page")])

        status = _lambda.Function(self,
                                  'Status',
                                  runtime=_lambda.Runtime.PYTHON_3_8,
                                  handler='index.lambda_handler',
                                  code=_lambda.Code.asset('lambda/status'),
                                  environment={
                                      'url': f"https://minecrafter.{domain}",
                                      'domain': domain
                                  })

        # ApiGW
        apigw = api.LambdaRestApi(self,
                                  'ApiGW',
                                  handler=status,
                                  proxy=False,
                                  domain_name={
                                      "domain_name": f'minecrafter.{domain}',
                                      "certificate": cert
                                  },
                                  default_cors_preflight_options={
                                      "allow_origins": api.Cors.ALL_ORIGINS,
                                      "allow_methods": api.Cors.ALL_METHODS
                                  })

        start = apigw.root.add_resource('start')
        start.add_method('ANY', integration=api.LambdaIntegration(starter))

        apigw.root.add_method('ANY')

        dns.ARecord(self,
                    'PointDNSToApiGW',
                    zone=zone,
                    target=dns.RecordTarget.from_alias(
                        targets.ApiGateway(apigw)),
                    record_name=f"minecrafter.{domain}")
Пример #11
0
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        """
        Creates a VPC with 2 public and 2 private subnets,
        each subnet with a /18 CIDR range,
        a 2 NAT gateways
        """
        vpc = ec2.Vpc(
            self, "MindLAMPVPC",
            cidr="10.10.0.0/16"
        )

        # Security group for instances
        security_group = ec2.SecurityGroup(
            self, "MindLAMPSecurityGroup",
            vpc=vpc,
            description="Security group for LAMP Platform instances"
        )

        # Allow TCP to port 80 from 0.0.0.0/0
        security_group.add_ingress_rule(
            peer=ec2.Peer.any_ipv4(),
            connection=ec2.Port.tcp(80),
            description="Allow HTTP connections to port 80"
        )
        # Allow TCP to port 443 from 0.0.0.0/0
        security_group.add_ingress_rule(
            peer=ec2.Peer.any_ipv4(),
            connection=ec2.Port.tcp(443),
            description="Allow HTTP connections to port 443"
        )

        # Allow TCP to port 443 from 0.0.0.0/0
        security_group.add_ingress_rule(
            peer=ec2.Peer.any_ipv6(),
            connection=ec2.Port.tcp(443),
            description="Allow HTTP connections to port 443 with ipv6"
        )

        # Install docker on boot
        user_data = ec2.UserData.for_linux()
        user_data.add_commands(
            "yum -y install docker && usermod -a -G docker ec2-user")

        # The EC2 instance
        instance1 = ec2.Instance(
            self, "MindLAMPInstance1",
            instance_type=ec2.InstanceType("t3a.large"),
            machine_image=ec2.MachineImage.latest_amazon_linux(),
            user_data=user_data,
            instance_name="LAMP platform",
            block_devices=[
                ec2.BlockDevice(
                    device_name="/dev/sdf",
                    volume=ec2.BlockDeviceVolume.ebs(
                        volume_size=30,
                        encrypted=True,
                        delete_on_termination=True
                    )
                ),
                ec2.BlockDevice(
                    device_name="/dev/sdg",
                    volume=ec2.BlockDeviceVolume.ebs(
                        volume_size=100,
                        encrypted=True,
                        delete_on_termination=False
                    )
                )
            ],
            security_group=security_group,
            vpc=vpc,
            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC)
        )

        # Associate the SSM managed policy for SSM control + access
        instance1.role.add_managed_policy(
            policy=iam.ManagedPolicy.from_aws_managed_policy_name(
                managed_policy_name="AmazonSSMManagedInstanceCore")
        )

        # Get an existing Route53 hosted zone
        hosted_zone = route53.HostedZone.from_hosted_zone_attributes(
            self, "MindLAMPHostedZone",
            hosted_zone_id=self.node.try_get_context("hosted_zone_id"),
            zone_name=self.node.try_get_context("zone_name")
        )

        # Create an A record to point to the public IP of instance1
        record_set1 = route53.RecordSet(
            self, "Node1RecordSet",
            record_type=route53.RecordType.A,
            target=route53.RecordTarget(values=[instance1.instance_public_ip]),
            zone=hosted_zone,
            record_name="node1"
        )