def set_prometheus_endpoint(self): """ Set a Managed Prometheus endpoint with full access and add it to private routes """ sg_res = t_ec2.SecurityGroup( title=alphanum(f"{self.name}ApsVpcEndpointSG"), VpcId=Ref(self.vpc), GroupDescription="Used by Prometheus VPC Endpoint", SecurityGroupIngress=[ t_ec2.SecurityGroupRule(IpProtocol="tcp", FromPort="443", ToPort="443", CidrIp="0.0.0.0/0") ], ) self._r[sg_res.title] = sg_res res = t_ec2.VPCEndpoint( title=alphanum(f"{self.name}ApsVpcEndpoint"), VpcId=Ref(self.vpc), ServiceName=f"com.amazonaws.{self.region}.aps-workspaces", SubnetIds=[Ref(subnet) for subnet in self.gateway_subnets], SecurityGroupIds=[Ref(self._r[sg_res.title])], VpcEndpointType="Interface", ) self._r[res.title] = res
def create_vpc_endpoint(self): self.create_resource( ec2.VPCEndpoint( 'S3VPCEndpoint', RouteTableIds=[Ref(prt) for prt in self.PRIVATE_ROUTE_TABLES], ServiceName=AMAZON_S3_VPC_ENDPOINT, VpcId=Ref(self.vpc)))
def create_dynamo_endpoint(self, route_table_ids): t = self.template variables = self.get_variables() if variables["CreateDynamoEndpoint"]: t.add_resource( ec2.VPCEndpoint( "dynamoVpcEndpoint", RouteTableIds=route_table_ids, VpcId=VPC_ID, ServiceName=Sub("com.amazonaws.${AWS::Region}.dynamodb"), ))
def set_s3_endpoint(self): """Set an S3 endpoint with full access and add it to private routes""" res = t_ec2.VPCEndpoint( title=alphanum(f"{self.name}S3EndpointGateway"), VpcId=Ref(self.vpc), ServiceName=f"com.amazonaws.{self.region}.s3", RouteTableIds=[ Ref(route_table) for route_table in self.natted_route_tables ], ) if self.public_route_table is not None: res.RouteTableIds.append(Ref(self.public_route_table)) self._r[res.title] = res
def s3_vpc_endpoint(self) -> ec2.VPCEndPoint: """Return S3 VPC Endpoint. Needed to retrieve images as ECR store images on S3. """ return ec2.VPCEndpoint( name_to_id(f"{self.name}S3Endpoint"), PolicyDocument=self.s3_endpoint_policy_document.as_dict, RouteTableIds=[Ref(self.s3_route_table)], ServiceName=f"com.amazonaws.{self.region}.s3", VpcEndpointType="Gateway", VpcId=Ref(self.vpc), )
def cloudwatch_logs_vpc_endpoint(self) -> ec2.VPCEndPoint: """Return Cloudwatch VPC Endpoint. Needed for ecs task to send logs to cloudwatch. """ return ec2.VPCEndpoint( name_to_id(f"{self.name}CloudwatchLogsEndpoint"), PrivateDnsEnabled="true", SecurityGroupIds=[Ref(self.security_group)], ServiceName=f"com.amazonaws.{self.region}.logs", SubnetIds=[Ref(self.subnet)], VpcEndpointType="Interface", VpcId=Ref(self.vpc), )
def sts_vpc_endpoint(self) -> ec2.VPCEndPoint: """Return STS VPC Endpoint. Needed to initialize session from the container. """ return ec2.VPCEndpoint( name_to_id(f"{self.name}STSEndpoint"), PrivateDnsEnabled="true", SecurityGroupIds=[Ref(self.security_group)], ServiceName=f"com.amazonaws.{self.region}.sts", SubnetIds=[Ref(self.subnet)], VpcEndpointType="Interface", VpcId=Ref(self.vpc), )
def s3_vpc_endpoint(self) -> ec2.VPCEndPoint: """Return S3 VPC Endpoint. Note that is endpoint is also needed when using ECR as ECR stores images on S3. """ assert self.s3_endpoint_policy_document is not None return ec2.VPCEndpoint( name_to_id(f"{self.name}S3Endpoint"), PolicyDocument=self.s3_endpoint_policy_document.as_dict, RouteTableIds=[Ref(self.s3_route_table)], ServiceName=f"com.amazonaws.{self.region}.s3", VpcEndpointType="Gateway", VpcId=Ref(self.vpc), )
def ecr_api_vpc_endpoint(self) -> ec2.VPCEndPoint: """Return ECR api VPC Endpoint. Needed to retrieve images from ECR service. """ return ec2.VPCEndpoint( name_to_id(f"{self.name}EcrApiEndpoint"), PolicyDocument=self.ecr_endpoints_policy_document.as_dict, PrivateDnsEnabled="true", SecurityGroupIds=[Ref(self.security_group)], ServiceName=f"com.amazonaws.{self.region}.ecr.api", SubnetIds=[Ref(self.subnet)], VpcEndpointType="Interface", VpcId=Ref(self.vpc), )
def interface_vpc_endpoints(self) -> list[ec2.VPCEndpoint]: """Return interface endpoints.""" endpoints = [] for service_name, pd in self.interface_endpoints: if pd is not None: opt_params = {"PolicyDocument": pd.as_dict} else: opt_params = {} endpoints.append( ec2.VPCEndpoint( name_to_id(f"{service_name}Endpoint"), PrivateDnsEnabled="true", SecurityGroupIds=[Ref(self.security_group)], ServiceName=f"com.amazonaws.{self.region}.{service_name}", SubnetIds=[Ref(self.subnet)], VpcEndpointType="Interface", VpcId=Ref(self.vpc), **opt_params, )) return endpoints
def __init__(self): super(VPC, self).__init__() self.vpc = ec2.VPC( "VPC", CidrBlock="172.1.0.0/16", InstanceTenancy="default", EnableDnsSupport=True, EnableDnsHostnames=True, Tags=Tags(Name=Ref("AWS::StackName")), ) self.internet_gateway = ec2.InternetGateway( "InternetGateway", Tags=Tags(Name=Join( "", [Ref("AWS::StackName"), "-internet-gateway"]), ), ) self.internet_gateway_attachment = ec2.VPCGatewayAttachment( "InternetGatewayAttachment", InternetGatewayId=Ref(self.internet_gateway), VpcId=Ref(self.vpc), ) self.public_route_table = ec2.RouteTable( "PublicRouteTable", VpcId=Ref(self.vpc), Tags=Tags(Name=Join( "-", [Ref("AWS::StackName"), "public-route-table"]), ), ) self.private_route_table = ec2.RouteTable( "PrivateRouteTable", VpcId=Ref(self.vpc), Tags=Tags(Name=Join( "-", [Ref("AWS::StackName"), "private-route-table"]), ), ) self.vpc_s3_endpoint = ec2.VPCEndpoint( "VPCS3Endpoint", ServiceName=Join( "", ["com.amazonaws.", Ref("AWS::Region"), ".s3"]), VpcId=Ref(self.vpc), RouteTableIds=[ Ref(self.public_route_table), Ref(self.private_route_table) ], ) self.route_to_internet = ec2.Route( "RouteToInternet", DestinationCidrBlock="0.0.0.0/0", GatewayId=Ref(self.internet_gateway), RouteTableId=Ref(self.public_route_table), DependsOn=self.internet_gateway_attachment.title, ) # private subnets self.private_subnet_1 = ec2.Subnet( "PrivateSubnet1", AvailabilityZone=Select(0, GetAZs()), CidrBlock="172.1.1.0/24", MapPublicIpOnLaunch=False, Tags=Tags(Name=Join( "", [Ref("AWS::StackName"), "-private-subnet-1"]), ), VpcId=Ref(self.vpc), ) self.private_subnet_1_route_table_association = ec2.SubnetRouteTableAssociation( "PrivateSubnet1RouteTableAssociation", RouteTableId=Ref(self.private_route_table), SubnetId=Ref(self.private_subnet_1), ) self.private_subnet_2 = ec2.Subnet( "PrivateSubnet2", AvailabilityZone=Select(1, GetAZs()), CidrBlock="172.1.2.0/24", MapPublicIpOnLaunch=False, Tags=Tags(Name=Join( "", [Ref("AWS::StackName"), "-private-subnet-2"]), ), VpcId=Ref(self.vpc), ) self.private_subnet_2_route_table_association = ec2.SubnetRouteTableAssociation( "PrivateSubnet2RouteTableAssociation", RouteTableId=Ref(self.private_route_table), SubnetId=Ref(self.private_subnet_2), ) self.private_network_aCL = ec2.NetworkAcl( "PrivateNetworkACL", VpcId=Ref(self.vpc), Tags=Tags(Name=Join("", [Ref("AWS::StackName"), "-private-nacl"]), ), ) self.private_subnet_1_network_acl_association = ec2.SubnetNetworkAclAssociation( "PrivateSubnet1NetworkAclAssociation", SubnetId=Ref(self.private_subnet_1), NetworkAclId=Ref(self.private_network_aCL), ) self.private_subnet_2_network_acl_association = ec2.SubnetNetworkAclAssociation( "PrivateSubnet2NetworkAclAssociation", SubnetId=Ref(self.private_subnet_2), NetworkAclId=Ref(self.private_network_aCL), ) self.private_network_acl_entry_in = ec2.NetworkAclEntry( "PrivateNetworkAclEntryIn", CidrBlock="172.1.0.0/16", Egress=False, NetworkAclId=Ref(self.private_network_aCL), Protocol=-1, RuleAction="allow", RuleNumber=200, ) self.private_network_acl_entry_out = ec2.NetworkAclEntry( "PrivateNetworkAclEntryOut", CidrBlock="172.1.0.0/16", Egress=True, NetworkAclId=Ref(self.private_network_aCL), Protocol=-1, RuleAction="allow", RuleNumber=200, ) # public subnets self.public_subnet_1 = ec2.Subnet( "PublicSubnet1", AvailabilityZone=Select(0, GetAZs()), CidrBlock="172.1.128.0/24", MapPublicIpOnLaunch=True, Tags=Tags(Name=Join( "", [Ref("AWS::StackName"), "-public-subnet-1"]), ), VpcId=Ref(self.vpc), ) self.public_subnet_1_route_table_association = ec2.SubnetRouteTableAssociation( "PublicSubnet1RouteTableAssociation", RouteTableId=Ref(self.public_route_table), SubnetId=Ref(self.public_subnet_1), ) self.public_subnet_2 = ec2.Subnet( "PublicSubnet2", AvailabilityZone=Select(1, GetAZs()), CidrBlock="172.1.129.0/24", MapPublicIpOnLaunch=True, Tags=Tags(Name=Join( "", [Ref("AWS::StackName"), "-public-subnet-2"]), ), VpcId=Ref(self.vpc), ) self.public_subnet_2_route_table_association = ec2.SubnetRouteTableAssociation( "PublicSubnet2RouteTableAssociation", RouteTableId=Ref(self.public_route_table), SubnetId=Ref(self.public_subnet_2), )
from troposphere import ec2, GetAtt, Join, Ref from stacks.endpoints.resources.sns_endpoint_security_group import ( sns_endpoint_security_group, ) from stacks.parameters import subnet_ids, vpc_id sns_endpoint = ec2.VPCEndpoint( "SNSEndpoint", SecurityGroupIds=[GetAtt(sns_endpoint_security_group, "GroupId")], PrivateDnsEnabled=True, ServiceName=Join("", ["com.amazonaws.", { "Ref": "AWS::Region" }, ".sns"]), SubnetIds=Ref(subnet_ids), VpcEndpointType="Interface", VpcId=Ref(vpc_id), )
def configure_vpc(config, template): stack = config['stack'] region = config['region'] public_subnets = [] private_subnets = [] vpcs_file = read_yaml_file('configuration/vpcs.yaml') vpcs = vpcs_file['vpcs'] connections = vpcs_file['connections'] eips = read_yaml_file('configuration/eips.yaml') if stack not in vpcs: sys.stderr.write('%s: not found in vpcs\n' % stack) sys.exit(1) if stack not in eips: sys.stderr.write('%s: not found in eips; execute "bin/manage-eips"\n' % stack) sys.exit(1) vpc = template.add_resource( ec2.VPC( 'VPC', CidrBlock=vpcs[stack]['cidr'], InstanceTenancy='default', Tags=Tags(Name=config['description'], ), )) internet_gateway = template.add_resource( ec2.InternetGateway( 'InternetGateway', Tags=Tags(Name=config['description'], ), )) internet_gateway_attachment = template.add_resource( ec2.VPCGatewayAttachment( 'InternetGatewayAttachment', VpcId=Ref(vpc), InternetGatewayId=Ref(internet_gateway), # DeletionPolicy='Retain', )) public_route_table = template.add_resource( ec2.RouteTable( 'PublicRouteTable', VpcId=Ref(vpc), Tags=Tags(Name='%s - Public Routing Table' % stack, ), )) private_route_table = template.add_resource( ec2.RouteTable( 'PrivateRouteTable', VpcId=Ref(vpc), Tags=Tags(Name='%s - Private Routing Table' % stack, ), )) # default public subnet route is through the Internet Gateway default_public_route = template.add_resource( ec2.Route( 'DefaultPublicRoute', GatewayId=Ref(internet_gateway), DestinationCidrBlock='0.0.0.0/0', RouteTableId=Ref(public_route_table), DependsOn=Name(internet_gateway_attachment), )) network_acl = template.add_resource( ec2.NetworkAcl( 'NetworkAcl', VpcId=Ref(vpc), Tags=Tags(Name=config['description'], ), )) # It's standard practice to leave Network ACL's completely permissive # (not to be confused with SecurityGroups) template.add_resource( ec2.NetworkAclEntry( 'NetworkAclEntryIngressFromVpc', Protocol='-1', RuleNumber='100', CidrBlock='0.0.0.0/0', Egress=False, RuleAction='allow', NetworkAclId=Ref(network_acl), )) template.add_resource( ec2.NetworkAclEntry( 'NetworkAclEntryEgress', Protocol='-1', RuleNumber='100', CidrBlock='0.0.0.0/0', Egress=True, RuleAction='allow', NetworkAclId=Ref(network_acl), )) for subnet_config in config['subnets']: if subnet_config['public']: subnet_list = public_subnets subnet_route_table = public_route_table label = 'PublicSubnet' else: subnet_list = private_subnets subnet_route_table = private_route_table label = 'PrivateSubnet' label += subnet_config['zone'].upper() subnet = template.add_resource( ec2.Subnet( label, VpcId=Ref(vpc), AvailabilityZone=region + subnet_config['zone'], CidrBlock=subnet_config['cidr'], Tags=Tags( Name='%s %s' % (config['description'], label), IsPublic=subnet_config['public'], ), )) subnet_list.append({ 'label': label, 'object': subnet, 'config': subnet_config, }) template.add_resource( ec2.SubnetRouteTableAssociation( 'SubnetRouteTableAssociation%s' % label, SubnetId=Ref(subnet), RouteTableId=Ref(subnet_route_table), )) template.add_resource( ec2.SubnetNetworkAclAssociation( 'SubnetAclAssociation%s' % label, SubnetId=Ref(subnet), NetworkAclId=Ref(network_acl), )) if 'create_s3_endpoint' in config and config['create_s3_endpoint']: s3_endpoint = template.add_resource( ec2.VPCEndpoint( 'S3Endpoint', RouteTableIds=[Ref(private_route_table)], PolicyDocument={ 'Version': '2012-10-17', 'Statement': [{ 'Action': '*', 'Effect': 'Allow', 'Resource': '*', 'Principal': '*' }] }, VpcId=Ref(vpc), ServiceName='com.amazonaws.' + region + '.s3', ))
def ssm_network(): template = Template() default_route = "0.0.0.0/0" vpc_cidr = "192.168.0.0/16" template.add_parameter(Parameter( "VpcCidr", Type="String", Description="Cidr block for VPC", MinLength="9", MaxLength="18", Default=vpc_cidr, AllowedPattern="(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", ConstraintDescription="Must match following pattern 'xxx.xxx.xxx.xxx/xx'" )) template.add_parameter(Parameter( "CreateEndpoints", Type="String", Description="Create VPC Endpoints", Default="No", AllowedValues=["Yes", "No"], ConstraintDescription="'Yes' or 'No' are only options" )) template.add_parameter(Parameter( "CreateNatGateway", Type="String", Description="Create NAT Gateway", Default="No", AllowedValues=["Yes", "No"], ConstraintDescription="'Yes' or 'No' are only options" )) conditions = { "CreateVpcEndpointsUpperYes": Equals( Ref("CreateEndpoints"), "Yes" ), "CreateVpcEndpointsLowerYes": Equals( Ref("CreateEndpoints"), "yes" ), "CreateVpcEndpoints": Or( Condition("CreateVpcEndpointsUpperYes"), Condition("CreateVpcEndpointsLowerYes") ), "CreateNatGatewayUpperYes": Equals( Ref("CreateNatGateway"), "Yes" ), "CreateNatGatewayLowerYes": Equals( Ref("CreateNatGateway"), "yes" ), "CreateNatGateway": Or( Condition("CreateNatGatewayUpperYes"), Condition("CreateNatGatewayLowerYes") ) } ssm_vpc = ec2.VPC( 'SsmVpc', CidrBlock=Ref("VpcCidr"), InstanceTenancy="default", EnableDnsHostnames=True, EnableDnsSupport=True, Tags=Tags( Name="SSM VPC" ) ) subnet_blocks = Cidr(GetAtt(ssm_vpc, "CidrBlock"), 256, 8) ssm_ig = ec2.InternetGateway( 'SsmIG', ) ssm_attach_gw = ec2.VPCGatewayAttachment( 'SsmAttachGateway', InternetGatewayId=Ref(ssm_ig), VpcId=Ref(ssm_vpc) ) ssm_public_subnet = ec2.Subnet( 'SsmPublicSubnet', DependsOn=ssm_attach_gw, AvailabilityZone=Select(0, GetAZs('')), CidrBlock=Select(0, subnet_blocks), VpcId=Ref(ssm_vpc), Tags=Tags( Name="Public Subnet" ) ) ssm_public_route_table = ec2.RouteTable( 'SsmPublicRouteTable', VpcId=Ref(ssm_vpc), ) ssm_public_route = ec2.Route( 'SsmPublicRoute', DestinationCidrBlock=default_route, GatewayId=Ref(ssm_ig), RouteTableId=Ref(ssm_public_route_table) ) ssm_public_subnet_route_table_association = ec2.SubnetRouteTableAssociation( 'SsmPublicSubnetRouteTableAssociation', RouteTableId=Ref(ssm_public_route_table), SubnetId=Ref(ssm_public_subnet) ) ssm_eip_nat_gateway = ec2.EIP( 'SsmEipNatGateway', Condition="CreateNatGateway" ) ssm_nat_gateway = ec2.NatGateway( 'SsmNatGateway', Condition="CreateNatGateway", DependsOn=ssm_eip_nat_gateway, SubnetId=Ref(ssm_public_subnet), AllocationId=GetAtt(ssm_eip_nat_gateway, "AllocationId"), ) ssm_private_subnet = ec2.Subnet( 'SsmPrivateSubnet', DependsOn=ssm_attach_gw, AvailabilityZone=Select(0, GetAZs('')), CidrBlock=Select(1, subnet_blocks), VpcId=Ref(ssm_vpc), Tags=Tags( Name="Private Subnet" ) ) ssm_private_route_table = ec2.RouteTable( 'SsmPrivateRouteTable', VpcId=Ref(ssm_vpc), ) ssm_private_route = ec2.Route( 'SsmPrivateRoute', Condition="CreateNatGateway", DestinationCidrBlock=default_route, NatGatewayId=Ref(ssm_nat_gateway), RouteTableId=Ref(ssm_private_route_table) ) ssm_private_subnet_route_table_association = ec2.SubnetRouteTableAssociation( 'SsmPrivateSubnetRouteTableAssociation', RouteTableId=Ref(ssm_private_route_table), SubnetId=Ref(ssm_private_subnet) ) ssm_sg_ingress_rules = [ ec2.SecurityGroupRule( ToPort=443, FromPort=443, IpProtocol="tcp", CidrIp=GetAtt(ssm_vpc, "CidrBlock") ) ] ssm_security_group = ec2.SecurityGroup( 'SsmSecurityGroup', GroupName="SsmSG", GroupDescription="SG for SSM usage", VpcId=Ref(ssm_vpc), SecurityGroupIngress=ssm_sg_ingress_rules ) ssm_s3e_vpc_endpoint = ec2.VPCEndpoint( 'SsmS3VpcEndpoint', Condition="CreateVpcEndpoints", RouteTableIds=[ Ref(ssm_private_route_table) ], ServiceName=vpc_endpoint("s3"), VpcId=Ref(ssm_vpc), VpcEndpointType="Gateway" ) ssm_ssm_vpc_endpoint = ec2.VPCEndpoint( 'SsmSsmVpcEndpoint', Condition="CreateVpcEndpoints", SubnetIds=[Ref(ssm_private_subnet)], ServiceName=vpc_endpoint("ssm"), VpcId=Ref(ssm_vpc), VpcEndpointType="Interface", SecurityGroupIds=[ Ref(ssm_security_group) ], PrivateDnsEnabled=True ) ssm_ssmmessages_vpc_endpoint = ec2.VPCEndpoint( 'SsmSsmMessagesVpcEndpoint', Condition="CreateVpcEndpoints", SubnetIds=[Ref(ssm_private_subnet)], ServiceName=vpc_endpoint("ssmmessages"), VpcId=Ref(ssm_vpc), VpcEndpointType="Interface", SecurityGroupIds=[ Ref(ssm_security_group) ], PrivateDnsEnabled=True ) ssm_ec2messages_vpc_endpoint = ec2.VPCEndpoint( 'SsmEc2MessagesVpcEndpoint', Condition="CreateVpcEndpoints", SubnetIds=[Ref(ssm_private_subnet)], ServiceName=vpc_endpoint("ec2messages"), VpcId=Ref(ssm_vpc), VpcEndpointType="Interface", SecurityGroupIds=[ Ref(ssm_security_group) ], PrivateDnsEnabled=True ) template.add_resource(ssm_vpc) template.add_resource(ssm_ig) template.add_resource(ssm_attach_gw) template.add_resource(ssm_eip_nat_gateway) template.add_resource(ssm_public_subnet) template.add_resource(ssm_public_route_table) template.add_resource(ssm_nat_gateway) template.add_resource(ssm_public_route) template.add_resource(ssm_public_subnet_route_table_association) template.add_resource(ssm_private_subnet) template.add_resource(ssm_private_route_table) template.add_resource(ssm_private_route) template.add_resource(ssm_private_subnet_route_table_association) template.add_resource(ssm_security_group) template.add_resource(ssm_s3e_vpc_endpoint) template.add_resource(ssm_ec2messages_vpc_endpoint) template.add_resource(ssm_ssm_vpc_endpoint) template.add_resource(ssm_ssmmessages_vpc_endpoint) for k in conditions: template.add_condition(k, conditions[k]) template.add_output(Output( 'SsmVpc', Description="VPC for SSM", Value=Ref(ssm_vpc), Export=Export(Join("", [Ref("AWS::StackName"), "-ssm-vpc"])) )) template.add_output(Output( 'SsmSg', Description="Security Group for SSM", Value=Ref(ssm_security_group), Export=Export(Join("", [Ref("AWS::StackName"), "-ssm-sg"])) )) template.add_output(Output( 'SsmPrivateSubnet', Description="Private Subnet for SSM", Value=Ref(ssm_private_subnet), Export=Export(Join("", [Ref("AWS::StackName"), "-ssm-private-subnet"])) )) template.add_output(Output( 'SsmPrivateRouteTable', Description="Private RouteTable for SSM", Value=Ref(ssm_private_route_table), Export=Export(Join("", [Ref("AWS::StackName"), "-ssm-private-route-table"])) )) with open(os.path.dirname(os.path.realpath(__file__)) + '/ssm_network.yml', 'w') as cf_file: cf_file.write(template.to_yaml()) return template.to_yaml()
def create_vpc_endpoint(self): self.create_resource( ec2.VPCEndpoint('S3VPCEndpoint', RouteTableIds=[Ref(self.public_route_table)], ServiceName=AMAZON_S3_VPC_ENDPOINT, VpcId=Ref(self.vpc)))
def configure(self): self.vpc_metadata = constants.ENVIRONMENTS[self.env]['vpc'] self.set_description('VPC, Routes, Base Security Groups, and NATs') common_vpc_tags = [ec2.Tag('Name', self.env) ] + self.get_tags(service_override='VPC') _vpc = self.add_resource( ec2.VPC('VPC', CidrBlock=self.vpc_metadata['cidrblock'], EnableDnsSupport=True, EnableDnsHostnames=True, Tags=common_vpc_tags)) _dhcp_options = self.add_resource( ec2.DHCPOptions('DHCPOptions', DomainName="node.{}.{}".format( self.env, constants.TAG), DomainNameServers=['AmazonProvidedDNS'], Tags=common_vpc_tags)) self.add_resource( ec2.VPCDHCPOptionsAssociation('VPCDHCPOptionsAssociation', DhcpOptionsId=Ref(_dhcp_options), VpcId=Ref(_vpc))) _internet_gateway = self.add_resource( ec2.InternetGateway('InternetGateway', Tags=self.get_tags( service_override='InternetGateway', role_override='InternetGateway'))) self.add_resource( ec2.VPCGatewayAttachment('AttachInternetGateway', VpcId=Ref(_vpc), InternetGatewayId=Ref(_internet_gateway))) # route_tables stores all ec2.RouteTables generated and adds them to # a private vpc s3 endpoint route_tables = [] _public_route_table = self.add_resource( ec2.RouteTable('PublicRouteTable', VpcId=Ref(_vpc), Tags=self.get_tags( service_override='PublicRouteTable', role_override='PublicRouteTable'))) route_tables.append(_public_route_table) # Public Subnet Routes and ACLs self.add_resource( ec2.Route('PublicRoute', RouteTableId=Ref(_public_route_table), DestinationCidrBlock='0.0.0.0/0', GatewayId=Ref(_internet_gateway))) _public_network_acl = self.add_resource( ec2.NetworkAcl('PublicNetworkAcl', VpcId=Ref(_vpc), Tags=self.get_tags( service_override='PublicNetworkAcl', role_override='PublicNetworkAcl'))) self.add_resource( ec2.NetworkAclEntry('IngressPublicNetworkAclEntry', NetworkAclId=Ref(_public_network_acl), RuleNumber=100, Protocol='-1', RuleAction='allow', Egress=False, CidrBlock='0.0.0.0/0', PortRange=ec2.PortRange(From=1, To=65535))) self.add_resource( ec2.NetworkAclEntry('EgressPublicNetworkAclEntry', NetworkAclId=Ref(_public_network_acl), RuleNumber=101, Protocol='-1', RuleAction='allow', Egress=True, CidrBlock='0.0.0.0/0', PortRange=ec2.PortRange(From=1, To=65535))) # Private Network ACLs _private_network_acl = self.add_resource( ec2.NetworkAcl('PrivateNetworkAcl', VpcId=Ref(_vpc), Tags=self.get_tags( service_override='PrivateNetworkAcl', role_override='PrivateNetworkAcl'))) self.add_resource( ec2.NetworkAclEntry('IngressPrivateNetworkAclEntry', NetworkAclId=Ref(_private_network_acl), RuleNumber=100, Protocol='-1', RuleAction='allow', Egress=False, CidrBlock='0.0.0.0/0', PortRange=ec2.PortRange(From=1, To=65535))) self.add_resource( ec2.NetworkAclEntry('EgressPrivateNetworkAclEntry', NetworkAclId=Ref(_private_network_acl), RuleNumber=101, Protocol='-1', RuleAction='allow', Egress=True, CidrBlock='0.0.0.0/0', PortRange=ec2.PortRange(From=1, To=65535))) # Default security groups - referenced by name by constants/default-security-groups # _nat_security_group = self.add_resource( # ec2.SecurityGroup( # 'NATSecurityGroup', # VpcId=Ref(_vpc), # GroupDescription='Security Group for NAT Instances', # SecurityGroupIngress=[ # {'IpProtocol': '-1', 'FromPort': 1, 'ToPort': 65535, 'CidrIp': self.vpc_metadata['cidrblock']}, # {'IpProtocol': '-1', 'FromPort': 1, 'ToPort': 65535, 'CidrIp': '10.0.0.0/8'} # ], # Tags=self.get_tags(service_override='NAT', role_override='NAT-SecurityGroup') # ) # ) # _consul_security_group = self.add_resource( # ec2.SecurityGroup( # 'ConsulSecurityGroup', # VpcId=Ref(_vpc), # GroupDescription='Security Group for Consul access', # SecurityGroupIngress=[ # {'IpProtocol': 'tcp', 'FromPort': 8300, 'ToPort': 8302, 'CidrIp': '10.0.0.0/8'}, # consul server rpc/serf # {'IpProtocol': 'udp', 'FromPort': 8300, 'ToPort': 8302, 'CidrIp': '10.0.0.0/8'}, # consul server rpc/serf # {'IpProtocol': 'tcp', 'FromPort': 8400, 'ToPort': 8400, 'CidrIp': '10.0.0.0/8'}, # consul client rpc # {'IpProtocol': 'tcp', 'FromPort': 8500, 'ToPort': 8500, 'CidrIp': '10.0.0.0/8'}, # consul http # {'IpProtocol': 'tcp', 'FromPort': 8600, 'ToPort': 8600, 'CidrIp': '10.0.0.0/8'}, # consul dns # {'IpProtocol': 'udp', 'FromPort': 8600, 'ToPort': 8600, 'CidrIp': '10.0.0.0/8'} # consul dns # ], # Tags=[ # ec2.Tag('ivy:team', self.TEAM['email']), # ec2.Tag('ivy:environment', self.env), # ec2.Tag('ivy:service', 'Consul'), # ec2.Tag('ivy:role', 'Consul-SecurityGroup') # ] # ) # ) # _ssh_security_group = self.add_resource( # ec2.SecurityGroup( # 'InternalSecurityGroup', # VpcId=Ref(_vpc), # GroupDescription='Internal Rules', # SecurityGroupIngress=[ # {'IpProtocol': 'icmp', 'FromPort': -1, 'ToPort': -1, 'CidrIp': '10.0.0.0/8'}, # {'IpProtocol': 'tcp', 'FromPort': 22, 'ToPort': 22, 'CidrIp': '10.0.0.0/8'} # ], # SecurityGroupEgress=[ # {'IpProtocol': '-1', 'FromPort': 0, 'ToPort': 65535, 'CidrIp': '0.0.0.0/0'} # ], # Tags=[ # ec2.Tag('ivy:team', self.TEAM['email']), # ec2.Tag('ivy:environment', self.env), # ec2.Tag('ivy:service', 'infrastructure'), # ec2.Tag('ivy:role', 'internal') # ] # ) # ) # # self.add_security_group(Ref(_nat_security_group), Ref(_consul_security_group), Ref(_ssh_security_group)) ## This sets up all private and public AZs for index, zone in enumerate(self.vpc_metadata['zones'], 1): _public_subnet = self.add_resource( ec2.Subnet( 'PublicSubnet{}'.format(index), VpcId=Ref(_vpc), CidrBlock=zone['public-cidrblock'], AvailabilityZone=zone['availability-zone'], MapPublicIpOnLaunch=True, Tags=self.get_tags( service_override='PublicSubnet', role_override='PublicSubnet{}'.format(index)) + [ ec2.Tag('Name', '{}-PublicSubnet{}'.format( self.env, index)) ])) self.add_resource( ec2.SubnetRouteTableAssociation( 'PublicSubnetRouteTableAssociation{}'.format(index), SubnetId=Ref(_public_subnet), RouteTableId=Ref(_public_route_table))) self.add_resource( ec2.SubnetNetworkAclAssociation( 'PublicSubnetNetworkAclAssociation{}'.format(index), SubnetId=Ref(_public_subnet), NetworkAclId=Ref(_public_network_acl))) # Allow VPCs with no private subnets (save money on NAT instances for VPCs with only public instances) if zone.get('private-cidrblock'): _private_subnet = self.add_resource( ec2.Subnet( 'PrivateSubnet{}'.format(index), VpcId=Ref(_vpc), CidrBlock=zone['private-cidrblock'], AvailabilityZone=zone['availability-zone'], Tags=self.get_tags( service_override='PrivateSubnet', role_override='PrivateSubnet{}'.format(index)) + [ ec2.Tag( 'Name', '{}-PrivateSubnet{}'.format( self.env, index)) ])) # Private subnets get their own route table for AZ-specific NATs _private_route_table = self.add_resource( ec2.RouteTable( 'PrivateRouteTable{}'.format(index), VpcId=Ref(_vpc), Tags=self.get_tags( service_override='PrivateRouteTable', role_override='PrivateRouteTable{}'.format( index)))) route_tables.append(_private_route_table) # Create an EIP to be used with the NAT instance or gateway _nat_eip = self.add_resource( ec2.EIP('NATInstanceEIP{}'.format(index), Domain='vpc')) # Use VPC NAT Gateway _nat_gw = self.add_resource( ec2.NatGateway('NATGateway{}'.format(index), AllocationId=GetAtt(_nat_eip, "AllocationId"), SubnetId=Ref(_public_subnet))) # Create a route via the NAT GW for the private route table self.add_resource( ec2.Route('PrivateRoute{}'.format(index), RouteTableId=Ref(_private_route_table), DestinationCidrBlock='0.0.0.0/0', NatGatewayId=Ref(_nat_gw))) self.add_resource( ec2.SubnetRouteTableAssociation( 'PrivateSubnetRouteTableAssociation{}'.format(index), SubnetId=Ref(_private_subnet), RouteTableId=Ref(_private_route_table))) self.add_resource( ec2.SubnetNetworkAclAssociation( 'PrivateSubnetNetworkAclAssociation{}'.format(index), SubnetId=Ref(_private_subnet), NetworkAclId=Ref(_private_network_acl))) # use route_table to create a VPC S3 endpoint self.add_resource( ec2.VPCEndpoint('S3VPCEndpoint', RouteTableIds=[Ref(rt) for rt in route_tables], ServiceName='com.amazonaws.{}.s3'.format( self.region), VpcId=Ref(_vpc)))