Ejemplo n.º 1
0
    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")
Ejemplo n.º 2
0
    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")
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)])
            ])