def __init__(self, scope: core.Stack, id: str, ecs_cluster, vpc, services_3000_sec_group, desired_service_count, **kwargs): super().__init__(scope, id, **kwargs) self.ecs_cluster = ecs_cluster self.vpc = vpc self.services_3000_sec_group = services_3000_sec_group self.desired_service_count = desired_service_count # This will create an ALB with listener/target group, ecs task def, ecs fargate service, logging in cloudwatch # and security group from ALB to containers. This essentially condenses 95 lines of code into 15. self.fargate_load_balanced_service = aws_ecs_patterns.LoadBalancedFargateService( self, "FrontendFargateLBService", cluster=self.ecs_cluster, image=aws_ecs.ContainerImage.from_registry( "brentley/ecsdemo-frontend"), container_port=3000, cpu=256, memory_limit_mi_b=512, enable_logging=True, desired_count=self.desired_service_count, load_balancer_type=aws_ecs_patterns.LoadBalancerType( 'APPLICATION'), public_load_balancer=True, environment={ "CRYSTAL_URL": "http://ecsdemo-crystal.service:3000/crystal", "NODEJS_URL": "http://ecsdemo-nodejs.service:3000" }, ) # There has to be a better way, but for now this is what we got. # Allow inbound 3000 from Frontend Service to Backend self.sec_grp_ingress_backend_to_frontend_3000 = aws_ec2.CfnSecurityGroupIngress( self, "InboundBackendSecGrp3000", ip_protocol='TCP', source_security_group_id=self.fargate_load_balanced_service. service.connections.security_groups[0].security_group_id, from_port=3000, to_port=3000, group_id=self.services_3000_sec_group.security_group_id) # There has to be a better way, but for now this is what we got. # Allow inbound 3000 Backend to Frontend Service self.sec_grp_ingress_frontend_to_backend_3000 = aws_ec2.CfnSecurityGroupIngress( self, "InboundFrontendtoBackendSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_3000_sec_group. security_group_id, from_port=3000, to_port=3000, group_id=self.fargate_load_balanced_service.service.connections. security_groups[0].security_group_id, )
def __init__(self, scope: core.Stack, id=str, **kwargs): super().__init__(scope, id, **kwargs) self.vpc = ec2.Vpc( self, "BaseVPC", cidr='10.0.0.0/24', enable_dns_support=True, enable_dns_hostnames=True, ) self.services_3000_sec_group = ec2.SecurityGroup( self, "FrontendToBackendSecurityGroup", allow_all_outbound=True, description= "Security group for frontend service to talk to backend services", vpc=self.vpc) self.sec_grp_ingress_self_3000 = ec2.CfnSecurityGroupIngress( self, "InboundSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_3000_sec_group. security_group_id, from_port=3000, to_port=3000, group_id=self.services_3000_sec_group.security_group_id)
def __init__(self, scope: core.Construct, id: str, vpc, asg_security_groups, **kwargs) -> None: super().__init__(scope, id, **kwargs) # Creat DB Low Level API - MySQL M-AZs db_security_group = ec2.CfnSecurityGroup( self, "dbSG", group_description="All EC2 access DB", group_name="DB_SG", vpc_id=vpc.vpc_id) for asg_sg in asg_security_groups: ec2.CfnSecurityGroupIngress( self, "SG_ingress", ip_protocol="tcp", description="ASG EC2 access DB", to_port=3306, from_port=3306, group_id=db_security_group.attr_group_id, source_security_group_id=asg_sg.security_group_id) subnet_ids = [] for i in vpc.isolated_subnets: subnet_ids.append(i.subnet_id) db_subnet_group = rds.CfnDBSubnetGroup( self, "db_subnet", db_subnet_group_description="DB_subnet", db_subnet_group_name="db_subnet", subnet_ids=subnet_ids) db_mysql = rds.CfnDBInstance( self, "MyDB", db_name="mysqldb", db_instance_class="db.t2.small", allocated_storage="100", storage_type="gp2", engine="MySQL", engine_version="5.7.22", master_username=db_master_username, master_user_password=db_master_user_password, multi_az=True, vpc_security_groups=[db_security_group.attr_group_id], db_subnet_group_name=db_subnet_group.db_subnet_group_name, backup_retention_period=7, allow_major_version_upgrade=False, enable_cloudwatch_logs_exports=[ "audit", "error", "general", "slowquery" ], delete_automated_backups=False) db_mysql.add_depends_on(db_subnet_group) db_mysql.add_depends_on(db_security_group)
def __init__(self, scope: core.Stack, id=str, **kwargs): super().__init__(scope, id, **kwargs) # This resource alone will create a private/public subnet in each AZ as well as nat/internet gateway(s) self.vpc = aws_ec2.Vpc( self, "BaseVPC", cidr='10.0.0.0/24', enable_dns_support=True, enable_dns_hostnames=True, ) # Creating ECS Cluster in the VPC created above self.ecs_cluster = aws_ecs.Cluster(self, "ECSCluster", vpc=self.vpc) # Adding service discovery namespace to cluster self.ecs_cluster.add_default_cloud_map_namespace(name="service", ) # Frontend security group frontend service to backend services self.services_3000_sec_group = aws_ec2.SecurityGroup( self, "FrontendToBackendSecurityGroup", allow_all_outbound=True, description= "Security group for frontend service to talk to backend services", vpc=self.vpc) # Allow inbound 3000 from ALB to Frontend Service self.sec_grp_ingress_self_3000 = aws_ec2.CfnSecurityGroupIngress( self, "InboundSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_3000_sec_group. security_group_id, from_port=3000, to_port=3000, group_id=self.services_3000_sec_group.security_group_id)
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) # The code that defines your stack goes here # instance role # instance profile # SecurityGroup publicsecuritygroup01 = aws_ec2.CfnSecurityGroup( self, 'publicsecuritygroup01', group_description='publicsecuritygroup', group_name='publicsecuritygroup01', vpc_id=core.Fn.import_value('vpcid01'), tags=[core.CfnTag(key='Name', value='publicsecuritygroup01')]) privatesecuritygroup01 = aws_ec2.CfnSecurityGroup( self, 'privatesecuritygroup01', group_description='privatesecuritygroup', group_name='privatesecuritygroup01', vpc_id=core.Fn.import_value('vpcid01'), tags=[core.CfnTag(key='Name', value='privatesecuritygroup01')]) # public Ingress aws_ec2.CfnSecurityGroupIngress(self, 'publicsecuritygroupingress01', group_id=publicsecuritygroup01.ref, ip_protocol='tcp', cidr_ip='0.0.0.0/0', description='for bastion', from_port=22, to_port=22) # public Egress aws_ec2.CfnSecurityGroupEgress( self, 'publicsecuritygroupegress01', group_id=publicsecuritygroup01.ref, ip_protocol='tcp', destination_security_group_id=privatesecuritygroup01.ref, description='for private', from_port=22, to_port=22) # private Ingress aws_ec2.CfnSecurityGroupIngress( self, 'privatesecuritygroupingress01', group_id=privatesecuritygroup01.ref, ip_protocol='tcp', source_security_group_id=publicsecuritygroup01.ref, description='for bastion', from_port=22, to_port=22) # private Egress aws_ec2.CfnSecurityGroupEgress(self, 'privatesecuritygroupegress01', group_id=privatesecuritygroup01.ref, ip_protocol='tcp', cidr_ip='0.0.0.0/0', description='for 443', from_port=443, to_port=443) aws_ec2.CfnSecurityGroupEgress(self, 'privatesecuritygroupegress02', group_id=privatesecuritygroup01.ref, ip_protocol='tcp', cidr_ip='0.0.0.0/0', description='for 80', from_port=80, to_port=80) # aws_ec2.CfnSecurityGroupEgress(self, 'privatesecuritygroupegress03', group_id=privatesecuritygroup01.ref, ip_protocol='tcp', cidr_ip='0.0.0.0/0', description='for 22', from_port=22, to_port=22) core.CfnOutput(self, 'output01', value=publicsecuritygroup01.ref, description='publicsecuritygroup', export_name='publicsecuritygroup01') core.CfnOutput(self, 'output02', value=privatesecuritygroup01.ref, description='privatesecuritygroup', export_name='privatesecuritygroup01')
def __init__(self, scope: core.Stack, id: str, cluster: ecs.ICluster, vpc, sec_group, desired_service_count, **kwargs): super().__init__(scope, id, **kwargs) self.cluster = cluster self.vpc = vpc self.sec_group = sec_group self.desired_service_count = desired_service_count self.fargate_load_balanced_service = ecs_patterns.ApplicationLoadBalancedFargateService( self, "FrontendFargateLBService", cluster=self.cluster, desired_count=self.desired_service_count, service_name="Fargate-Frontend", cpu=256, memory_limit_mib=512, public_load_balancer=True, task_image_options={ "image": ecs.ContainerImage.from_registry("brentley/ecsdemo-frontend"), "container_port": 3000, "enable_logging": True, "environment": { "CRYSTAL_URL": "http://ecsdemo-crystal.service:3000/crystal", "NODEJS_URL": "http://ecsdemo-nodejs.service:3000" } }, ) self.fargate_load_balanced_service.service.connections.security_groups[ 0].add_ingress_rule(peer=ec2.Peer.ipv4(self.vpc.vpc_cidr_block), connection=ec2.Port.tcp(3000), description="Allow http inbound from VPC") self.sec_grp_ingress_backend_to_frontend_3000 = ec2.CfnSecurityGroupIngress( self, "InboundBackendSecGrp3000", ip_protocol='TCP', source_security_group_id=self.fargate_load_balanced_service. service.connections.security_groups[0].security_group_id, from_port=3000, to_port=3000, group_id=self.sec_group.security_group_id) self.sec_grp_ingress_frontend_to_backend_3000 = ec2.CfnSecurityGroupIngress( self, "InboundFrontendtoBackendSecGrp3000", ip_protocol='TCP', source_security_group_id=self.sec_group.security_group_id, from_port=3000, to_port=3000, group_id=self.fargate_load_balanced_service.service.connections. security_groups[0].security_group_id, ) scaling = self.fargate_load_balanced_service.service.auto_scale_task_count( min_capacity=3, max_capacity=6) scaling.scale_on_cpu_utilization( "CpuScaling", target_utilization_percent=30, scale_in_cooldown=core.Duration.seconds(60), scale_out_cooldown=core.Duration.seconds(60), ) core.CfnOutput(self, "LoadBalancerDNS", value=self.fargate_load_balanced_service.load_balancer. load_balancer_dns_name)
def __init__(self, scope: core.Construct, id: str, vpc: aws_ec2.Vpc, **kwargs) -> None: super().__init__(scope, id, **kwargs) # ECS Cluster # https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_ecs.README.html#clusters self.ecs_cluster = aws_ecs.Cluster( self, "ECSCluster", vpc=vpc, cluster_name="Fargate-microservices") # ECS Enable Cloud map self.ecs_cluster.add_default_cloud_map_namespace(name="service", ) # ECS adding capacity self.asg = self.ecs_cluster.add_capacity( "ECSEC2Capacity", instance_type=aws_ec2.InstanceType( instance_type_identifier='t3.small'), min_capacity=0, max_capacity=10) core.CfnOutput(self, "EC2AutoScalingGroupName", value=self.asg.auto_scaling_group_name, export_name="EC2ASGName") # Namespace details as CFN output self.namespace_outputs = { 'ARN': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_arn, 'NAME': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_name, 'ID': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_id, } # Cluster Attributes self.cluster_outputs = { 'NAME': self.ecs_cluster.cluster_name, 'SECGRPS': str(self.ecs_cluster.connections.security_groups) } # When enabling EC2, we need the security groups "registered" to the cluster for imports in other service stacks if self.ecs_cluster.connections.security_groups: self.cluster_outputs['SECGRPS'] = str([ x.security_group_id for x in self.ecs_cluster.connections.security_groups ][0]) # Allow inbound 80 from ALB to Frontend Service self.services_80_sec_group = aws_ec2.SecurityGroup( self, "FrontendToBackendSecurityGroup", allow_all_outbound=True, description= "Security group to allow inbound 80 from ALB to Frontend Service", vpc=vpc) self.sec_grp_ingress_self_80 = aws_ec2.CfnSecurityGroupIngress( self, "InboundSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_80_sec_group. security_group_id, from_port=80, to_port=80, group_id=self.services_80_sec_group.security_group_id) # All Outputs required for other stacks to build core.CfnOutput(self, "NSArn", value=self.namespace_outputs['ARN'], export_name="NSARN") core.CfnOutput(self, "NSName", value=self.namespace_outputs['NAME'], export_name="NSNAME") core.CfnOutput(self, "NSId", value=self.namespace_outputs['ID'], export_name="NSID") core.CfnOutput(self, "FE2BESecGrp", value=self.services_80_sec_group.security_group_id, export_name="SecGrpId") core.CfnOutput(self, "ECSClusterName", value=self.cluster_outputs['NAME'], export_name="ECSClusterName") core.CfnOutput(self, "ECSClusterSecGrp", value=self.cluster_outputs['SECGRPS'], export_name="ECSSecGrpList") core.CfnOutput(self, "ServicesSecGrp", value=self.services_80_sec_group.security_group_id, export_name="ServicesSecGrp")
def __init__(self, scope: core.Construct, id: str, data, iam_vars) -> None: super().__init__(scope, id) # VPC vpc = ec2.CfnVPC(self, "cdk-vpc", cidr_block=data["vpc"]) igw = ec2.CfnInternetGateway(self, id="igw") ec2.CfnVPCGatewayAttachment(self, id="igw-attach", vpc_id=vpc.ref, internet_gateway_id=igw.ref) public_route_table = ec2.CfnRouteTable(self, id="public_route_table", vpc_id=vpc.ref) ec2.CfnRoute(self, id="public_route", route_table_id=public_route_table.ref, destination_cidr_block="0.0.0.0/0", gateway_id=igw.ref) public_subnets = [] for i, s in enumerate(data["subnets"]["public"]): subnet = ec2.CfnSubnet(self, id="public_{}".format(s), cidr_block=s, vpc_id=vpc.ref, availability_zone=core.Fn.select( i, core.Fn.get_azs()), map_public_ip_on_launch=True) public_subnets.append(subnet) ec2.CfnSubnetRouteTableAssociation( self, id="public_{}_association".format(s), route_table_id=public_route_table.ref, subnet_id=subnet.ref) eip = ec2.CfnEIP(self, id="natip") nat = ec2.CfnNatGateway(self, id="nat", allocation_id=eip.attr_allocation_id, subnet_id=public_subnets[0].ref) private_route_table = ec2.CfnRouteTable(self, id="private_route_table", vpc_id=vpc.ref) ec2.CfnRoute(self, id="private_route", route_table_id=private_route_table.ref, destination_cidr_block="0.0.0.0/0", nat_gateway_id=nat.ref) private_subnets = [] for i, s in enumerate(data["subnets"]["private"]): subnet = ec2.CfnSubnet(self, id="private_{}".format(s), cidr_block=s, vpc_id=vpc.ref, availability_zone=core.Fn.select( i, core.Fn.get_azs()), map_public_ip_on_launch=False) private_subnets.append(subnet) ec2.CfnSubnetRouteTableAssociation( self, id="private_{}_association".format(s), route_table_id=private_route_table.ref, subnet_id=subnet.ref) # Security groups lb_sg = ec2.CfnSecurityGroup(self, id="lb", group_description="LB SG", vpc_id=vpc.ref) lambda_sg = ec2.CfnSecurityGroup(self, id="lambda", group_description="Lambda SG", vpc_id=vpc.ref) public_prefix = ec2.CfnPrefixList(self, id="cidr_prefix", address_family="IPv4", max_entries=1, prefix_list_name="public", entries=[{ "cidr": "0.0.0.0/0", "description": "Public" }]) _sg_rules = [{ 'sg': lb_sg.attr_group_id, 'rules': [{ "direction": "ingress", "description": "HTTP from Internet", "from_port": 80, "to_port": 80, "protocol": "tcp", "cidr_blocks": public_prefix.ref }, { "direction": "egress", "description": "LB to Lambda", "from_port": 80, "to_port": 80, "protocol": "tcp", "source_security_group_id": lambda_sg.attr_group_id }] }, { "sg": lambda_sg.attr_group_id, "rules": [{ "direction": "ingress", "description": "HTTP from LB", "from_port": 80, "to_port": 80, "protocol": "tcp", "source_security_group_id": lb_sg.attr_group_id }, { "direction": "egress", "description": "All to Internet", "from_port": 0, "to_port": 65535, "protocol": "tcp", "cidr_blocks": public_prefix.ref }] }] for ruleset in _sg_rules: for rule in ruleset["rules"]: if rule["direction"] == "ingress": ec2.CfnSecurityGroupIngress( self, id=rule["description"].replace(" ", "_"), description=rule["description"], to_port=rule["to_port"], from_port=rule["from_port"], ip_protocol=rule["protocol"], group_id=ruleset["sg"], source_prefix_list_id=rule["cidr_blocks"] if "cidr_blocks" in rule else None, source_security_group_id=rule[ "source_security_group_id"] if "source_security_group_id" in rule else None) else: ec2.CfnSecurityGroupEgress( self, id=rule["description"].replace(" ", "_"), description=rule["description"], to_port=rule["to_port"], from_port=rule["from_port"], ip_protocol=rule["protocol"], group_id=ruleset["sg"], destination_prefix_list_id=rule["cidr_blocks"] if "cidr_blocks" in rule else None, destination_security_group_id=rule[ "source_security_group_id"] if "source_security_group_id" in rule else None) # IAM assume_policy_doc = iam.PolicyDocument() for statement in iam_vars["assume"]["Statement"]: _statement = iam.PolicyStatement(actions=[statement["Action"]], ) _statement.add_service_principal(statement["Principal"]["Service"]) assume_policy_doc.add_statements(_statement) role = iam.CfnRole(self, id="iam_role", path="/", assume_role_policy_document=assume_policy_doc) role_policy_doc = iam.PolicyDocument() for statement in iam_vars["policy"]["Statement"]: _statement = iam.PolicyStatement(actions=statement["Action"], resources=["*"]) role_policy_doc.add_statements(_statement) policy = iam.CfnPolicy(self, id="iam_policy", policy_document=role_policy_doc, policy_name="cdkPolicy", roles=[role.ref]) # Lambda shutil.make_archive("../lambda", 'zip', "../lambda/") s3_client = boto3.client('s3') s3_client.upload_file("../lambda.zip", "cloudevescops-zdays-demo", "cdk.zip") function = lmd.CfnFunction(self, id="lambda_function", handler="lambda.lambda_handler", role=role.attr_arn, runtime="python3.7", code={ "s3Bucket": "cloudevescops-zdays-demo", "s3Key": "cdk.zip" }, vpc_config={ "securityGroupIds": [lambda_sg.ref], "subnetIds": [s.ref for s in private_subnets] }, environment={"variables": { "TOOL": "CDK" }}) # LB lb = alb.CfnLoadBalancer(self, id="alb", name="lb-cdk", scheme="internet-facing", type="application", subnets=[s.ref for s in public_subnets], security_groups=[lb_sg.ref]) lmd.CfnPermission(self, id="lambda_permis", action="lambda:InvokeFunction", function_name=function.ref, principal="elasticloadbalancing.amazonaws.com") tg = alb.CfnTargetGroup(self, id="alb_tg", name="lambda-cdk", target_type="lambda", health_check_enabled=True, health_check_interval_seconds=40, health_check_path="/", health_check_timeout_seconds=30, targets=[{ "id": function.get_att("Arn").to_string() }], matcher={"httpCode": "200"}) alb.CfnListener(self, id="listener", default_actions=[{ "type": "forward", "targetGroupArn": tg.ref }], load_balancer_arn=lb.ref, port=80, protocol="HTTP") core.CfnOutput(self, id="fqdn", value=lb.attr_dns_name)
def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) vpc = ec2.Vpc(self, id="MyVPC", nat_gateways=0, cidr="192.168.0.0/20", max_azs=3, subnet_configuration=[]) pub_subnet = ec2.PublicSubnet(self, id="PublicSubnet", availability_zone="eu-central-1c", cidr_block="192.168.0.0/24", vpc_id=vpc.vpc_id, map_public_ip_on_launch=True) igw = ec2.CfnInternetGateway( self, id="MyIGW", tags=[core.CfnTag(key="Name", value="IGW")]) ec2.CfnVPCGatewayAttachment(self, id="IGW_Assoc", vpc_id=vpc.vpc_id, internet_gateway_id=igw.ref) pub_subnet.add_route(id="default_route-sub01", router_id=igw.ref, router_type=ec2.RouterType('GATEWAY'), destination_cidr_block="0.0.0.0/0", enables_internet_connectivity=True) # Elastic IP eip_01 = ec2.CfnEIP(self, id="EIP01") # NAT gateway ngw = ec2.CfnNatGateway(self, id="NAT_GW", allocation_id=eip_01.attr_allocation_id, subnet_id=pub_subnet.subnet_id, tags=[core.CfnTag(key="Name", value="NAT_GW")]) subnet01 = ec2.Subnet(self, id="Subnet01", availability_zone="eu-central-1a", cidr_block="192.168.1.0/24", vpc_id=vpc.vpc_id, map_public_ip_on_launch=False) subnet02 = ec2.Subnet(self, id="Subnet02", availability_zone="eu-central-1b", cidr_block="192.168.2.0/24", vpc_id=vpc.vpc_id, map_public_ip_on_launch=False) subnet01.add_route(id="default_route-sub01", router_id=ngw.ref, router_type=ec2.RouterType('NAT_GATEWAY'), destination_cidr_block="0.0.0.0/0", enables_internet_connectivity=True) subnet02.add_route(id="default_route-sub02", router_id=ngw.ref, router_type=ec2.RouterType('NAT_GATEWAY'), destination_cidr_block="0.0.0.0/0", enables_internet_connectivity=True) sg_lb = ec2.CfnSecurityGroup( self, id="SG_ALB", group_description="SG for the APP LB", group_name="SG_ALB", vpc_id=vpc.vpc_id, tags=[core.CfnTag(key="Name", value="SG_ALB")]) sg_ec2i = ec2.CfnSecurityGroup( self, id="SG_Instances", group_description="SG for the Instances", group_name="SG_Instances", vpc_id=vpc.vpc_id, tags=[core.CfnTag(key="Name", value="SG_Instances")]) # my_home_ip = requests.get("https://api.ipify.org").text my_home_ip = "94.112.113.195" ports_pub = {'tcp': [22, 80], 'icmp': [-1]} for protocol, ports_list in ports_pub.items(): for port in ports_list: ec2.CfnSecurityGroupIngress( self, id=f"sg_alb_in_{protocol}_{port}", group_id=sg_lb.attr_group_id, ip_protocol=protocol, cidr_ip=f"{my_home_ip}/32", to_port=port, from_port=port, description=f"{protocol.upper()} {port} from home IP") ec2.CfnSecurityGroupIngress( self, id=f"sg_ec2i_in_{protocol}_{port}", group_id=sg_ec2i.attr_group_id, ip_protocol=protocol, to_port=port, from_port=port, source_security_group_id=sg_lb.ref, description=f"{protocol.upper()} {port} from the ALB SG") with open( "/home/dragos/Documents/AWS_CDK/app_lb_sample/app_lb_sample/configure.sh", 'r') as config_file: ud = core.Fn.base64(config_file.read()) bastion_host = ec2.CfnInstance( self, id="bastion", image_id="ami-0de9f803fcac87f46", instance_type="t2.micro", subnet_id=pub_subnet.subnet_id, key_name="proton_mail_kp", security_group_ids=[sg_lb.ref], tags=[core.CfnTag(key="Name", value="bastion")]) instance01 = ec2.CfnInstance( self, id="WebServer01", image_id="ami-0de9f803fcac87f46", instance_type="t2.micro", subnet_id=subnet01.subnet_id, key_name="proton_mail_kp", security_group_ids=[sg_ec2i.ref], user_data=ud, tags=[core.CfnTag(key="Name", value="WebServer01")]) instance02 = ec2.CfnInstance( self, id="WebServer02", image_id="ami-0de9f803fcac87f46", instance_type="t2.micro", subnet_id=subnet02.subnet_id, key_name="proton_mail_kp", security_group_ids=[sg_ec2i.ref], user_data=ud, tags=[core.CfnTag(key="Name", value="WebServer02")]) # health_check = elbv2.HealthCheck(enabled=True, # healthy_http_codes="200", # path="/index.html", # protocol=elbv2.Protocol("HTTP")) target01 = elbv2.CfnTargetGroup.TargetDescriptionProperty( id=instance01.ref) target02 = elbv2.CfnTargetGroup.TargetDescriptionProperty( id=instance02.ref) tg = elbv2.CfnTargetGroup( self, id="TG-WEB-HTTP", name="TG-WEB-HTTP", health_check_enabled=True, health_check_path="/index.html", health_check_port="80", matcher=elbv2.CfnTargetGroup.MatcherProperty(http_code="200"), port=80, protocol="HTTP", # CASE SENSITIVE target_type="instance", # CASE SENSITIVE targets=[target01, target02], vpc_id=vpc.vpc_id) alb = elbv2.CfnLoadBalancer( self, id="MyALB-HTTP", ip_address_type="ipv4", name="MyALB-HTTP", scheme="internet-facing", security_groups=[sg_lb.ref], type="application", subnets=[subnet01.subnet_id, subnet02.subnet_id]) def_act = Listener.ActionProperty(type="forward", authenticate_cognito_config=None, authenticate_oidc_config=None, fixed_response_config=None, forward_config=None, order=50000, redirect_config=None, target_group_arn=tg.ref) listener = elbv2.CfnListener(self, id="Listener01", load_balancer_arn=alb.ref, port=80, protocol="HTTP", default_actions=[def_act])
def __init__(self, scope: core.Construct, id: str, vpc, subnet_id, **kwargs) -> None: super().__init__(scope, id, **kwargs) prefix = self.node.try_get_context("project_name") env_name = self.node.try_get_context("env") volumne_size = self.node.try_get_context("volumne_size") ec2_type = self.node.try_get_context("ec2_type") self.security_group = ec2.CfnSecurityGroup( self, id="web_server_sg", vpc_id=vpc.ref, group_name=env_name + '-' + prefix + '-www01', group_description="Web server security group", # security_group_ingress=[ingress_ssh], # security_group_egress=[egress_all], tags=[ core.CfnTag(key="Name", value=env_name + '-' + prefix + '-www01') ]) # public Ingress ec2.CfnSecurityGroupIngress(self, 'publicsecuritygroupingress01', group_id=self.security_group.ref, ip_protocol='tcp', cidr_ip='0.0.0.0/0', description='http', from_port=80, to_port=80) ec2.CfnSecurityGroupIngress(self, 'publicsecuritygroupingress02', group_id=self.security_group.ref, ip_protocol='tcp', cidr_ip='0.0.0.0/0', description='ssh', from_port=22, to_port=22) # public Egress ec2.CfnSecurityGroupEgress( self, 'publicsecuritygroupegress01', group_id=self.security_group.ref, ip_protocol='-1', cidr_ip='0.0.0.0/0' # destination_security_group_id=privatesecuritygroup01.ref, # description='for private', # from_port=22, to_port=22 ) # private Ingress image_id = ec2.AmazonLinuxImage( generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2).get_image( self).image_id self.host = ec2.CfnInstance( self, env_name + '-' + prefix, # availability_zone="ap-northeast-1a", image_id=image_id, instance_type=ec2_type, key_name=key_name, # credit_specification= { "cpu_credits" : "standard" }, credit_specification=ec2.CfnInstance.CreditSpecificationProperty( cpu_credits="standard"), disable_api_termination=False, security_group_ids=[self.security_group.ref], subnet_id=subnet_id.ref, block_device_mappings=[{ "deviceName": "/dev/xvda", "ebs": { "volumeSize": volumne_size, } }], tags=[{ "key": "Name", "value": env_name + '-' + prefix + '-www01' }])
def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) vpc = ec2.Vpc(self, id="MyVPC", nat_gateways=0, cidr="192.168.0.0/20", max_azs=1, subnet_configuration=[]) subnet = ec2.Subnet(self, id="MySubnet", availability_zone="eu-central-1a", cidr_block="192.168.1.0/24", vpc_id=vpc.vpc_id, map_public_ip_on_launch=True) igw = ec2.CfnInternetGateway(self, id="MyIGW", tags=[core.CfnTag(key="Name", value="IGW")]) ec2.CfnVPCGatewayAttachment(self, id="IGW_Assoc", vpc_id=vpc.vpc_id, internet_gateway_id=igw.ref) subnet.add_route(id="default_route", router_id=igw.ref, router_type=ec2.RouterType('GATEWAY'), destination_cidr_block="0.0.0.0/0", enables_internet_connectivity=True) sg_public = ec2.CfnSecurityGroup(self, id="SG_PUBLIC", group_description="SG for the Public Subnet", group_name="SG_PUBLIC", vpc_id=vpc.vpc_id, tags=[core.CfnTag(key="Name", value="SG_Public")]) my_home_ip = requests.get("https://api.ipify.org").text ports_pub = {'tcp': [22, 80], 'icmp': [-1] } for protocol, ports_list in ports_pub.items(): for port in ports_list: ec2.CfnSecurityGroupIngress(self, id=f"sg_pub_in_{protocol}_{port}", group_id=sg_public.attr_group_id, ip_protocol=protocol, cidr_ip=f"{my_home_ip}/32", to_port=port, from_port=port, description=f"{protocol.upper()} {port} from home IP") with open("/home/dragos/Documents/AWS_CDK/instance_creation/instance_creation/configure.sh", 'r') as config_file: ud = core.Fn.base64(config_file.read()) instance = ec2.CfnInstance(self, id="MyInstance", image_id="ami-0de9f803fcac87f46", instance_type="t2.micro", subnet_id=subnet.subnet_id, key_name="proton_mail_kp", security_group_ids=[sg_public.ref], tags=[core.CfnTag(key="Name", value="MyInstance")]) # COMMENT instance.user_data = ud
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) az1 = core.Fn.select(0, core.Fn.get_azs(region=core.Aws.REGION)) az2 = core.Fn.select(1, core.Fn.get_azs(region=core.Aws.REGION)) ########## # VPC ########## # VPC vpc = ec2.Vpc(self, "vpc", cidr="10.0.0.0/16", subnet_configuration=[]) # Internet gateway internet_gateway = ec2.CfnInternetGateway(self, "internet-gateway") ec2.CfnVPCGatewayAttachment(self, "internet_gateway_attatchment", vpc_id=vpc.vpc_id, internet_gateway_id=internet_gateway.ref) # Public Subnet az1 public_subnet_az1 = ec2.PublicSubnet(self, "subnet-public-1a", availability_zone=az1, cidr_block="10.0.0.0/24", vpc_id=vpc.vpc_id, map_public_ip_on_launch=True) public_subnet_az1.add_route("internet-gateway-route", router_id=internet_gateway.ref, router_type=ec2.RouterType.GATEWAY) # Public Subnet az2 public_subnet_az2 = ec2.PublicSubnet(self, "subnet-public-1c", availability_zone=az2, cidr_block="10.0.1.0/24", vpc_id=vpc.vpc_id, map_public_ip_on_launch=True) public_subnet_az2.add_route("internet-gateway-route", router_id=internet_gateway.ref, router_type=ec2.RouterType.GATEWAY) # Private Subnet az1 private_subnet_az1 = ec2.PrivateSubnet(self, "subnet-private-1a", availability_zone=az1, cidr_block="10.0.2.0/24", vpc_id=vpc.vpc_id) # Private Subnet az2 private_subnet_az2 = ec2.PrivateSubnet(self, "subnet-private-1c", availability_zone=az2, cidr_block="10.0.3.0/24", vpc_id=vpc.vpc_id) ########## # EC2 ########## # # EC2 Security Group ec2_security_group = ec2.SecurityGroup(self, "ec2-security-group", vpc=vpc) # ec2_security_group.add_ingress_rule(peer=ec2.Peer.any_ipv4(),connection=ec2.Port.tcp(80)) # User Data user_data = ec2.UserData.for_linux() user_data.add_commands( "yum -y update", "amazon-linux-extras install php7.2 -y", "yum -y install mysql httpd php-mbstring php-xml", "wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/", "tar zxvf /tmp/latest-ja.tar.gz -C /tmp", "cp -r /tmp/wordpress/* /var/www/html/", "chown apache:apache -R /var/www/html", "systemctl enable httpd.service", "systemctl start httpd.service") # EC2 Instance instance_az1 = ec2.CfnInstance( self, "wordpress-instance-az1", subnet_id=public_subnet_az1.subnet_id, image_id=ec2.AmazonLinuxImage( generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2).get_image( self).image_id, instance_type=ec2.InstanceType.of( instance_class=ec2.InstanceClass.BURSTABLE3, instance_size=ec2.InstanceSize.MICRO).to_string(), security_group_ids=[ec2_security_group.security_group_id], user_data=core.Fn.base64(user_data.render())) core.CfnOutput(self, "EC2 PublicDnsName", value=instance_az1.attr_public_dns_name) ########## # RDS ########## # RDS Security Group rds_security_group = ec2.SecurityGroup(self, "rds-security-group", vpc=vpc) ec2.CfnSecurityGroupIngress( self, "rds-security-group-ingress", group_id=rds_security_group.security_group_id, ip_protocol="tcp", from_port=3306, to_port=3306, source_security_group_id=ec2_security_group.security_group_id) # RDS Subnet Group rds_subnet_group = rds.CfnDBSubnetGroup( self, "rds-subnet-group", db_subnet_group_description="rds-subnet-group", subnet_ids=[ private_subnet_az1.subnet_id, private_subnet_az2.subnet_id ]) # RDS Instance rds_instance = rds.CfnDBInstance( self, "rds-instance", db_instance_identifier="wordpress-rds", engine=rds.DatabaseInstanceEngine.mysql( version=rds.MysqlEngineVersion.VER_8_0_20).engine_type, db_instance_class="db.t3.micro", master_username="******", master_user_password="******", db_name="wordpress", multi_az=False, vpc_security_groups=[rds_security_group.security_group_id], db_subnet_group_name=rds_subnet_group.ref, allocated_storage="20") core.CfnOutput(self, "RDS EndpointAddress", value=rds_instance.attr_endpoint_address) core.CfnOutput(self, "RDS EndpointPort", value=rds_instance.attr_endpoint_port) ########## # ALB ########## # ALB Security Group alb_security_group = ec2.SecurityGroup(self, "alb-security-group", vpc=vpc) alb_security_group.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(80)) # ALB Instance alb_instance = elb.ApplicationLoadBalancer( self, "alb", vpc=vpc, vpc_subnets=ec2.SubnetSelection( subnets=[public_subnet_az1, public_subnet_az2]), internet_facing=True, security_group=alb_security_group) # ALB Target Group alb_target_group = elb.ApplicationTargetGroup( self, "alb-target-group", vpc=vpc, target_type=elb.TargetType.INSTANCE, targets=[elb.InstanceTarget(instance_az1.ref)], protocol=elb.ApplicationProtocol.HTTP, port=80, health_check=elb.HealthCheck(protocol=elb.ApplicationProtocol.HTTP, path="/wp-includes/images/blank.gif")) # ALB Listener alb_listener = elb.ApplicationListener( self, "alb-listener", load_balancer=alb_instance, default_target_groups=[alb_target_group], protocol=elb.ApplicationProtocol.HTTP, port=80) core.CfnOutput(self, "ALB DNS Name", value=alb_instance.load_balancer_dns_name) # EC2 Security Group Ingress ec2.CfnSecurityGroupIngress( self, "ec2-security-group-ingress", group_id=ec2_security_group.security_group_id, ip_protocol="tcp", from_port=80, to_port=80, source_security_group_id=alb_security_group.security_group_id)
def __init__(self, scope: core.Stack, id: str, **kwargs): super().__init__(scope, id, **kwargs) # This resource alone will create a private/public subnet in each AZ as well as nat/internet gateway(s) self.vpc = aws_ec2.Vpc( self, "BaseVPC", cidr='10.0.0.0/24', ) # Creating ECS Cluster in the VPC created above self.ecs_cluster = aws_ecs.Cluster(self, "ECSCluster", vpc=self.vpc, cluster_name="container-demo", container_insights=True) # Adding service discovery namespace to cluster self.ecs_cluster.add_default_cloud_map_namespace( name="service.local", ) ###### CAPACITY PROVIDERS SECTION ##### # Adding EC2 capacity to the ECS Cluster #self.asg = self.ecs_cluster.add_capacity( # "ECSEC2Capacity", # instance_type=aws_ec2.InstanceType(instance_type_identifier='t3.small'), # min_capacity=0, # max_capacity=10 #) #core.CfnOutput(self, "EC2AutoScalingGroupName", value=self.asg.auto_scaling_group_name, export_name="EC2ASGName") ##### END CAPACITY PROVIDER SECTION ##### ###### EC2 SPOT CAPACITY PROVIDER SECTION ###### ## As of today, AWS CDK doesn't support Launch Templates on the AutoScaling construct, hence it ## doesn't support Mixed Instances Policy to combine instance types on Auto Scaling and adhere to Spot best practices ## In the meantime, CfnLaunchTemplate and CfnAutoScalingGroup resources are used to configure Spot capacity ## https://github.com/aws/aws-cdk/issues/6734 #self.ecs_spot_instance_role = aws_iam.Role( # self, "ECSSpotECSInstanceRole", # assumed_by=aws_iam.ServicePrincipal("ec2.amazonaws.com"), # managed_policies=[ # aws_iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AmazonEC2ContainerServiceforEC2Role"), # aws_iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AmazonEC2RoleforSSM") # ] #) # #self.ecs_spot_instance_profile = aws_iam.CfnInstanceProfile( # self, "ECSSpotInstanceProfile", # roles = [ # self.ecs_spot_instance_role.role_name # ] # ) # ## This creates a Launch Template for the Auto Scaling group #self.lt = aws_ec2.CfnLaunchTemplate( # self, "ECSEC2SpotCapacityLaunchTemplate", # launch_template_data={ # "instanceType": "m5.large", # "imageId": aws_ssm.StringParameter.value_for_string_parameter( # self, # "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id"), # "securityGroupIds": [ x.security_group_id for x in self.ecs_cluster.connections.security_groups ], # "iamInstanceProfile": {"arn": self.ecs_spot_instance_profile.attr_arn}, # # # Here we configure the ECS agent to drain Spot Instances upon catching a Spot Interruption notice from instance metadata # "userData": core.Fn.base64( # core.Fn.sub( # "#!/usr/bin/bash\n" # "echo ECS_CLUSTER=${cluster_name} >> /etc/ecs/ecs.config\n" # "sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\n" # "sudo service iptables save\n" # "echo ECS_ENABLE_SPOT_INSTANCE_DRAINING=true >> /etc/ecs/ecs.config\n" # "echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config\n" # "cat /etc/ecs/ecs.config", # variables = { # "cluster_name":self.ecs_cluster.cluster_name # } # ) # ) # }, # launch_template_name="ECSEC2SpotCapacityLaunchTemplate") # #self.ecs_ec2_spot_mig_asg = aws_autoscaling.CfnAutoScalingGroup( # self, "ECSEC2SpotCapacity", # min_size = "0", # max_size = "10", # vpc_zone_identifier = [ x.subnet_id for x in self.vpc.private_subnets ], # mixed_instances_policy = { # "instancesDistribution": { # "onDemandAllocationStrategy": "prioritized", # "onDemandBaseCapacity": 0, # "onDemandPercentageAboveBaseCapacity": 0, # "spotAllocationStrategy": "capacity-optimized" # }, # "launchTemplate": { # "launchTemplateSpecification": { # "launchTemplateId": self.lt.ref, # "version": self.lt.attr_default_version_number # }, # "overrides": [ # {"instanceType": "m5.large"}, # {"instanceType": "m5d.large"}, # {"instanceType": "m5a.large"}, # {"instanceType": "m5ad.large"}, # {"instanceType": "m5n.large"}, # {"instanceType": "m5dn.large"}, # {"instanceType": "m3.large"}, # {"instanceType": "m4.large"}, # {"instanceType": "t3.large"}, # {"instanceType": "t2.large"} # ] # } # } #) # #core.Tag.add(self.ecs_ec2_spot_mig_asg, "Name", self.ecs_ec2_spot_mig_asg.node.path) #core.CfnOutput(self, "EC2SpotAutoScalingGroupName", value=self.ecs_ec2_spot_mig_asg.ref, export_name="EC2SpotASGName") # ##### END EC2 SPOT CAPACITY PROVIDER SECTION ##### # Namespace details as CFN output self.namespace_outputs = { 'ARN': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_arn, 'NAME': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_name, 'ID': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_id, } # Cluster Attributes self.cluster_outputs = { 'NAME': self.ecs_cluster.cluster_name, 'SECGRPS': str(self.ecs_cluster.connections.security_groups) } # When enabling EC2, we need the security groups "registered" to the cluster for imports in other service stacks if self.ecs_cluster.connections.security_groups: self.cluster_outputs['SECGRPS'] = str([ x.security_group_id for x in self.ecs_cluster.connections.security_groups ][0]) # Frontend service to backend services on 3000 self.services_3000_sec_group = aws_ec2.SecurityGroup( self, "FrontendToBackendSecurityGroup", allow_all_outbound=True, description= "Security group for frontend service to talk to backend services", vpc=self.vpc) # Allow inbound 3000 from ALB to Frontend Service self.sec_grp_ingress_self_3000 = aws_ec2.CfnSecurityGroupIngress( self, "InboundSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_3000_sec_group. security_group_id, from_port=3000, to_port=3000, group_id=self.services_3000_sec_group.security_group_id) # Creating an EC2 bastion host to perform load test on private backend services amzn_linux = aws_ec2.MachineImage.latest_amazon_linux( generation=aws_ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, edition=aws_ec2.AmazonLinuxEdition.STANDARD, virtualization=aws_ec2.AmazonLinuxVirt.HVM, storage=aws_ec2.AmazonLinuxStorage.GENERAL_PURPOSE) # Instance Role/profile that will be attached to the ec2 instance # Enabling service role so the EC2 service can use ssm role = aws_iam.Role( self, "InstanceSSM", assumed_by=aws_iam.ServicePrincipal("ec2.amazonaws.com")) # Attaching the SSM policy to the role so we can use SSM to ssh into the ec2 instance role.add_managed_policy( aws_iam.ManagedPolicy.from_aws_managed_policy_name( "service-role/AmazonEC2RoleforSSM")) # Reading user data, to install siege into the ec2 instance. with open("stresstool_user_data.sh") as f: user_data = f.read() # Instance creation self.instance = aws_ec2.Instance( self, "Instance", instance_name="{}-stresstool".format(stack_name), instance_type=aws_ec2.InstanceType("t3.medium"), machine_image=amzn_linux, vpc=self.vpc, role=role, user_data=aws_ec2.UserData.custom(user_data), security_group=self.services_3000_sec_group) # App Mesh Configuration # self.appmesh() # All Outputs required for other stacks to build core.CfnOutput(self, "NSArn", value=self.namespace_outputs['ARN'], export_name="NSARN") core.CfnOutput(self, "NSName", value=self.namespace_outputs['NAME'], export_name="NSNAME") core.CfnOutput(self, "NSId", value=self.namespace_outputs['ID'], export_name="NSID") core.CfnOutput(self, "FE2BESecGrp", value=self.services_3000_sec_group.security_group_id, export_name="SecGrpId") core.CfnOutput(self, "ECSClusterName", value=self.cluster_outputs['NAME'], export_name="ECSClusterName") core.CfnOutput(self, "ECSClusterSecGrp", value=self.cluster_outputs['SECGRPS'], export_name="ECSSecGrpList") core.CfnOutput(self, "ServicesSecGrp", value=self.services_3000_sec_group.security_group_id, export_name="ServicesSecGrp") core.CfnOutput(self, "StressToolEc2Id", value=self.instance.instance_id) core.CfnOutput(self, "StressToolEc2Ip", value=self.instance.instance_private_ip)
def __init__(self, scope: core.Construct, id: str, application_port, ingress_security_group_ids, ssl_certificate_arn, ssl_policy, subnet_ids, vpc_id): super().__init__(scope, id) # Use low level constructs to build security groups as it allows us to name the # ingress rules properly. It's also easier to map the low level construct params # to their cfn equivalent app_sg = ec2.CfnSecurityGroup( self, id='SharedApplicationSecurityGroup', group_description='Shared Fargate Security Group', vpc_id=vpc_id) app_lb_sg = ec2.CfnSecurityGroup( self, id='SharedApplicationLBSecurityGroup', group_description='Shared ALB Security Group', vpc_id=vpc_id, security_group_egress=[{ 'ipProtocol': 'tcp', 'fromPort': application_port, 'toPort': application_port, 'destinationSecurityGroupId': app_sg.ref }]) app_sg_ingress = ec2.CfnSecurityGroupIngress( self, id='SharedApplicationSecurityGroupIngress', group_id=app_sg.ref, source_security_group_id=app_lb_sg.ref, ip_protocol='tcp', from_port=application_port, to_port=application_port) for index, sg in enumerate(ingress_security_group_ids): ec2.CfnSecurityGroupIngress( self, id=f"SharedApplicationLBSecurityGroupIngress{index}", group_id=app_lb_sg.ref, source_security_group_id=sg, ip_protocol='tcp', from_port=443, to_port=443) lb = elbv2.CfnLoadBalancer(self, id='SharedLoadBalancer', scheme='internal', security_groups=[app_lb_sg.ref], subnets=subnet_ids) listener = elbv2.CfnListener( self, id='SharedListener', certificates=[{ 'certificateArn': ssl_certificate_arn }], default_actions=[{ 'type': 'fixed-response', 'fixedResponseConfig': { 'contentType': 'text/plain', 'messageBody': 'You have reached the the Load Balancer, but not matched any of the listener rules', 'statusCode': '200' } }], load_balancer_arn=lb.ref, port=443, protocol='HTTPS', ssl_policy=ssl_policy) core.CfnOutput( self, id=SHARED_LB_DNS_NAME, description='Shared Load Balancer DNS Name', export_name=f"{core.Aws.STACK_NAME}:{SHARED_LB_DNS_NAME}", value=lb.attr_dns_name) core.CfnOutput( self, id=SHARED_LB_HOSTED_ZONE_ID, description='Shared Load Balancer Canonical Hosted Zone ID', export_name=f"{core.Aws.STACK_NAME}:{SHARED_LB_HOSTED_ZONE_ID}", value=lb.attr_canonical_hosted_zone_id) core.CfnOutput( self, id=SHARED_LB_LISTENER, description='Shared Load Balancer Listener', export_name=f"{core.Aws.STACK_NAME}:{SHARED_LB_LISTENER}", value=listener.ref) core.CfnOutput( self, id=SHARED_SERVICE_SECURITY_GROUP, description='Shared Fargate Security Group', export_name= f"{core.Aws.STACK_NAME}:{SHARED_SERVICE_SECURITY_GROUP}", value=app_sg.ref)
def __init__(self, scope: core.Stack, id: str, **kwargs): super().__init__(scope, id, **kwargs) environment = 'dev' support_group_cluster_name = 'octank-support' resource_name = support_group_cluster_name + '-' + environment # This resource alone will create a private/public subnet in each AZ as well as nat/internet gateway(s) self.vpc = aws_ec2.Vpc(self, 'OctankSupportVPC', cidr='10.0.0.0/24', max_azs=3) # Creating ECS Cluster in the VPC created above self.ecs_cluster = aws_ecs.Cluster(self, resource_name, vpc=self.vpc, cluster_name=resource_name) # Adding service discovery namespace to cluster self.ecs_cluster.add_default_cloud_map_namespace( name='support.octank.local', # name=resource_name + '-services', ) # Namespace details as CFN output self.namespace_outputs = { 'ARN': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_arn, 'NAME': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_name, 'ID': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_id, } # Cluster Attributes self.cluster_outputs = { 'NAME': self.ecs_cluster.cluster_name, # 'SECGRPS': str(self.ecs_cluster.connections.security_groups) } # Security Group for port 8080 services self.services_8080_sec_group = aws_ec2.SecurityGroup( # self, 'FrontendToBackendSecurityGroup', self, 'ELBToBackendSecurityGroup', allow_all_outbound=True, description= 'Security group for LB to talk to octicketing applicatoin', vpc=self.vpc) # Allow inbound 8080 from ALB to Frontend Service self.sec_grp_ingress_self_8080 = aws_ec2.CfnSecurityGroupIngress( self, 'InboundSecGrp8080', ip_protocol='TCP', source_security_group_id=self.services_8080_sec_group. security_group_id, from_port=8080, to_port=8080, group_id=self.services_8080_sec_group.security_group_id) # All Outputs required for other stacks to build core.CfnOutput(self, 'NSArn', value=self.namespace_outputs['ARN'], export_name='NSARN') core.CfnOutput(self, 'NSName', value=self.namespace_outputs['NAME'], export_name='NSNAME') core.CfnOutput(self, 'NSId', value=self.namespace_outputs['ID'], export_name='NSID') # value=self.services_8080_sec_group.security_group_id, export_name='SecGrpId') core.CfnOutput(self, 'ECSClusterName', value=self.cluster_outputs['NAME'], export_name='ECSClusterName') core.CfnOutput(self, 'ServicesSecGrp', value=self.services_8080_sec_group.security_group_id, export_name='ServicesSecGrp')
def __init__(self, scope: core.Stack, id: str, **kwargs): super().__init__(scope, id, **kwargs) # This resource alone will create a private/public subnet in each AZ as well as nat/internet gateway(s) self.vpc = aws_ec2.Vpc( self, "BaseVPC", cidr='10.0.0.0/24', ) # Creating ECS Cluster in the VPC created above self.ecs_cluster = aws_ecs.Cluster(self, "ECSCluster", vpc=self.vpc) # Adding service discovery namespace to cluster self.ecs_cluster.add_default_cloud_map_namespace(name="service", ) # Namespace details as CFN output self.namespace_outputs = { 'ARN': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_arn, 'NAME': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_name, 'ID': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_id, } # Cluster Attributes self.cluster_outputs = { 'NAME': self.ecs_cluster.cluster_name, 'SECGRPS': str(self.ecs_cluster.connections.security_groups) } # Frontend service to backend services on 3000 self.services_3000_sec_group = aws_ec2.SecurityGroup( self, "FrontendToBackendSecurityGroup", allow_all_outbound=True, description= "Security group for frontend service to talk to backend services", vpc=self.vpc) # Allow inbound 3000 from ALB to Frontend Service self.sec_grp_ingress_self_3000 = aws_ec2.CfnSecurityGroupIngress( self, "InboundSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_3000_sec_group. security_group_id, from_port=3000, to_port=3000, group_id=self.services_3000_sec_group.security_group_id) # All Outputs required for other stacks to build core.CfnOutput(self, "NSArn", value=self.namespace_outputs['ARN'], export_name="NSARN") core.CfnOutput(self, "NSName", value=self.namespace_outputs['NAME'], export_name="NSNAME") core.CfnOutput(self, "NSId", value=self.namespace_outputs['ID'], export_name="NSID") core.CfnOutput(self, "FE2BESecGrp", value=self.services_3000_sec_group.security_group_id, export_name="SecGrpId") core.CfnOutput(self, "ECSClusterName", value=self.cluster_outputs['NAME'], export_name="ECSClusterName") core.CfnOutput(self, "ECSClusterSecGrp", value=self.cluster_outputs['SECGRPS'], export_name="ECSSecGrpList") core.CfnOutput(self, "ServicesSecGrp", value=self.services_3000_sec_group.security_group_id, export_name="ServicesSecGrp")
def __init__(self, scope: core.Stack, id: str, **kwargs): super().__init__(scope, id, **kwargs) # This resource alone will create a private/public subnet in each AZ as well as nat/internet gateway(s) self.vpc = aws_ec2.Vpc( self, "BaseVPC", cidr='10.0.0.0/24', ) # Creating ECS Cluster in the VPC created above self.ecs_cluster = aws_ecs.Cluster(self, "ECSCluster", vpc=self.vpc, cluster_name="container-demo") # Adding service discovery namespace to cluster self.ecs_cluster.add_default_cloud_map_namespace(name="service", ) ###### CAPACITY PROVIDERS SECTION ##### # Adding EC2 capacity to the ECS Cluster self.asg = self.ecs_cluster.add_capacity( "ECSEC2Capacity", instance_type=aws_ec2.InstanceType( instance_type_identifier='t3.small'), min_capacity=0, max_capacity=10) core.CfnOutput(self, "EC2AutoScalingGroupName", value=self.asg.auto_scaling_group_name, export_name="EC2ASGName") ##### END CAPACITY PROVIDER SECTION ##### # Namespace details as CFN output self.namespace_outputs = { 'ARN': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_arn, 'NAME': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_name, 'ID': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_id, } # Cluster Attributes self.cluster_outputs = { 'NAME': self.ecs_cluster.cluster_name, 'SECGRPS': str(self.ecs_cluster.connections.security_groups) } # When enabling EC2, we need the security groups "registered" to the cluster for imports in other service stacks if self.ecs_cluster.connections.security_groups: self.cluster_outputs['SECGRPS'] = str([ x.security_group_id for x in self.ecs_cluster.connections.security_groups ][0]) # Frontend service to backend services on 3000 self.services_3000_sec_group = aws_ec2.SecurityGroup( self, "FrontendToBackendSecurityGroup", allow_all_outbound=True, description= "Security group for frontend service to talk to backend services", vpc=self.vpc) # Allow inbound 3000 from ALB to Frontend Service self.sec_grp_ingress_self_3000 = aws_ec2.CfnSecurityGroupIngress( self, "InboundSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_3000_sec_group. security_group_id, from_port=3000, to_port=3000, group_id=self.services_3000_sec_group.security_group_id) # Creating an EC2 bastion host to perform load test on private backend services amzn_linux = aws_ec2.MachineImage.latest_amazon_linux( generation=aws_ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, edition=aws_ec2.AmazonLinuxEdition.STANDARD, virtualization=aws_ec2.AmazonLinuxVirt.HVM, storage=aws_ec2.AmazonLinuxStorage.GENERAL_PURPOSE) # Instance Role/profile that will be attached to the ec2 instance # Enabling service role so the EC2 service can use ssm role = aws_iam.Role( self, "InstanceSSM", assumed_by=aws_iam.ServicePrincipal("ec2.amazonaws.com")) # Attaching the SSM policy to the role so we can use SSM to ssh into the ec2 instance role.add_managed_policy( aws_iam.ManagedPolicy.from_aws_managed_policy_name( "service-role/AmazonEC2RoleforSSM")) # Reading user data, to install siege into the ec2 instance. with open("stresstool_user_data.sh") as f: user_data = f.read() # Instance creation self.instance = aws_ec2.Instance( self, "Instance", instance_name="{}-stresstool".format(stack_name), instance_type=aws_ec2.InstanceType("t3.medium"), machine_image=amzn_linux, vpc=self.vpc, role=role, user_data=aws_ec2.UserData.custom(user_data), security_group=self.services_3000_sec_group) # All Outputs required for other stacks to build core.CfnOutput(self, "NSArn", value=self.namespace_outputs['ARN'], export_name="NSARN") core.CfnOutput(self, "NSName", value=self.namespace_outputs['NAME'], export_name="NSNAME") core.CfnOutput(self, "NSId", value=self.namespace_outputs['ID'], export_name="NSID") core.CfnOutput(self, "FE2BESecGrp", value=self.services_3000_sec_group.security_group_id, export_name="SecGrpId") core.CfnOutput(self, "ECSClusterName", value=self.cluster_outputs['NAME'], export_name="ECSClusterName") core.CfnOutput(self, "ECSClusterSecGrp", value=self.cluster_outputs['SECGRPS'], export_name="ECSSecGrpList") core.CfnOutput(self, "ServicesSecGrp", value=self.services_3000_sec_group.security_group_id, export_name="ServicesSecGrp") core.CfnOutput(self, "StressToolEc2Id", value=self.instance.instance_id) core.CfnOutput(self, "StressToolEc2Ip", value=self.instance.instance_private_ip)
def __init__(self, scope: core.Construct, id: str, vpc_ip: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) if vpc_ip: print("VPC_IP " + vpc_ip) cidr = vpc_ip else: cidr = "10.0.0.0/16" # 01. VPC 생성 cfVpc = ec2.CfnVPC(self, "VPC", cidr_block=cidr, tags=[core.Tag(key="Name", value="CDKVPC")]) # 02. Subnet 생성 subnet_2a = ec2.CfnSubnet( self, id="subnet_2a", availability_zone="ap-northeast-2a", cidr_block="100.0.1.0/24", map_public_ip_on_launch=True, vpc_id=cfVpc.ref, tags=[core.Tag(key="Name", value="subnet-2a")]) subnet_2c = ec2.CfnSubnet( self, id="subnet_2c", availability_zone="ap-northeast-2c", cidr_block="100.0.2.0/24", map_public_ip_on_launch=True, vpc_id=cfVpc.ref, tags=[core.Tag(key="Name", value="subnet-2c")]) # 03. Internet Gateway 생성 internet_gateway = ec2.CfnInternetGateway( self, id="Internet_Gateway_DNS_Example", tags=[core.Tag(key="Name", value="Internet_Gateway_for_DNS")]) # 04. Internat Gateway Attach ec2.CfnVPCGatewayAttachment(self, id="vpcgw", vpc_id=cfVpc.ref, internet_gateway_id=internet_gateway.ref) #05. Route Table 생성 route_table = ec2.CfnRouteTable( self, id="dns_example_routetable", vpc_id=cfVpc.ref, tags=[core.Tag(key="Name", value="Route_for_DNS")]) #Route ec2.CfnRoute(self, id="IGW_Route", route_table_id=route_table.ref, destination_cidr_block="0.0.0.0/0", gateway_id=internet_gateway.ref) ec2.CfnSubnetRouteTableAssociation(self, id="DnsSubnet_Associate_2a", route_table_id=route_table.ref, subnet_id=subnet_2a.ref) ec2.CfnSubnetRouteTableAssociation(self, id="DnsSubnet_Associate_2c", route_table_id=route_table.ref, subnet_id=subnet_2c.ref) # 03. SG 생성 sg = ec2.CfnSecurityGroup(self, id="sg-ssh", vpc_id=cfVpc.ref, group_description="Default Group", tags=[core.Tag(key="Name", value="DNS_SG")]) #security_group_ingress=[ingress_ssh]) #security_group_egress=[egress_all]) ingress_ssh = ec2.CfnSecurityGroupIngress(self, "SSH", ip_protocol="tcp", group_id=sg.ref, from_port=22, to_port=22, cidr_ip="0.0.0.0/0") egress_all = ec2.CfnSecurityGroupEgress( self, id="OUTBOUND", group_id=sg.ref, ip_protocol="-1", #from_port=0, #to_port=65535, cidr_ip="0.0.0.0/0") # 04. DNS Server EC2 생성 dns_server = ec2.MachineImage.generic_linux( {"ap-northeast-2": "ami-00d293396a942208d"}) ec2.CfnInstance(self, id="dns_master", image_id=dns_server.get_image(self).image_id, instance_type="t2.small", key_name="SeoulRegion", security_group_ids=[sg.ref], subnet_id=subnet_2a.ref, tags=[{ "key": "Name", "value": "dns_master" }]) ec2.CfnInstance(self, id="dns_slave", image_id=dns_server.get_image(self).image_id, instance_type="t2.small", key_name="SeoulRegion", security_group_ids=[sg.ref], subnet_id=subnet_2c.ref, tags=[{ "key": "Name", "value": "dns_slave" }])
def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # Create an empty VPC # If you don't specify any other resources EXCEPT the VPC, there's a standard template applied vpc = ec2.Vpc( self, id="MyVPC", nat_gateways=0, cidr="192.168.0.0/20", max_azs=1, subnet_configuration=[], ) # A couple of subnets app_subnet = ec2.CfnSubnet( self, id="Application", vpc_id=vpc.vpc_id, availability_zone="eu-central-1a", cidr_block="192.168.1.0/24", map_public_ip_on_launch=False, tags=[core.CfnTag(key="Name", value="Application")]) web_subnet = ec2.CfnSubnet( self, id="Webhost", vpc_id=vpc.vpc_id, availability_zone="eu-central-1b", cidr_block="192.168.2.0/24", map_public_ip_on_launch=True, tags=[core.CfnTag(key="Name", value="WebHost")]) # A couple of route tables private_rt = ec2.CfnRouteTable( self, id="Private_RT", vpc_id=vpc.vpc_id, tags=[core.CfnTag(key="Name", value="Private_RT")]) public_rt = ec2.CfnRouteTable( self, id="Public_RT", vpc_id=vpc.vpc_id, tags=[core.CfnTag(key="Name", value="Public_RT")]) # How to associate a subnet with a route table ec2.CfnSubnetRouteTableAssociation(self, id="WebHostRTAssoc", subnet_id=web_subnet.ref, route_table_id=public_rt.ref) ec2.CfnSubnetRouteTableAssociation(self, id="ApplicationRTAssoc", subnet_id=app_subnet.ref, route_table_id=private_rt.ref) # A gateway (Internet Gateway in this case) igw = ec2.CfnInternetGateway( self, id="MyIGW", tags=[core.CfnTag(key="Name", value="IGW")]) # How to associate a gateway to a VPC (IGW in this case - for VGW use vpn_gateway_id=blablabla) ec2.CfnVPCGatewayAttachment(self, id="IGW_Assoc", vpc_id=vpc.vpc_id, internet_gateway_id=igw.ref) # Elastic IP eip_01 = ec2.CfnEIP(self, id="EIP01") # NAT gateway ngw = ec2.CfnNatGateway(self, id="NAT_GW", allocation_id=eip_01.attr_allocation_id, subnet_id=web_subnet.ref, tags=[core.CfnTag(key="Name", value="NAT_GW")]) ngw.add_depends_on(eip_01) # Add a route to a route table default_route_public = ec2.CfnRoute(self, id="DefaultRoutePublic", route_table_id=public_rt.ref, destination_cidr_block="0.0.0.0/0", gateway_id=igw.ref) default_route_public.add_depends_on(igw) default_route_private = ec2.CfnRoute( self, id="DefaultRouteprivate", route_table_id=private_rt.ref, destination_cidr_block="0.0.0.0/0", nat_gateway_id=ngw.ref) default_route_private.add_depends_on(ngw) ### Security Groups ### # PUBLIC SUBNET SG sg_public = ec2.CfnSecurityGroup( self, id="SG_PUBLIC", group_description="SG for the Public Subnet", group_name="SG_PUBLIC", vpc_id=vpc.vpc_id, tags=[core.CfnTag(key="Name", value="SG_Public")]) my_home_ip = requests.get("https://api.my-ip.io/ip.json").json()['ip'] ports_pub = {'tcp': [22, 80], 'icmp': [-1]} for protocl, ports_list in ports_pub.items(): for port in ports_list: ec2.CfnSecurityGroupIngress( self, id=f"sg_pub_in_{protocl}_{port}", group_id=sg_public.attr_group_id, ip_protocol=protocl, cidr_ip=f"{my_home_ip}/32", to_port=port, from_port=port, description=f"{protocl.upper()} {port} from home IP") # SG INGRESS ENTRIES - ICMP - EXAMPLE # sg_in_icmp = ec2.CfnSecurityGroupIngress(self, id="SG_PUB_IN_ICMP", # group_id=sg_public.attr_group_id, # ip_protocol = "icmp", # cidr_ip = f"{my_home_ip}/32", # to_port = -1, # from_port = -1, # description = "ICMP FROM HOME") # SG EGRESS ENTRIES - AUTO-IMPLIED IF NOT CONFIGURED # sg_out_all = ec2.CfnSecurityGroupEgress(self, id="SG_PUB_OUT_ALL", # group_id=sg_public.attr_group_id, # ip_protocol="-1", # cidr_ip="0.0.0.0/0") # PRIVATE SUBNET SG sg_private = ec2.CfnSecurityGroup( self, id="SG_PRIVATE", group_description="SG for the Private Subnet", group_name="SG_PRIVATE", vpc_id=vpc.vpc_id, tags=[core.CfnTag(key="Name", value="SG_Private")]) sg_private.add_depends_on(sg_public) ports_priv = {'tcp': [22, 21, 53, 3368, 80], 'icmp': [-1]} for protocl, ports_list in ports_priv.items(): for port in ports_list: ec2.CfnSecurityGroupIngress( self, id=f"sg_priv_in_{protocl}_{port}", group_id=sg_private.attr_group_id, description= f"{protocl.upper()}:{port} from the public subnet only", ip_protocol=protocl, from_port=port, to_port=port, source_security_group_id=sg_public.ref) ### EC2 Instances ### # Generate some user data _ WIP # user_data = ec2.UserData.custom # One in the public subnet webserver01 = ec2.CfnInstance( self, id="WebServer01", image_id="ami-0de9f803fcac87f46", instance_type="t2.micro", subnet_id=web_subnet.ref, key_name="proton_mail_kp", security_group_ids=[sg_public.ref], tags=[core.CfnTag(key="Name", value="WebServer01")]) appserver01 = ec2.CfnInstance( self, id="AppServer01", image_id="ami-0de9f803fcac87f46", instance_type="t2.micro", subnet_id=app_subnet.ref, key_name="proton_mail_kp", security_group_ids=[sg_private.ref], tags=[core.CfnTag(key="Name", value="AppServer01")])
def __init__(self, scope: core.Stack, id: str, **kwargs): super().__init__(scope, id, **kwargs) # This resource alone will create a private/public subnet in each AZ as well as nat/internet gateway(s) self.vpc = aws_ec2.Vpc( self, "BaseVPC", cidr='10.0.0.0/24', ) # Creating ECS Cluster in the VPC created above self.ecs_cluster = aws_ecs.Cluster(self, "ECSCluster", vpc=self.vpc, cluster_name="stang-ec2-cluster") # Adding service discovery namespace to cluster self.ecs_cluster.add_default_cloud_map_namespace(name="service", ) ###### CAPACITY PROVIDERS SECTION ##### # Adding EC2 capacity to the ECS Cluster self.asg = self.ecs_cluster.add_capacity( "ECSEC2Capacity", instance_type=aws_ec2.InstanceType( instance_type_identifier='m5.large'), key_name='stang-linux-us-west-2', min_capacity=0, max_capacity=10) core.CfnOutput(self, "EC2AutoScalingGroupName", value=self.asg.auto_scaling_group_name, export_name="EC2ASGName") ##### END CAPACITY PROVIDER SECTION ##### # Namespace details as CFN output self.namespace_outputs = { 'ARN': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_arn, 'NAME': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_name, 'ID': self.ecs_cluster.default_cloud_map_namespace. private_dns_namespace_id, } # Cluster Attributes self.cluster_outputs = { 'NAME': self.ecs_cluster.cluster_name, 'SECGRPS': str(self.ecs_cluster.connections.security_groups) } # When enabling EC2, we need the security groups "registered" to the cluster for imports in other service stacks if self.ecs_cluster.connections.security_groups: self.cluster_outputs['SECGRPS'] = str([ x.security_group_id for x in self.ecs_cluster.connections.security_groups ][0]) # Frontend service to backend services on 3000 self.services_3000_sec_group = aws_ec2.SecurityGroup( self, "FrontendToBackendSecurityGroup", allow_all_outbound=True, description= "Security group for frontend service to talk to backend services", vpc=self.vpc) # Allow inbound 3000 from ALB to Frontend Service self.sec_grp_ingress_self_3000 = aws_ec2.CfnSecurityGroupIngress( self, "InboundSecGrp3000", ip_protocol='TCP', source_security_group_id=self.services_3000_sec_group. security_group_id, from_port=3000, to_port=3000, group_id=self.services_3000_sec_group.security_group_id) # All Outputs required for other stacks to build core.CfnOutput(self, "NSArn", value=self.namespace_outputs['ARN'], export_name="NSARN") core.CfnOutput(self, "NSName", value=self.namespace_outputs['NAME'], export_name="NSNAME") core.CfnOutput(self, "NSId", value=self.namespace_outputs['ID'], export_name="NSID") core.CfnOutput(self, "FE2BESecGrp", value=self.services_3000_sec_group.security_group_id, export_name="SecGrpId") core.CfnOutput(self, "ECSClusterName", value=self.cluster_outputs['NAME'], export_name="ECSClusterName") core.CfnOutput(self, "ECSClusterSecGrp", value=self.cluster_outputs['SECGRPS'], export_name="ECSSecGrpList") core.CfnOutput(self, "ServicesSecGrp", value=self.services_3000_sec_group.security_group_id, export_name="ServicesSecGrp")
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) current_directory = os.path.realpath( os.path.join(os.getcwd(), os.path.dirname(__file__))) allowed_values = yaml.load(open( os.path.join(current_directory, "..", "..", "allowed_values.yaml")), Loader=yaml.SafeLoader) ami_mapping = {"AMI": {"OEJITSI": AMI_NAME}} for region in generated_ami_ids.keys(): ami_mapping[region] = {"OEJITSI": generated_ami_ids[region]} aws_ami_region_map = core.CfnMapping(self, "AWSAMIRegionMap", mapping=ami_mapping) # utility function to parse the unique id from the stack id for # shorter resource names using cloudformation functions def append_stack_uuid(name): return core.Fn.join("-", [ name, core.Fn.select( 0, core.Fn.split( "-", core.Fn.select(2, core.Fn.split( "/", core.Aws.STACK_ID)))) ]) # # PARAMETERS # cidr_block_param = core.CfnParameter( self, "IngressCidrBlock", allowed_pattern="((\d{1,3})\.){3}\d{1,3}/\d{1,2}", default="0.0.0.0/0", description= "Required: A CIDR block to restrict access to the Jitsi application. Leave as 0.0.0.0/0 to allow public access from internet." ) ec2_instance_type_param = core.CfnParameter( self, "InstanceType", allowed_values=allowed_values["allowed_instance_types"], default="t3.xlarge", description= "Required: The EC2 instance type for the application Auto Scaling Group." ) jitsi_hostname_param = core.CfnParameter( self, "JitsiHostname", description= "Required: The hostname to access Jitsi. E.G. 'jitsi.internal.mycompany.com'" ) jitsi_interface_app_name_param = core.CfnParameter( self, "JitsiInterfaceAppName", default="Jitsi Meet", description= "Optional: Customize the app name on the Jitsi interface.") jitsi_interface_default_remote_display_name_param = core.CfnParameter( self, "JitsiInterfaceDefaultRemoteDisplayName", default="Fellow Jitster", description= "Optional: Customize the default display name for Jitsi users.") jitsi_interface_native_app_name_param = core.CfnParameter( self, "JitsiInterfaceNativeAppName", default="Jitsi Meet", description= "Optional: Customize the native app name on the Jitsi interface.") jitsi_interface_show_brand_watermark_param = core.CfnParameter( self, "JitsiInterfaceShowBrandWatermark", allowed_values=["true", "false"], default="true", description= "Optional: Display the watermark logo image in the upper left corner." ) jitsi_interface_show_watermark_for_guests_param = core.CfnParameter( self, "JitsiInterfaceShowWatermarkForGuests", allowed_values=["true", "false"], default="true", description= "Optional: Display the watermark logo image in the upper left corner for guest users. This can be set to override the general setting behavior for guest users." ) jitsi_interface_brand_watermark_param = core.CfnParameter( self, "JitsiInterfaceBrandWatermark", default="", description= "Optional: Provide a URL to a PNG image to be used as the brand watermark logo image in the upper right corner. File should be publically available for download." ) jitsi_interface_brand_watermark_link_param = core.CfnParameter( self, "JitsiInterfaceBrandWatermarkLink", default="http://jitsi.org", description= "Optional: Provide a link destination for the brand watermark logo image in the upper right corner." ) jitsi_interface_watermark_param = core.CfnParameter( self, "JitsiInterfaceWatermark", default="", description= "Optional: Provide a URL to a PNG image to be used as the watermark logo image in the upper left corner. File should be publically available for download." ) jitsi_interface_watermark_link_param = core.CfnParameter( self, "JitsiInterfaceWatermarkLink", default="http://jitsi.org", description= "Optional: Provide a link destination for the Jitsi watermark logo image in the upper left corner." ) route_53_hosted_zone_name_param = core.CfnParameter( self, "Route53HostedZoneName", description= "Required: Route 53 Hosted Zone name in which a DNS record will be created by this template. Must already exist and be the domain part of the Jitsi Hostname parameter, without trailing dot. E.G. 'internal.mycompany.com'" ) notification_email_param = core.CfnParameter( self, "NotificationEmail", default="", description= "Optional: Specify an email address to get emails about deploys, Let's Encrypt, and other system events." ) # # CONDITIONS # notification_email_exists_condition = core.CfnCondition( self, "NotificationEmailExistsCondition", expression=core.Fn.condition_not( core.Fn.condition_equals(notification_email_param.value, ""))) # # RESOURCES # # vpc vpc = Vpc(self, "Vpc") # sns sns_notification_topic = aws_sns.CfnTopic( self, "NotificationTopic", topic_name="{}-notifications".format(core.Aws.STACK_NAME)) sns_notification_subscription = aws_sns.CfnSubscription( self, "NotificationSubscription", protocol="email", topic_arn=sns_notification_topic.ref, endpoint=notification_email_param.value_as_string) sns_notification_subscription.cfn_options.condition = notification_email_exists_condition iam_notification_publish_policy = aws_iam.PolicyDocument(statements=[ aws_iam.PolicyStatement(effect=aws_iam.Effect.ALLOW, actions=["sns:Publish"], resources=[sns_notification_topic.ref]) ]) # cloudwatch app_log_group = aws_logs.CfnLogGroup( self, "JitsiAppLogGroup", retention_in_days=TWO_YEARS_IN_DAYS) app_log_group.cfn_options.update_replace_policy = core.CfnDeletionPolicy.RETAIN app_log_group.cfn_options.deletion_policy = core.CfnDeletionPolicy.RETAIN system_log_group = aws_logs.CfnLogGroup( self, "JitsiSystemLogGroup", retention_in_days=TWO_YEARS_IN_DAYS) system_log_group.cfn_options.update_replace_policy = core.CfnDeletionPolicy.RETAIN system_log_group.cfn_options.deletion_policy = core.CfnDeletionPolicy.RETAIN # iam iam_jitsi_instance_role = aws_iam.CfnRole( self, "JitsiInstanceRole", assume_role_policy_document=aws_iam.PolicyDocument(statements=[ aws_iam.PolicyStatement( effect=aws_iam.Effect.ALLOW, actions=["sts:AssumeRole"], principals=[aws_iam.ServicePrincipal("ec2.amazonaws.com")]) ]), policies=[ aws_iam.CfnRole.PolicyProperty( policy_document=aws_iam.PolicyDocument(statements=[ aws_iam.PolicyStatement( effect=aws_iam.Effect.ALLOW, actions=[ "logs:CreateLogStream", "logs:DescribeLogStreams", "logs:PutLogEvents" ], resources=[ app_log_group.attr_arn, system_log_group.attr_arn ]) ]), policy_name="AllowStreamLogsToCloudWatch"), aws_iam.CfnRole.PolicyProperty( policy_document=aws_iam.PolicyDocument(statements=[ aws_iam.PolicyStatement( effect=aws_iam.Effect.ALLOW, actions=[ "ec2:AssociateAddress", "ec2:DescribeVolumes", "ec2:DescribeTags", "cloudwatch:GetMetricStatistics", "cloudwatch:ListMetrics", "cloudwatch:PutMetricData" ], resources=["*"]) ]), policy_name="AllowStreamMetricsToCloudWatch"), aws_iam.CfnRole.PolicyProperty( policy_document=aws_iam.PolicyDocument(statements=[ aws_iam.PolicyStatement( effect=aws_iam.Effect.ALLOW, actions=["autoscaling:Describe*"], resources=["*"]) ]), policy_name="AllowDescribeAutoScaling"), ], managed_policy_arns=[ "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" ]) # ec2 jitsi_sg = aws_ec2.CfnSecurityGroup( self, "JitsiSg", group_description="Jitsi security group", vpc_id=vpc.id()) eip = aws_ec2.CfnEIP(self, "Eip", domain="vpc") core.Tags.of(eip).add("Name", "{}/Eip".format(core.Aws.STACK_NAME)) ec2_instance_profile = aws_iam.CfnInstanceProfile( self, "JitsiInstanceProfile", roles=[iam_jitsi_instance_role.ref]) with open("jitsi/jitsi_launch_config_user_data.sh") as f: jitsi_launch_config_user_data = f.read() ec2_launch_config = aws_autoscaling.CfnLaunchConfiguration( self, "JitsiLaunchConfig", image_id=core.Fn.find_in_map("AWSAMIRegionMap", core.Aws.REGION, "OEJITSI"), instance_type=ec2_instance_type_param.value_as_string, iam_instance_profile=ec2_instance_profile.ref, security_groups=[jitsi_sg.ref], user_data=(core.Fn.base64( core.Fn.sub( jitsi_launch_config_user_data, { "JitsiHostname": jitsi_hostname_param.value_as_string, "JitsiPublicIP": eip.ref, "LetsEncryptCertificateEmail": notification_email_param.value_as_string })))) # autoscaling asg = aws_autoscaling.CfnAutoScalingGroup( self, "JitsiAsg", launch_configuration_name=ec2_launch_config.ref, desired_capacity="1", max_size="1", min_size="1", vpc_zone_identifier=vpc.public_subnet_ids()) asg.cfn_options.creation_policy = core.CfnCreationPolicy( resource_signal=core.CfnResourceSignal(count=1, timeout="PT15M")) asg.cfn_options.update_policy = core.CfnUpdatePolicy( auto_scaling_rolling_update=core.CfnAutoScalingRollingUpdate( max_batch_size=1, min_instances_in_service=0, pause_time="PT15M", wait_on_resource_signals=True)) core.Tags.of(asg).add("Name", "{}/JitsiAsg".format(core.Aws.STACK_NAME)) jitsi_http_ingress = aws_ec2.CfnSecurityGroupIngress( self, "JitsiHttpSgIngress", cidr_ip=cidr_block_param.value_as_string, from_port=80, group_id=jitsi_sg.ref, ip_protocol="tcp", to_port=80) jitsi_https_ingress = aws_ec2.CfnSecurityGroupIngress( self, "JitsiHttpsSgIngress", cidr_ip=cidr_block_param.value_as_string, from_port=443, group_id=jitsi_sg.ref, ip_protocol="tcp", to_port=443) jitsi_fallback_network_audio_video_ingress = aws_ec2.CfnSecurityGroupIngress( self, "JitsiFallbackNetworkAudioVideoSgIngress", cidr_ip=cidr_block_param.value_as_string, from_port=4443, group_id=jitsi_sg.ref, ip_protocol="tcp", to_port=4443) jitsi_general_network_audio_video_ingress = aws_ec2.CfnSecurityGroupIngress( self, "JitsiGeneralNetworkAudioVideoSgIngress", cidr_ip=cidr_block_param.value_as_string, from_port=10000, group_id=jitsi_sg.ref, ip_protocol="udp", to_port=10000) # route 53 record_set = aws_route53.CfnRecordSet( self, "RecordSet", hosted_zone_name= f"{route_53_hosted_zone_name_param.value_as_string}.", name=jitsi_hostname_param.value_as_string, resource_records=[eip.ref], type="A") # https://github.com/aws/aws-cdk/issues/8431 record_set.add_property_override("TTL", 60) # AWS::CloudFormation::Interface self.template_options.metadata = { "OE::Patterns::TemplateVersion": template_version, "AWS::CloudFormation::Interface": { "ParameterGroups": [{ "Label": { "default": "Infrastructure Config" }, "Parameters": [ jitsi_hostname_param.logical_id, route_53_hosted_zone_name_param.logical_id, cidr_block_param.logical_id, ec2_instance_type_param.logical_id, notification_email_param.logical_id ] }, { "Label": { "default": "Jitsi Config" }, "Parameters": [ jitsi_interface_app_name_param.logical_id, jitsi_interface_default_remote_display_name_param. logical_id, jitsi_interface_native_app_name_param.logical_id, jitsi_interface_show_brand_watermark_param.logical_id, jitsi_interface_show_watermark_for_guests_param. logical_id, jitsi_interface_brand_watermark_param.logical_id, jitsi_interface_brand_watermark_link_param.logical_id, jitsi_interface_watermark_param.logical_id, jitsi_interface_watermark_link_param.logical_id, ] }, *vpc.metadata_parameter_group()], "ParameterLabels": { cidr_block_param.logical_id: { "default": "Ingress CIDR Block" }, ec2_instance_type_param.logical_id: { "default": "EC2 instance type" }, jitsi_hostname_param.logical_id: { "default": "Jitsi Hostname" }, jitsi_interface_app_name_param.logical_id: { "default": "Jitsi Interface App Name" }, jitsi_interface_default_remote_display_name_param.logical_id: { "default": "Jitsi Interface Default Remote Display Name" }, jitsi_interface_native_app_name_param.logical_id: { "default": "Jitsi Interface Native App Name" }, jitsi_interface_show_brand_watermark_param.logical_id: { "default": "Jitsi Interface Show Watermark" }, jitsi_interface_show_watermark_for_guests_param.logical_id: { "default": "Jitsi Interface Show Watermark For Guests" }, jitsi_interface_brand_watermark_param.logical_id: { "default": "Jitsi Interface Watermark" }, jitsi_interface_brand_watermark_link_param.logical_id: { "default": "Jitsi Interface Watermark Link" }, jitsi_interface_watermark_param.logical_id: { "default": "Jitsi Interface Watermark" }, jitsi_interface_watermark_link_param.logical_id: { "default": "Jitsi Interface Watermark Link" }, notification_email_param.logical_id: { "default": "Notification Email" }, route_53_hosted_zone_name_param.logical_id: { "default": "AWS Route 53 Hosted Zone Name" }, **vpc.metadata_parameter_labels() } } } # # OUTPUTS # eip_output = core.CfnOutput( self, "EipOutput", description= "The Elastic IP address dynamically mapped to the autoscaling group instance.", value=eip.ref) endpoint_output = core.CfnOutput( self, "JitsiUrl", description="The URL for the Jitsi instance.", value=core.Fn.join( "", ["https://", jitsi_hostname_param.value_as_string]))