def __init__(self, scope: core.Construct, construct_id: str, vpc, nlb_listener_port, nlb_name, nlb_id, internet_facing, targetgroup_port, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) #network load balancer nlb = elb.NetworkLoadBalancer( self, internet_facing=internet_facing, load_balancer_name=nlb_name, id=nlb_id, vpc=vpc, # The object from above vpc from lookup vpc_subnets=ec2.SubnetSelection(subnets=vpc.public_subnets)) #load balancer scuirty group sg_nlb = ec2.SecurityGroup(self, id="sg_nlb", vpc=vpc, security_group_name="sg_nlb") #listener listener = nlb.add_listener("Listener", port=nlb_listener_port, protocol=elb.Protocol.TCP) target_group = elb.NetworkTargetGroup(self, vpc=vpc, id="Target", port=targetgroup_port) listener.add_target_groups("TargetGroup", target_group) #sg_nlb ingress sg_nlb.add_ingress_rule(peer=ec2.Peer.ipv4("0.0.0.0/0"), connection=ec2.Port.tcp(22)) core.Tag(key="Owner", value="Wahaj-nlb")
def __init__(self, scope: core.Construct, id: str, stack_name: str, task_definition_cpu: int, task_definition_memory_limit_mib: int, docker_image_name: str, container_port: int, desired_container_count: int, private_subnets: Sequence[aws_ec2.Subnet] = None, public_subnets: Sequence[aws_ec2.Subnet] = None, private_security_group: aws_ec2.SecurityGroup = None, public_security_group: aws_ec2.SecurityGroup = None, vpc: aws_ec2.Vpc = None, fargate_cluster: aws_ecs.Cluster = None, authorizer_lambda_arn: str = None, authorizer_lambda_role_arn: str = None, **kwargs): super().__init__(scope, id, **kwargs) # Role self.role = aws_iam.Role( self, 'Role', assumed_by=aws_iam.ServicePrincipal(service='ecs.amazonaws.com'), managed_policies=[ aws_iam.ManagedPolicy.from_aws_managed_policy_name( managed_policy_name= 'service-role/AmazonECSTaskExecutionRolePolicy') ], inline_policies={ id: aws_iam.PolicyDocument(statements=[ aws_iam.PolicyStatement( effect=aws_iam.Effect.ALLOW, actions=[ 'kms:Encrypt', 'kms:Decrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*', 'kms:DescribeKey', 'ec2:CreateNetworkInterface', 'ec2:DescribeNetworkInterfaces', 'ec2:DeleteNetworkInterface', # Remaining actions from https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-ecs.html 'elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets', 'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer', 'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress' ], resources=['*']) ]) }) self.role.assume_role_policy.add_statements( aws_iam.PolicyStatement( actions=['sts:AssumeRole'], principals=[ aws_iam.ServicePrincipal(service='ecs-tasks.amazonaws.com') ])) # Set Defaults if parameters are None if vpc is None: vpc = aws_ec2.Vpc(self, 'Vpc') if private_subnets is None: private_subnets = vpc.private_subnets if public_subnets is None: public_subnets = vpc.public_subnets if public_security_group is None: public_security_group = aws_ec2.SecurityGroup( self, 'PublicSecurityGroup', vpc=vpc, allow_all_outbound=True) # Allow inbound HTTP traffic public_security_group.add_ingress_rule( peer=aws_ec2.Peer.ipv4(cidr_ip='0.0.0.0/0'), connection=aws_ec2.Port.tcp(port=80)) # Allow inbound HTTPS traffic public_security_group.add_ingress_rule( peer=aws_ec2.Peer.ipv4(cidr_ip='0.0.0.0/0'), connection=aws_ec2.Port.tcp(port=443)) if private_security_group is None: private_security_group = aws_ec2.SecurityGroup( self, 'PrivateSecurityGroup', vpc=vpc, allow_all_outbound=True) public_subnet_cidr_blocks = Utils.get_subnet_cidr_blocks( public_subnets) # Create an ingress rule for each of the NLB's subnet's CIDR ranges and add the rules to the ECS service's # security group. This will allow requests from the NLB to go into the ECS service. This allow inbound # traffic from public subnets. for cidr_block in public_subnet_cidr_blocks: private_security_group.add_ingress_rule( peer=aws_ec2.Peer.ipv4(cidr_ip=cidr_block), connection=aws_ec2.Port.tcp(port=container_port)) if fargate_cluster is None: fargate_cluster = aws_ecs.Cluster( self, 'FargateCluster', ) task_def = aws_ecs.FargateTaskDefinition( self, 'TaskDefinition', cpu=task_definition_cpu, memory_limit_mib=task_definition_memory_limit_mib, task_role=self.role, execution_role=self.role) container = aws_ecs.ContainerDefinition( self, 'Container', image=aws_ecs.ContainerImage.from_registry(name=docker_image_name), task_definition=task_def, logging=aws_ecs.AwsLogDriver(stream_prefix='/ecs')) container.add_port_mappings( aws_ecs.PortMapping(container_port=container_port, protocol=aws_ec2.Protocol.TCP)) ecs_service = aws_ecs.FargateService( self, 'FargateService', cluster=fargate_cluster, task_definition=task_def, vpc_subnets=aws_ec2.SubnetSelection(subnets=private_subnets), security_group=private_security_group, desired_count=desired_container_count) target_group = aws_elasticloadbalancingv2.NetworkTargetGroup( self, 'TargetGroup', port=80, # Health check occurs over HTTP health_check=aws_elasticloadbalancingv2.HealthCheck( protocol=aws_elasticloadbalancingv2.Protocol.TCP), targets=[ecs_service], vpc=vpc) nlb = aws_elasticloadbalancingv2.NetworkLoadBalancer( self, 'NetworkLoadBalancer', vpc=vpc, internet_facing=False, vpc_subnets=aws_ec2.SubnetSelection(subnets=public_subnets), ) nlb.add_listener( id='Listener', port=80, # HTTP listener default_target_groups=[target_group]) # nlb.log_access_logs( # todo: add this later when you have time to research the correct bucket policy. # bucket=aws_s3.Bucket( # self, 'LoadBalancerLogBucket', # bucket_name='load-balancer-logs', # public_read_access=False, # block_public_access=aws_s3.BlockPublicAccess( # block_public_policy=True, # restrict_public_buckets=True # ) # ) # ) # Dependencies ecs_service.node.add_dependency(nlb) # API Gateway rest_api = aws_apigateway.RestApi(self, stack_name) resource = rest_api.root.add_resource( path_part='{proxy+}', default_method_options=aws_apigateway.MethodOptions( request_parameters={'method.request.path.proxy': True})) token_authorizer = None if authorizer_lambda_arn and authorizer_lambda_role_arn: token_authorizer = aws_apigateway.TokenAuthorizer( #todo: make this a parameter? self, 'JwtTokenAuthorizer', results_cache_ttl=core.Duration.minutes(5), identity_source='method.request.header.Authorization', assume_role=aws_iam.Role.from_role_arn( self, 'AuthorizerLambdaInvokationRole', role_arn=authorizer_lambda_role_arn), handler=aws_lambda.Function.from_function_arn( self, 'AuthorizerLambda', function_arn=authorizer_lambda_arn)) resource.add_method( http_method='ANY', authorization_type=aws_apigateway.AuthorizationType.CUSTOM, authorizer=token_authorizer, integration=aws_apigateway.HttpIntegration( url=f'http://{nlb.load_balancer_dns_name}/{{proxy}}', http_method='ANY', proxy=True, options=aws_apigateway.IntegrationOptions( request_parameters={ 'integration.request.path.proxy': 'method.request.path.proxy' }, connection_type=aws_apigateway.ConnectionType.VPC_LINK, vpc_link=aws_apigateway.VpcLink( self, 'VpcLink', description= f'API Gateway VPC Link to internal NLB for {stack_name}', vpc_link_name=stack_name, targets=[nlb]))))
def __init__(self, app: core.App, id: str, **kwargs) -> None: super().__init__(app, id, **kwargs) # Create an S3 bucket where we will store the UDP logs udp_logs_bucket = s3.Bucket(self, "UDPLogsBucket") # Create a VPC using CDK's default VPC architecture. See README for diagram. vpc = ec2.Vpc(self, "VPC") workers_asg = autoscaling.AutoScalingGroup( self, "ASG", vpc=vpc, vpc_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.PUBLIC if PUBLIC_ACCESS else ec2. SubnetType.PRIVATE), instance_type=ec2.InstanceType("t2.small"), machine_image=ec2.AmazonLinuxImage(), desired_capacity=1 if PUBLIC_ACCESS else 2) # Create a security group that controls access to the NLB > Instances # It is important to note that NLB security works different than Classic ELB or ALB # NLBs do not attach security groups, security controls are managed on the instances themselves! allow_udp_sg = ec2.SecurityGroup( self, "AllowUdpSG", vpc=vpc, description="Allow UDP listener through Network Load Balancer", allow_all_outbound= False, # The default SG for the ASG is already allowing all outbound ) # Add rules to the security group for internal access, and the configured NLB_PUBLIC_ACCESS for ipv4 in [NLB_ACCESS_IPV4, vpc.vpc_cidr_block]: allow_udp_sg.add_ingress_rule( peer=ec2.Peer.ipv4(ipv4), connection=ec2.Port( string_representation=str(UDP_LISTEN_PORT), protocol=ec2.Protocol.UDP, from_port=UDP_LISTEN_PORT, to_port=UDP_LISTEN_PORT, ), ) workers_asg.add_security_group(allow_udp_sg) # Add the td-agent to our worker instances using user-data scripts # Example of using an external function to modify a resource install_td_agent_user_data(workers_asg, udp_logs_bucket, UDP_LISTEN_PORT) # Attach the SSM Managed policy for managing the instance through SSM Sessions # This allows us to ditch bastions hosts! # This policy also is granting us S3 access for logging, if you remove it you will need to add an IAM role # with access to the s3 bucket. managed_policy = iam.ManagedPolicy().from_aws_managed_policy_name( managed_policy_name="service-role/AmazonEC2RoleforSSM") workers_asg.role.add_managed_policy(managed_policy) # Create a network load balancer for accepting our UDP logs # This will create the required EIPs when configured for Public Access lb = elbv2.NetworkLoadBalancer(self, "LB", vpc=vpc, cross_zone_enabled=True, internet_facing=PUBLIC_ACCESS) # Create a listener & target group for our NLB. # It is important to note that the TCP protocol will be overriden to UDP shortly listener = lb.add_listener("Listener", port=UDP_LISTEN_PORT, protocol=elbv2.Protocol.TCP) target_group = elbv2.NetworkTargetGroup(self, vpc=vpc, id="Target", port=UDP_LISTEN_PORT, targets=[workers_asg]) listener.add_target_groups("TargetGroupUdp", target_group) # Workaround for lack of UDP NLB support in CDK. # As of writing this CDK does not have support for UDP NLBs # TODO - Remove these overrides when support is added # https://github.com/awslabs/aws-cdk/issues/3107 listener.node.find_child("Resource").add_property_override( "Protocol", "UDP") target_group.node.find_child("Resource").add_property_override( "Protocol", "UDP")
def __init__(self, scope: core.Construct, id: str, pub_hosted_zone: object, **kwargs) -> None: super().__init__(scope, id, **kwargs) sts = boto3.client("sts") deploy_account_id = sts.get_caller_identity()["Account"] deploy_region = sts.meta.region_name #TODO ADD an ASG vpc = ec2.Vpc( self, "iais-public", nat_gateways=0, subnet_configuration=[ ec2.SubnetConfiguration(name="public", subnet_type=ec2.SubnetType.PUBLIC), ec2.SubnetConfiguration(name="private", subnet_type=ec2.SubnetType.ISOLATED), ]) sg = ec2.SecurityGroup(self, f"iais-sg-{str}", vpc=vpc, allow_all_outbound=True, description="For HTTPS access.") sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(443)) self.sg = sg self.vpc = vpc instance_ami = ec2.MachineImage.latest_amazon_linux( generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, edition=ec2.AmazonLinuxEdition.STANDARD, virtualization=ec2.AmazonLinuxVirt.HVM, storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE) role = iam.Role(self, "iais-web-server-roles", assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) role.add_managed_policy( iam.ManagedPolicy.from_aws_managed_policy_name( "service-role/AmazonEC2RoleforSSM")) role.add_managed_policy( iam.ManagedPolicy.from_aws_managed_policy_name( "AmazonRekognitionFullAccess")) instance = ec2.Instance(self, "iais-web-server-instance", instance_type=ec2.InstanceType("t2.micro"), machine_image=instance_ami, vpc=vpc, role=role, security_group=sg) instance_target = targets.InstanceIdTarget( instance_id=instance.instance_id, port=443) lb = elbv2.NetworkLoadBalancer(self, f"iais-lb-{str}", vpc=vpc, internet_facing=True) lb_tg = elbv2.NetworkTargetGroup(self, vpc=vpc, id=f"iais-tg-{str}", port=443, targets=[instance_target]) lb_listener = lb.add_listener(f"iais-listener-{str}", port=443, default_target_groups=[lb_tg]) r53.ARecord(self, "AliasRecord", zone=pub_hosted_zone, target=r53.RecordTarget.from_alias( r53t.LoadBalancerTarget(lb))) r53.ARecord(self, "AliasRecordWww", zone=pub_hosted_zone, record_name="www.imageaisearch.com", target=r53.RecordTarget.from_alias( r53t.LoadBalancerTarget(lb))) secrets_man_policy = iam.Policy( self, "iais", roles=[role], policy_name="iais-web-server-secrets-manager", statements=[ iam.PolicyStatement( actions=[ "secretsmanager:GetResourcePolicy", "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecretVersionIds" ], resources=[ f"arn:aws:secretsmanager:{deploy_region}:{deploy_account_id}:secret:DJANGO_SECRET_KEY-mHAOZX" ]) ]) secrets_man_policy.attach_to_role(role)
def __init__(self, stack: core.Stack, VPC: ec2.Vpc) -> None: bastionSG = ec2.SecurityGroup( stack, "BastionSecurityGroup", vpc=VPC, description="Allow ssh access to the bastion host", allow_all_outbound=True) bastionSG.add_ingress_rule(ec2.Peer.any_ipv4(), ec2.Port.tcp(22), '' "allow ssh access from the world") bastionSG.add_ingress_rule(ec2.Peer.any_ipv4(), ec2.Port.tcp_range(8081, 8083), "allow http(s) access from the world") userData = ec2.UserData.for_linux() userData.add_commands(""" set -v apt update apt install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common gdebi-core ec2-instance-connect curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" apt install -y docker-ce docker-ce-cli containerd.io usermod -a -G docker ubuntu curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose echo 'version: "3.8"' > /home/ubuntu/docker-compose.yaml echo 'services:' >> /home/ubuntu/docker-compose.yaml echo ' web:' >> /home/ubuntu/docker-compose.yaml echo ' image: %s/mtls-demo-web' >> /home/ubuntu/docker-compose.yaml echo ' network_mode: "service:proxy"' >> /home/ubuntu/docker-compose.yaml echo ' depends_on:' >> /home/ubuntu/docker-compose.yaml echo ' - proxy' >> /home/ubuntu/docker-compose.yaml echo ' restart: unless-stopped' >> /home/ubuntu/docker-compose.yaml echo ' proxy:' >> /home/ubuntu/docker-compose.yaml echo ' image: %s/mtls-demo-proxy' >> /home/ubuntu/docker-compose.yaml echo ' ports:' >> /home/ubuntu/docker-compose.yaml echo ' - "9901:9901"' >> /home/ubuntu/docker-compose.yaml echo ' - "8081:8081"' >> /home/ubuntu/docker-compose.yaml echo ' - "8082:8082"' >> /home/ubuntu/docker-compose.yaml echo ' - "8083:8083"' >> /home/ubuntu/docker-compose.yaml echo ' - "8084:8084"' >> /home/ubuntu/docker-compose.yaml echo ' restart: unless-stopped' >> /home/ubuntu/docker-compose.yaml echo 'networks:' >> /home/ubuntu/docker-compose.yaml echo ' public:' >> /home/ubuntu/docker-compose.yaml echo ' external: true' >> /home/ubuntu/docker-compose.yaml /usr/local/bin/docker-compose -f /home/ubuntu/docker-compose.yaml up """ % (stack.node.try_get_context("prefix"), stack.node.try_get_context("prefix"))) # no key installed, use # # aws ec2-instance-connect send-ssh-public-key # # to install a temporary key and gain access to the vm bastion = ec2.Instance( stack, "Bastion", instance_type=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machine_image=ec2.MachineImage.lookup( name="ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*" ), vpc=VPC, security_group=bastionSG, vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC), user_data=userData) core.CfnOutput(stack, "BastionIP", value=bastion.instance_public_ip) core.CfnOutput(stack, "BastionInstanceID", value=bastion.instance_id) core.CfnOutput( stack, "BastionSendSSHKeyCommand", value= "aws ec2-instance-connect send-ssh-public-key --instance-id %s --instance-os-user ubuntu --availability-zone %s --ssh-public-key file://~/.ssh/id_rsa.pub" % (bastion.instance_id, bastion.instance_availability_zone)) nlb = elbv2.NetworkLoadBalancer( stack, "NLB", vpc=VPC, internet_facing=True, vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC)) core.CfnOutput(stack, "NLBAddress", value=nlb.load_balancer_dns_name) core.Tag.add(nlb, "stack", "ec2", apply_to_launched_instances=True) nlb.add_listener( "HTTP", port=80, default_target_groups=[ elbv2.NetworkTargetGroup( stack, "HTTPDefaultTargetGroup", port=8081, vpc=VPC, targets=[elbv2.InstanceTarget(bastion.instance_id, 8081)]) ]) nlb.add_listener( "mTLS", port=443, default_target_groups=[ elbv2.NetworkTargetGroup( stack, "mTLSDefaultTargetGroup", port=8083, vpc=VPC, targets=[elbv2.InstanceTarget(bastion.instance_id, 8083)]) ])