class CdkNowIGetIt(cdk.Construct):
    def __init__(self, scope: cdk.Stack, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Create the VPC resource.
        self._vpc = Vpc(self, "MyVPC", cidr="10.10.0.0/16")
        # Create a Security Group within the VPC that is used to allow
        # management traffic from designated jump hosts.
        self._sg = SecurityGroup(
            self,
            "MySG",
            vpc=self._vpc,
            allow_all_outbound=False,
            description="Management traffic from jump boxes",
            security_group_name="jumpbox-mgmt-traffic")

        # Add ingress rules to the Security Group for the jump host
        # 10.255.0.10 to TCP/22 and TCP/3389.
        self._sg.add_ingress_rule(peer=Peer.ipv4("10.255.0.10/32"),
                                  connection=Port(
                                      protocol=Protocol.TCP,
                                      string_representation="host1",
                                      from_port=22,
                                      to_port=22))
        self._sg.add_ingress_rule(peer=Peer.ipv4("10.255.0.10/32"),
                                  connection=Port(
                                      protocol=Protocol.TCP,
                                      string_representation="host1",
                                      from_port=3389,
                                      to_port=3389))
class CdkNowIGetIt(cdk.Construct):
    def __init__(self, scope: cdk.Stack, construct_id: str, vpc_cidr: str,
                 jump_host: str, mgmt_ports: list, subnet_len: int,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # args:
        # - vpc_cidr (str): The CIDR range for the VPC.
        # - jump_host (str): An optional IP address for the jump host. If this
        #                    is not specified, te Security Group will not be
        #                    created.
        # - mgmt_ports (list): A list of TCP ports which the jump host is
        #                      allowed to connect to.
        # - subnet_len (int): The prefix length for subnet CIDR addresses.

        # Create the VPC resource. The VPC does not have an internet gateway,
        # or NAT gateway. Subnets are created in 2 zones.
        subnets = [
            SubnetConfiguration(name="MyVPC-Private",
                                subnet_type=SubnetType.ISOLATED,
                                cidr_mask=subnet_len)
        ]
        self._vpc = Vpc(self,
                        "MyVPC",
                        cidr=vpc_cidr,
                        max_azs=2,
                        nat_gateways=None,
                        subnet_configuration=subnets)

        # Security Group only created if the jump host parameter was
        # specified.
        if jump_host is not None and len(jump_host) > 0:
            self.create_sg(jump_host, mgmt_ports)

    def create_sg(self, jump_host, mgmt_ports):
        # Create a Security Group within the VPC that is used to allow
        # management traffic from designated jump hosts.
        self._sg = SecurityGroup(
            self,
            "MySG",
            vpc=self._vpc,
            allow_all_outbound=False,
            description="Management traffic from jump boxes",
            security_group_name="jumpbox-mgmt-traffic")

        # Add ingress rules to the Security Group for the jump host
        # TCP/22 and TCP/3389.
        for port in mgmt_ports:
            self._sg.add_ingress_rule(peer=Peer.ipv4(jump_host),
                                      connection=Port(
                                          protocol=Protocol.TCP,
                                          string_representation="jump",
                                          from_port=int(port),
                                          to_port=int(port)))
Esempio n. 3
0
 def _add_default_rules(self, sg: ec2.SecurityGroup, vpc: ec2.Vpc):
     """ Adds default rules to given security group.
     TODO: should create a high level construct to hide those rules.
     TODO: need to review those rules because we probably do not need all of them.
     Current default rules are:
         - All IMCP, TCP, and UDP from within the given VPC.
         - All TCP traffic from MetService network.
     """
     # Allow traffic coming from internal MetService network
     # TODO: we should probably restrict this rule to port 22 (SSH)
     sg.add_ingress_rule(
         peer=ec2.Peer.ipv4(self.config["metservice_cidr"]),
         connection=ec2.Port.all_tcp(),
         description="Allow connections from MetService network",
     )
     sg.add_ingress_rule(
         peer=ec2.Peer.ipv4(vpc.vpc_cidr_block),
         connection=ec2.Port.all_tcp(),
         description="Allow all TCP traffic from within the VPC",
     )
     sg.add_ingress_rule(
         peer=ec2.Peer.ipv4(vpc.vpc_cidr_block),
         connection=ec2.Port.all_udp(),
         description="Allow all UDP traffic from within the VPC ",
     )
     sg.add_ingress_rule(
         peer=ec2.Peer.ipv4(vpc.vpc_cidr_block),
         connection=ec2.Port.all_icmp(),
         description="Allow all ICMP traffic from within the VPC ",
     )
Esempio n. 4
0
 def _set_common_ingress_rules(
         primary: ec2.SecurityGroup,
         secondary: ec2.SecurityGroup) -> ec2.SecurityGroup:
     primary.add_ingress_rule(primary, ec2.Port.tcp_range(0, 65535))
     primary.add_ingress_rule(primary, ec2.Port.udp_range(0, 65535))
     primary.add_ingress_rule(primary, ec2.Port.icmp_type(-1))
     primary.add_ingress_rule(secondary, ec2.Port.tcp_range(0, 65535))
     primary.add_ingress_rule(secondary, ec2.Port.udp_range(0, 65535))
     primary.add_ingress_rule(secondary, ec2.Port.icmp_type(-1))
     return primary
Esempio n. 5
0
 def get_web_security_group(self, vpc):
     security_group = SecurityGroup(
         self._stack,
         'obm_web',
         vpc=vpc,
         allow_all_outbound=True,
     )
     for port_number in [SSH_PORT, HTTP_PORT, HTTPS_PORT]:
         port = Port(from_port=port_number,
                     to_port=port_number,
                     protocol=Protocol.TCP,
                     string_representation=f"Port {port_number}")
         security_group.add_ingress_rule(peer=Peer.any_ipv4(),
                                         connection=port)
         security_group.add_ingress_rule(peer=Peer.any_ipv6(),
                                         connection=port)
     self._tag_it(security_group)
     return security_group
Esempio n. 6
0
class CdkNowIGetIt(cdk.Construct):
    def __init__(self, scope: cdk.Stack, construct_id: str, vpc_cidr: str,
                 jump_host: str, mgmt_ports: list, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # args:
        # - vpc_cidr (str): The CIDR range for the VPC.
        # - jump_host (str): An optional IP address for the jump host. If this
        #                    is not specified, the Security Group will not be
        #                    created.
        # - mgmt_ports (list): A list of TCP ports which the jump host is
        #                      allowed to connect to.

        # Create the VPC resource with the given CIDR range.
        self._vpc = Vpc(self, "MyVPC", cidr=vpc_cidr)

        # Security Group only created if the jump host parameter was
        # specified.
        if jump_host is not None and len(jump_host) > 0:
            self.create_sg(jump_host, mgmt_ports)

    def create_sg(self, jump_host, mgmt_ports):
        # Create a Security Group within the VPC that is used to allow
        # management traffic from designated jump hosts.
        self._sg = SecurityGroup(
            self,
            "MySG",
            vpc=self._vpc,
            allow_all_outbound=False,
            description="Management traffic from jump boxes",
            security_group_name="jumpbox-mgmt-traffic")

        # Add ingress rules to the Security Group
        for port in mgmt_ports:
            self._sg.add_ingress_rule(peer=Peer.ipv4(jump_host),
                                      connection=Port(
                                          protocol=Protocol.TCP,
                                          string_representation="jump",
                                          from_port=int(port),
                                          to_port=int(port)))
Esempio n. 7
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]))))
Esempio n. 8
0
    def __init__(self, scope: core.Construct, construct_id: str,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        role = iam.Role(
            scope=self,
            id='AwsCustomResourceRole',
            assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'))
        role.add_to_policy(
            iam.PolicyStatement(actions=['iam:PassRole'], resources=['*']))

        my_custom_resource = cr.AwsCustomResource(
            scope=self,
            id='MyAwsCustomResource',
            role=role,
            policy=cr.AwsCustomResourcePolicy.from_sdk_calls(resources=['*']),
            on_create=cr.AwsSdkCall(
                action='listBuckets',
                service='s3',
                physical_resource_id=cr.PhysicalResourceId.of('BucketsList'),
            ))

        vpc = VPCConstruct(self, id_='test-vpc', num_of_azs=2)
        security_group = SecurityGroup(
            self,
            id='test-security-group',
            vpc=vpc,
            security_group_name='test-security-group')
        security_group.add_ingress_rule(connection=Port.tcp(443),
                                        peer=vpc.lambdas_sg)

        domain = es.Domain(
            scope=self,
            id='Domain',
            version=es.ElasticsearchVersion.V7_9,
            domain_name="es-domain-name",
            enable_version_upgrade=False,
            enforce_https=True,
            fine_grained_access_control=None,
            node_to_node_encryption=True,
            tls_security_policy=es.TLSSecurityPolicy.TLS_1_0,
            logging=es.LoggingOptions(
                app_log_enabled=True,
                slow_index_log_enabled=True,
                slow_search_log_enabled=True,
                app_log_group=LogGroup(
                    scope=self,
                    id="app-log-group",
                    log_group_name=f'/aws/aes/domains/esdomain/app-log-group',
                    removal_policy=core.RemovalPolicy.DESTROY),
                slow_index_log_group=LogGroup(
                    scope=self,
                    id="slow-index-log-group",
                    log_group_name=
                    f'/aws/aes/domains/esdomain/slow-index-log-group',
                    removal_policy=core.RemovalPolicy.DESTROY),
                slow_search_log_group=LogGroup(
                    scope=self,
                    id="slow-search-log-group",
                    log_group_name=
                    f'/aws/aes/domains/esdomain/slow-search-log-group',
                    removal_policy=core.RemovalPolicy.DESTROY)),
            removal_policy=core.RemovalPolicy.DESTROY,
            zone_awareness=es.ZoneAwarenessConfig(availability_zone_count=2,
                                                  enabled=True),
            vpc_options=es.VpcOptions(
                security_groups=[security_group],
                subnets=vpc.audit_vpc.select_subnets(
                    subnet_group_name=PRIVATE_SUBNET_GROUP).subnets))
Esempio n. 9
0
    def __init__(self, scope: cdk.Construct, construct_id: str, config, vpc: IVpc, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        self.neo4j_user_secret = Secret(self,'secretsmanager-secret-neo4j-user',
            secret_name=NEO4J_USER_SECRET_NAME
        )
       
        neo4j_server_instance_role = Role(self,'iam-role-neo4j-server-instance',
            assumed_by=ServicePrincipal('ec2.amazonaws.com'),
            managed_policies=[
                ManagedPolicy.from_aws_managed_policy_name('AmazonSSMManagedInstanceCore'), # Use SSM Session Manager rather than straight ssh
                ManagedPolicy.from_aws_managed_policy_name('CloudWatchAgentServerPolicy')
            ],
            inline_policies={
                "work-with-tags": PolicyDocument(
                    statements=[
                        PolicyStatement(
                            actions=[
                                'ec2:CreateTags',
                                'ec2:Describe*',
                                'elasticloadbalancing:Describe*',
                                'cloudwatch:ListMetrics',
                                'cloudwatch:GetMetricStatistics',
                                'cloudwatch:Describe*',
                                'autoscaling:Describe*',
                            ],
                            resources=["*"]
                        )
                    ]
                ),
                "access-neo4j-user-secret": PolicyDocument(
                    statements=[
                        PolicyStatement(
                            actions=['secretsmanager:GetSecretValue'],
                            resources=[self.neo4j_user_secret.secret_arn]
                        )
                    ]
                )
            }
        )

        instance_security_group = SecurityGroup(self, "ec2-sg-neo4j-server-instance",
            description="Altimeter Neo4j Server Instance",
            vpc=vpc
        )

        instance_security_group.add_ingress_rule(Peer.ipv4("0.0.0.0/0"), Port.tcp(7687), 'Bolt from ANYWHERE') # TESTING
        # instance_security_group.add_ingress_rule(Peer.ipv4("0.0.0.0/0"), Port.tcp(7473), 'Bolt from ANYWHERE') # TESTING

        # Prepare userdata script
        with open("./resources/neo4j-server-instance-userdata.sh", "r") as f:
            userdata_content = f.read()
        userdata_content = userdata_content.replace("[[NEO4J_USER_SECRET_NAME]]",NEO4J_USER_SECRET_NAME)
        user_data = UserData.for_linux()
        user_data.add_commands(userdata_content)

        instance_type = InstanceType.of(InstanceClass.BURSTABLE2, InstanceSize.MEDIUM)

        self.instance = Instance(self, 'ec2-instance-neo4j-server-instance',
            instance_name="instance-altimeter--neo4j-community-standalone-server",
            machine_image=MachineImage.generic_linux(
                ami_map={
                    "eu-west-1": "ami-00c8631d384ad7c53"
                }
            ),
            instance_type=instance_type,
            role=neo4j_server_instance_role,
            vpc=vpc,
            # vpc_subnets=SubnetSelection(subnets=vpc.select_subnets(subnet_group_name='Private').subnets),
            vpc_subnets=SubnetSelection(subnets=vpc.select_subnets(subnet_group_name='Public').subnets),
            security_group=instance_security_group,
            user_data=user_data,
            block_devices=[
                BlockDevice(
                    device_name="/dev/sda1",
                    volume=BlockDeviceVolume.ebs(
                        volume_size=10,
                        volume_type=EbsDeviceVolumeType.GP2,
                        encrypted=True, # Just encrypt
                        delete_on_termination=True
                    )                    
                ),
                BlockDevice(
                    device_name="/dev/sdb",
                    volume=BlockDeviceVolume.ebs(
                        volume_size=20, # TODO: Check size requirements
                        volume_type=EbsDeviceVolumeType.GP2,
                        encrypted=True,
                        delete_on_termination=True # ASSUMPTION: NO 'primary' data, only altimeter results.
                    )                    
                )
            ]
        )

        cdk.Tags.of(self.instance).add("neo4j_mode", "SINGLE")
        cdk.Tags.of(self.instance).add("dbms_mode", "SINGLE")