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