def _create_public_network(self, subnet_configs): public_route_table = RouteTable( camelcase("{self.env}Public".format(**locals())), VpcId=Ref(self.vpc), Tags=[ { 'Key': 'Name', 'Value': "{self.env}-public".format(**locals()) }, {'Key': 'environment', 'Value': self.env} ], DependsOn=self.vpc.title) self.template.add_resource(public_route_table) subnet_count = 0 existing_subnet_ids, existing_subnet_azs, az_balance = self._get_existing_subnet_info("PublicSubnet") for subnet_title, subnet_config in subnet_configs.items(): subnet_count += 1 if f"PublicSubnet{subnet_count}" in existing_subnet_ids: availability_zone = existing_subnet_azs[existing_subnet_ids[f"PublicSubnet{subnet_count}"]] else: availability_zone = min(az_balance, key=az_balance.get) subnet_title = camelcase("{self.env}Public".format(**locals())) + \ pascalcase(re.sub('[^a-zA-Z0-9*]', '', subnet_title)) subnet_name = "{self.env}-public-{subnet_count}".format(**locals()) subnet = Subnet( subnet_title, AvailabilityZone=availability_zone, CidrBlock=subnet_config['cidr'], VpcId=Ref(self.vpc), MapPublicIpOnLaunch=True, Tags=[ {'Key': 'Name', 'Value': subnet_name}, {'Key': 'environment', 'Value': self.env} ] ) self.public_subnets.append(subnet) self.template.add_resource(subnet) subnet_route_table_association = SubnetRouteTableAssociation( camelcase("{self.env}PublicSubnet{subnet_count}Assoc".format(**locals())), RouteTableId=Ref(public_route_table), SubnetId=Ref(subnet) ) self.template.add_resource(subnet_route_table_association) internet_gateway_route = Route( camelcase("{self.env}IgRoute".format(**locals())), DestinationCidrBlock='0.0.0.0/0', GatewayId=Ref(self.internet_gateway), RouteTableId=Ref(public_route_table) ) self.template.add_resource(internet_gateway_route) return None
def __build_subnet(self, subnet_config: SubnetConfig, vpc: VPC): subnet = self.__template.add_resource( Subnet( subnet_config.name, CidrBlock=subnet_config.cidr, VpcId=Ref(vpc), MapPublicIpOnLaunch=subnet_config.map_public_ip_on_launch, Tags=subnet_config.tags(), )) self.__template.add_output( Output(subnet_config.name + "Id", Value=Ref(subnet))) return subnet
def create_subnet(_subnet_title, _vpcid=None, _availability_zone=None, _map_public_ip_on_launch=False, _subnet_cidr=None): _sbnet = Subnet(title=_subnet_title, CidrBlock=_subnet_cidr, VpcId=_vpcid, AvailabilityZone=_availability_zone, MapPublicIpOnLaunch=_map_public_ip_on_launch) return _sbnet
def add_storage_subnets(template, vpc, az_index, layers): """ Function to add storage subnets inside the VPC :param layers: VPC layers :type layers: dict :param template: VPC Template() :type template: troposphere.Template :param vpc: Vpc() for Ref() :type vpc: troposphere.ec2.Vpc :param az_index: List of AZ Index (a,b,c..) :type az_index: list :returns: tuple() list of rtb, list of subnets """ rtb = RouteTable( "StorageRtb", template=template, VpcId=Ref(vpc), Tags=Tags(Name="StorageRtb") + Tags({f"vpc{DELIM}usage": "storage"}), Metadata=metadata, ) subnets = [] for index, subnet_cidr in zip(az_index, layers["stor"]): subnet = Subnet( f"StorageSubnet{index.upper()}", template=template, CidrBlock=subnet_cidr, VpcId=Ref(vpc), AvailabilityZone=Sub(f"${{AWS::Region}}{index}"), Tags=Tags( Name=If( USE_STACK_NAME_CON_T, Sub(f"${{AWS::StackName}}-Storage-{index}"), Sub(f"${{{ROOT_STACK_NAME_T}}}-Storage-{index}"), ), ) + Tags({f"vpc{DELIM}usage": "storage", f"vpc{DELIM}vpc-id": Ref(vpc)}), Metadata=metadata, ) SubnetRouteTableAssociation( f"StorageSubnetAssoc{index.upper()}", template=template, SubnetId=Ref(subnet), RouteTableId=Ref(rtb), Metadata=metadata, ) subnets.append(subnet) return [rtb], subnets
def __create_private_subnet(template: Template, vpc): private_subnet_cidr = template.add_parameter(parameter=Parameter( title='PrivateSubnetCidr', Type='String', Default='192.168.2.0/24')) private_subnet = template.add_resource( resource=Subnet(title='SamplePrivateSubnet', CidrBlock=Ref(private_subnet_cidr), VpcId=Ref(vpc))) private_route_table = template.add_resource( resource=RouteTable(title='SamplePrivateRoteTable', VpcId=Ref(vpc))) template.add_resource(resource=SubnetRouteTableAssociation( title='SamplePrivateRoteTableAssociation', RouteTableId=Ref(private_route_table), SubnetId=Ref(private_subnet)))
def addSubnet(template, Env, Owner, CidrBlock, Name, AvailabilityZone, MapPublicIpOnLaunch, Network): return template.add_resource( Subnet(Name.replace("-", "").replace(" ", "") + CidrBlock.replace("/", "").replace(".", ""), CidrBlock=CidrBlock, AvailabilityZone=AvailabilityZone, MapPublicIpOnLaunch=MapPublicIpOnLaunch, VpcId=Ref("VPC"), Tags=Tags( **{ 'Name': Name + " - " + Network + " Subnet - " + AvailabilityZone, 'Network': Network, 'Env': Env, 'Owner': Owner, })))
def _create_vpc(self): if self.vpc: self.tpl.add_output(Output(self.OUTPUT_VPC, Value=self.vpc)) self.tpl.add_output(Output(self.OUTPUT_SUBNETS, Value=','.join(self.subnets))) return vpc = VPC(self.RESOURCE_EKS_VPC.name, CidrBlock=self.vpc_cidr, Tags=Tags(Name=self.tag_name)) self.tpl.add_resource(vpc) gateway = self.tpl.add_resource(InternetGateway(self.RESOURCE_VPC_INTERNET_GATEWAY.name)) self.tpl.add_resource(VPCGatewayAttachment( self.RESOURCE_VPC_GATEWAY_ATTACHMENT.name, VpcId=Ref(vpc), InternetGatewayId=Ref(gateway), DependsOn=gateway, )) rt = self.tpl.add_resource(RouteTable( self.RESOURCE_VPC_ROUTE_TABLE.name, VpcId=Ref(vpc), DependsOn=gateway, Tags=Tags(Name='public subnet', Network='public'), )) self.tpl.add_resource(Route( self.RESOURCE_VPC_ROUTE.name, RouteTableId=Ref(rt), DestinationCidrBlock='0.0.0.0/0', GatewayId=Ref(gateway), )) self.resources.extend(deepcopy([self.RESOURCE_EKS_VPC, self.RESOURCE_VPC_INTERNET_GATEWAY, self.RESOURCE_VPC_GATEWAY_ATTACHMENT, self.RESOURCE_VPC_ROUTE_TABLE, self.RESOURCE_VPC_ROUTE])) subnets = [] vpc_network = IPNetwork(self.vpc_cidr) prefixlen = IPNetwork(self.vpc_cidr).prefixlen + (len(self.zones) - 1).bit_length() cidrs = list(vpc_network.subnet(prefixlen)) for i, zone in enumerate(self.zones): sname = self.RESOURCE_FORMAT_SUBNET.format(i + 1) staname = self.RESOURCE_FORMAT_SUBNET_RTA.format(i + 1) subnet = self.tpl.add_resource(Subnet( sname, AvailabilityZone=zone, VpcId=Ref(vpc), CidrBlock=str(cidrs[i].cidr), Tags=Tags(Name='{}-{}'.format(self.name, str(i + 1))) )) self.resources.append(Resource(sname, 'EKS VPC {}'.format(sname), Status.not_exist)) self.tpl.add_resource(SubnetRouteTableAssociation( staname, SubnetId=Ref(subnet), RouteTableId=Ref(rt) )) self.resources.append(Resource(staname, 'EKS VPC {}'.format(staname), Status.not_exist)) subnets.append(subnet) self.subnet_refs = [Ref(s) for s in subnets] self.tpl.add_output(Output(self.OUTPUT_VPC, Value=Ref(vpc))) self.tpl.add_output(Output(self.OUTPUT_SUBNETS, Value=Join(',', self.subnet_refs)))
def subnet_adder(self, subnet_list, name_ref, route_table_name): for index, cidr in enumerate(subnet_list): self.template.add_resource( Subnet( name_ref + str(index), CidrBlock=str(cidr), VpcId=Ref(self.vpc), # not a fan of the below line, but will do for now. This basically exists to ensure that subnets are # distributed between availability zones. However, since we are always creating 3 pub/priv subnets # this will fail if there are less than 3 AZs in a given region. Ideally the subnet count & # distribution would happen dynamically based on how many zones are available. AvailabilityZone=Select(index, self.azs))) self.template.add_resource( SubnetRouteTableAssociation( route_table_name + str(index), SubnetId=Ref(name_ref + str(index)), RouteTableId=Ref(route_table_name)))
def create_subnet(stack, name, subnet_cidr, avail_zone='us-east-1a', public_ip=False): """Add VPC Subnet Resource.""" return stack.stack.add_resource( Subnet( '{0}Subnet'.format(name), CidrBlock=Ref(subnet_cidr), MapPublicIpOnLaunch=public_ip, AvailabilityZone=avail_zone, VpcId=Ref(stack.vpc), Tags=[ { 'Key': 'Name', 'Value': '{0}{1}'.format(stack.env, name) }, ], ))
def __create_private_subnet(template: Template, vpc): private_route_table = template.add_resource( resource=RouteTable(title='SamplePrivateRoteTable', VpcId=Ref(vpc))) for suffix in ['A', 'B']: private_subnet_cidr = template.add_parameter( parameter=Parameter(title='PrivateSubnetCidr' + suffix, Type='String', Default=__get_subnet_cidr())) private_subnet = template.add_resource( resource=Subnet(title='SamplePrivateSubnet' + suffix, AvailabilityZone=Sub('${AWS::Region}' + suffix.lower()), CidrBlock=Ref(private_subnet_cidr), VpcId=Ref(vpc))) add_export(template, private_subnet.title + 'Id', Ref(private_subnet)) template.add_resource(resource=SubnetRouteTableAssociation( title='SamplePrivateRoteTableAssociation' + suffix, RouteTableId=Ref(private_route_table), SubnetId=Ref(private_subnet)))
def add_subnets(availability_zones, cidrType, map_public_ip, prefix, postfix): subnets = {} cidrs = cidr_to_subnets(cidrType) for availability_zone in availability_zones: subnets[availability_zone] = {} subnets[availability_zone][cidrType] = {} items = {} for subnet_name in get_subnet_names(cidrType): items[subnet_name] = t.add_resource( Subnet( prefix + availability_zone.replace("-", "") + subnet_name.upper(), VpcId=Ref("vpcId"), AvailabilityZone=availability_zone, CidrBlock=cidrs[availability_zone][cidrType][subnet_name], MapPublicIpOnLaunch=map_public_ip, Tags=Tags( Name=Join("", [Ref("stackName"), "-" + availability_zone + "-" + postfix + "-" + subnet_name.upper()]) ) )) subnets[availability_zone][cidrType] = items return subnets
def create_vpc_template(): template = Template() vpc_cidr = template.add_parameter(parameter=Parameter( title='VpcCidr', Type='String', Default='192.168.0.0/16')) subnet_cidr = template.add_parameter(parameter=Parameter( title='SubnetCidr', Type='String', Default='192.168.1.0/24')) vpc = template.add_resource( resource=VPC(title='SampleVpc', CidrBlock=Ref(vpc_cidr))) igw = template.add_resource(resource=InternetGateway(title='SampleIgw')) template.add_resource(resource=VPCGatewayAttachment( title='SampleAttachment', VpcId=Ref(vpc), InternetGatewayId=Ref(igw))) subnet = template.add_resource(resource=Subnet(title='SampleSubnet', CidrBlock=Ref(subnet_cidr), MapPublicIpOnLaunch=True, VpcId=Ref(vpc))) route_table = template.add_resource( resource=RouteTable(title='SampleRoteTable', VpcId=Ref(vpc))) template.add_resource(resource=SubnetRouteTableAssociation( title='SampleRoteTableAssociation', RouteTableId=Ref(route_table), SubnetId=Ref(subnet))) template.add_resource(resource=Route(title='SampleRoute', DestinationCidrBlock='0.0.0.0/0', GatewayId=Ref(igw), RouteTableId=Ref(route_table))) with open('./vpc.yml', mode='w') as file: file.write(template.to_yaml())
def __create_public_subnet(template: Template, vpc) -> Subnet: igw = template.add_resource(resource=InternetGateway(title='SampleIgw')) template.add_resource(resource=VPCGatewayAttachment( title='SampleAttachment', VpcId=Ref(vpc), InternetGatewayId=Ref(igw))) public_route_table = template.add_resource( resource=RouteTable(title='SamplePublicRoteTable', VpcId=Ref(vpc))) for suffix in ['A', 'B']: public_subnet_cidr = template.add_parameter( parameter=Parameter(title='PublicSubnetCidr' + suffix, Type='String', Default=__get_subnet_cidr())) public_subnet = template.add_resource( resource=Subnet(title='SamplePublicSubnet' + suffix, AvailabilityZone=Sub('${AWS::Region}' + suffix.lower()), CidrBlock=Ref(public_subnet_cidr), MapPublicIpOnLaunch=True, VpcId=Ref(vpc))) add_export(template, public_subnet.title + 'Id', Ref(public_subnet)) template.add_resource(resource=SubnetRouteTableAssociation( title='SamplePublicRoteTableAssociation' + suffix, RouteTableId=Ref(public_route_table), SubnetId=Ref(public_subnet))) template.add_resource(resource=Route(title='SamplePublicRoute', DestinationCidrBlock='0.0.0.0/0', GatewayId=Ref(igw), RouteTableId=Ref(public_route_table))) return public_subnet
def create_template(num_masters, num_agents, num_publicAgents): #outfilename = "test.json" outfilename = "cf_" + str(num_masters) + "." + str(num_agents) + "." + str( num_publicAgents) + ".json" # Create the Template t = Template() t.add_version('2010-09-09') t.add_description('Creates a set of Servers for DC/OS using CentOS 7.3 AMI. Creates a boot server to host the DC/OS installer and a NAT Instance for outbound connections from private agents. Creates ' + str(num_masters) + ' Master(s), ' \ + str(num_agents) + ' Private Agent(s), and ' + str(num_publicAgents) + ' Public Agent(s). After creating the Stack; Log into the boot server and run the DCOS Bash Script installer for AWS') # Amazon Linux AMI 2016.09.1.20170119 x86_64 VPC NAT HVM EBS # amzn-ami-vpc-nat-hvm-2016.09.1.20170119-x86_64-ebs - # ami-dd3dd7cb us-east-1 (N. Virginia) # ami-564b6e33 us-east-2 (Ohio) # ami-7d54061d us-west-1 (N. Cal) # ami-3b6fd05b us-west-2 (Oregon) t.add_mapping( 'NATAmi', { 'us-east-1': { 'default': 'ami-dd3dd7cb' }, 'us-east-2': { 'default': 'ami-564b6e33' }, 'us-west-1': { 'default': 'ami-7d54061d' }, 'us-west-2': { 'default': 'ami-3b6fd05b' }, }) # The c73 AMI pre created and deployed on each region t.add_mapping( 'c73Ami', { 'us-east-1': { 'default': 'ami-46c1b650' }, 'us-east-2': { 'default': 'ami-18f8df7d' }, 'us-west-1': { 'default': 'ami-f5d7f195' }, 'us-west-2': { 'default': 'ami-f4533694' }, }) # CloudFormation Parameters # Sometimes when I deployed stack on us-east-1; it would fail on av zone us-east-1c with error messages instance type not support on this AZ. I added this parameter to fix all of the components in on AZ for now avzone_param = t.add_parameter( Parameter( "AVZoneName", ConstraintDescription='Must be the name of an an Availability Zone', Description='Name of an Availability Zone', Type='AWS::EC2::AvailabilityZone::Name', )) # Every agent will get a data drive of this size dataDriveSizeGB_param = t.add_parameter( Parameter( "dataDriveSizeGB", Default="100", MinValue=20, MaxValue=1000, Description= 'Size of data drive to add to private agents from 20 to 1000GB', Type='Number')) # The key will be added to the centos user so you can login to centos using the key keyname_param = t.add_parameter( Parameter( "KeyName", ConstraintDescription= 'Must be the name of an existing EC2 KeyPair.', Description= 'Name of an existing EC2 KeyPair to enable SSH access to the instance', Type='AWS::EC2::KeyPair::KeyName', )) # While you can allow everyone it's more secure to just allow a single machine or subnet of machines; web port will also be opened to this CIDR sshlocation_param = t.add_parameter( Parameter( "sshlocation", Type="String", Description= "Subnet allowed to ssh to these servers. 0.0.0.0/0 to allow all.")) # Instance type for Master instanceTypeMaster_param = t.add_parameter( Parameter( 'InstanceTypeMaster', Type='String', Description='EC2 instance type for ' + str(num_masters) + ' Masters(s)', Default='m4.xlarge', AllowedValues=[ 't2.xlarge', 't2.2xlarge', 'm4.xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.10xlarge', 'c4.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', ], ConstraintDescription='Must be a valid EC2 instance type.', )) # Instance type for Agents instanceTypeAgent_param = t.add_parameter( Parameter( 'InstanceTypeAgent', Type='String', Description='EC2 instance type for ' + str(num_agents) + ' Private Agent(s)', Default='m4.2xlarge', AllowedValues=[ 't2.xlarge', 't2.2xlarge', 'm4.xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.10xlarge', 'c4.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', ], ConstraintDescription='Must be a valid EC2 instance type.', )) # Instance type for Public Agents instanceTypePublicAgent_param = t.add_parameter( Parameter( 'InstanceTypePublicAgent', Type='String', Description='EC2 instance type for ' + str(num_publicAgents) + ' Public Agent(s)', Default='m4.xlarge', AllowedValues=[ 't2.xlarge', 't2.2xlarge', 'm4.xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.10xlarge', 'c4.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', ], ConstraintDescription='Must be a valid EC2 instance type.', )) # Adding Resources ref_stack_id = Ref('AWS::StackId') ref_region = Ref('AWS::Region') ref_stack_name = Ref('AWS::StackName') # Create VPC nm = 'vpc' vpc = t.add_resource( VPC(nm, CidrBlock='10.10.0.0/16', EnableDnsSupport=True, EnableDnsHostnames=True, Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Create Subnet for Masters nm = 'mastersSubnet' subnetMasters = t.add_resource( Subnet(nm, AvailabilityZone=Ref(avzone_param), CidrBlock='10.10.0.0/24', VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Create Subnet for Agents nm = 'agentsSubnet' subnetAgents = t.add_resource( Subnet(nm, AvailabilityZone=Ref(avzone_param), CidrBlock='10.10.16.0/24', VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Create Subnet for Public Agents nm = 'publicAgentsSubnet' subnetPublicAgents = t.add_resource( Subnet(nm, AvailabilityZone=Ref(avzone_param), CidrBlock='10.10.32.0/24', VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Create Gateway; route to the outside world (Internet) nm = 'ig' internetGateway = t.add_resource( InternetGateway(nm, Tags=Tags(Application=ref_stack_id, Name=Join( "", [Ref('AWS::StackName'), "-", nm])))) # Attach Gateway to VPC nm = 'gatewayAttachment' gatewayAttachment = t.add_resource( VPCGatewayAttachment(nm, VpcId=Ref(vpc), InternetGatewayId=Ref(internetGateway))) # Create Route Table nm = 'routeTable' routeTable = t.add_resource( RouteTable(nm, VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Add Routes # Allow all outbound traffic nm = 'route' route = t.add_resource( Route( nm, DependsOn=gatewayAttachment.title, GatewayId=Ref(internetGateway), DestinationCidrBlock='0.0.0.0/0', RouteTableId=Ref(routeTable), )) # Associate RouteTable to Master and Public Subnets nm = 'subnetRTAMasters' subnetRouteTableAssociation = t.add_resource( SubnetRouteTableAssociation( nm, SubnetId=Ref(subnetMasters), RouteTableId=Ref(routeTable), )) nm = 'subnetRTAPublicAgents' subnetRouteTableAssociation = t.add_resource( SubnetRouteTableAssociation( nm, SubnetId=Ref(subnetPublicAgents), RouteTableId=Ref(routeTable), )) # Create Security Group (General access to ssh and internal connectionsn between masters, agents, and public agents) nm = 'securityGroup' securityGroup = t.add_resource( SecurityGroup(nm, GroupDescription='Security Group', SecurityGroupIngress=[ SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp=Ref(sshlocation_param)), SecurityGroupRule(IpProtocol='-1', CidrIp='10.10.0.0/16') ], VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Create Security Group Public Agents nm = 'securityGroupPublicAgents' publicAgentsSG = t.add_resource( SecurityGroup(nm, GroupDescription='Security Group Public Agents', SecurityGroupIngress=[ SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='10000', ToPort='10010', CidrIp='0.0.0.0/0'), SecurityGroupRule(IpProtocol='tcp', FromPort='9090', ToPort='9090', CidrIp='0.0.0.0/0') ], VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Create Security Group Masters Allow Access from sshlocation param as test nm = 'securityGroupMasters' mastersSG = t.add_resource( SecurityGroup(nm, GroupDescription='Security Group Masters', SecurityGroupIngress=[ SecurityGroupRule(IpProtocol='tcp', FromPort='80', ToPort='80', CidrIp=Ref(sshlocation_param)), SecurityGroupRule(IpProtocol='tcp', FromPort='443', ToPort='443', CidrIp=Ref(sshlocation_param)) ], VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) if useNatInstance: # **** Also change in natRoute **** # Create NAT instance; This allows private agents to get out to the Internet nm = 'nat' nat = t.add_resource( Instance( nm, SourceDestCheck="false", ImageId=FindInMap("NATAmi", Ref("AWS::Region"), "default"), InstanceType="m4.large", AvailabilityZone=Ref(avzone_param), KeyName=Ref(keyname_param), DependsOn=internetGateway.title, NetworkInterfaces=[ NetworkInterfaceProperty(GroupSet=[Ref(securityGroup)], AssociatePublicIpAddress='true', DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(subnetMasters), PrivateIpAddress='10.10.0.9') ], BlockDeviceMappings=[ BlockDeviceMapping(DeviceName="/dev/xvda", Ebs=EBSBlockDevice( DeleteOnTermination='true', )) ], Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) else: # Create Elastic IP for NatGateay nm = 'natIP' nat_eip = t.add_resource(EIP( nm, Domain="vpc", )) # Create NAT Gateway nm = 'natGateway' nat = t.add_resource( NatGateway( nm, AllocationId=GetAtt(nat_eip, 'AllocationId'), SubnetId=Ref(subnetMasters), )) # Create Route Table for NAT nm = 'natRouteTable' routeTableNAT = t.add_resource( RouteTable(nm, VpcId=Ref(vpc), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Associate Agent Subnet to NAT nm = 'subnetRTAAgents' subnetRouteTableAssociation = t.add_resource( SubnetRouteTableAssociation( nm, SubnetId=Ref(subnetAgents), RouteTableId=Ref(routeTableNAT), )) # Add Routes (Agents can reach out anywhere) nm = 'natRoute' if useNatInstance: route = t.add_resource( Route( nm, RouteTableId=Ref(routeTableNAT), DestinationCidrBlock='0.0.0.0/0', InstanceId=Ref(nat), )) else: route = t.add_resource( Route( nm, RouteTableId=Ref(routeTableNAT), DestinationCidrBlock='0.0.0.0/0', NatGatewayId=Ref(nat), )) # **************************************** # NOTE: I am using static PrivateIPAddresses; this may not be a good choice; however, it simplified the install script. The range of IP's for the master and agents are limited to 24 subnet and I start at 11 # With this configuration the max number of agents is around 240. # **************************************** # Create boot instance # Installs on AWS so far have taken longer than on Azure. Takes about 10 minutes for the boot server to configure. # Tried several InstanceType from t2.micro to m4.large; all take about 10 minutes for boot to load. The docker start of mesosphere/dcos-genconf seems to be taking longer than it did on azure. nm = 'boot' boot = t.add_resource( Instance(nm, ImageId=FindInMap("c73Ami", Ref("AWS::Region"), "default"), InstanceType="m4.xlarge", AvailabilityZone=Ref(avzone_param), KeyName=Ref(keyname_param), NetworkInterfaces=[ NetworkInterfaceProperty(GroupSet=[Ref(securityGroup)], AssociatePublicIpAddress='true', DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(subnetMasters), PrivateIpAddress='10.10.0.10') ], BlockDeviceMappings=[ BlockDeviceMapping(DeviceName="/dev/sda1", Ebs=EBSBlockDevice( VolumeSize="100", DeleteOnTermination='true', )) ], Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Create master instance(s) masters = [] i = 1 while i <= num_masters: nm = 'm' + str(i) private_ip = "10.10.0." + str(i + 10) instance = t.add_resource( Instance(nm, ImageId=FindInMap("c73Ami", Ref("AWS::Region"), "default"), InstanceType=Ref(instanceTypeMaster_param), AvailabilityZone=Ref(avzone_param), KeyName=Ref(keyname_param), NetworkInterfaces=[ NetworkInterfaceProperty( GroupSet=[Ref(securityGroup), Ref(mastersSG)], AssociatePublicIpAddress='true', DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(subnetMasters), PrivateIpAddress=private_ip) ], BlockDeviceMappings=[ BlockDeviceMapping(DeviceName="/dev/sda1", Ebs=EBSBlockDevice( VolumeSize="100", DeleteOnTermination='true', )) ], Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) masters.append(instance) i += 1 # Create agent instance(s) i = 1 while i <= num_agents: nm = 'a' + str(i) private_ip = "10.10.16." + str(i + 10) instance = t.add_resource( Instance( nm, ImageId=FindInMap("c73Ami", Ref("AWS::Region"), "default"), InstanceType=Ref(instanceTypeAgent_param), AvailabilityZone=Ref(avzone_param), KeyName=Ref(keyname_param), NetworkInterfaces=[ NetworkInterfaceProperty(GroupSet=[Ref(securityGroup)], AssociatePublicIpAddress='false', DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(subnetAgents), PrivateIpAddress=private_ip) ], BlockDeviceMappings=[ BlockDeviceMapping(DeviceName="/dev/sda1", Ebs=EBSBlockDevice( VolumeSize="100", DeleteOnTermination='true', )) ], Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) volume = t.add_resource( Volume(nm + "data", AvailabilityZone=Ref(avzone_param), Size=Ref(dataDriveSizeGB_param), Tags=Tags( Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm + "data"])))) volattach = t.add_resource( VolumeAttachment(nm + "dataattach", InstanceId=Ref(instance), VolumeId=Ref(volume), Device="/dev/sdc")) i += 1 # Create public agent instance(s) publicAgents = [] i = 1 nm = "p1" while i <= num_publicAgents: nm = 'p' + str(i) private_ip = "10.10.32." + str(i + 10) instance = t.add_resource( Instance( nm, ImageId=FindInMap("c73Ami", Ref("AWS::Region"), "default"), InstanceType=Ref(instanceTypePublicAgent_param), AvailabilityZone=Ref(avzone_param), KeyName=Ref(keyname_param), NetworkInterfaces=[ NetworkInterfaceProperty( GroupSet=[Ref(securityGroup), Ref(publicAgentsSG)], AssociatePublicIpAddress='true', DeviceIndex='0', DeleteOnTermination='true', SubnetId=Ref(subnetPublicAgents), PrivateIpAddress=private_ip) ], BlockDeviceMappings=[ BlockDeviceMapping(DeviceName="/dev/sda1", Ebs=EBSBlockDevice( VolumeSize="100", DeleteOnTermination='true', )) ], Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) publicAgents.append(instance) i += 1 # Load Balancer Masters nm = "masters" elasticLBMasters = t.add_resource( elb.LoadBalancer( nm, Instances=[Ref(r) for r in masters], Subnets=[Ref(subnetMasters)], SecurityGroups=[Ref(mastersSG)], CrossZone=False, Listeners=[ elb.Listener( LoadBalancerPort="80", InstancePort="80", Protocol="TCP", ), elb.Listener( LoadBalancerPort="443", InstancePort="443", Protocol="TCP", ), ], # Health Checking on port 80 which should be there after DCOS has been installed. HealthCheck=elb.HealthCheck( Target="TCP:80", HealthyThreshold="2", UnhealthyThreshold="2", Interval="30", Timeout="5", ), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Load Balancer Public Agents nm = "publicagents" elasticLBPublicAgents = t.add_resource( elb.LoadBalancer( nm, #AvailabilityZones=GetAZs(""), Instances=[Ref(r) for r in publicAgents], Subnets=[Ref(subnetPublicAgents)], SecurityGroups=[Ref(publicAgentsSG)], CrossZone=False, Listeners=[ elb.Listener( LoadBalancerPort="10000", InstancePort="10000", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10001", InstancePort="10001", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10002", InstancePort="10002", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10003", InstancePort="10003", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10004", InstancePort="10004", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10005", InstancePort="10005", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10006", InstancePort="10006", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10007", InstancePort="10007", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10008", InstancePort="10008", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10009", InstancePort="10009", Protocol="TCP", ), elb.Listener( LoadBalancerPort="10010", InstancePort="10010", Protocol="TCP", ), elb.Listener( LoadBalancerPort="9090", InstancePort="9090", Protocol="TCP", ), elb.Listener( LoadBalancerPort="80", InstancePort="80", Protocol="TCP", ), elb.Listener( LoadBalancerPort="443", InstancePort="443", Protocol="TCP", ) ], # I've added health check for port 9090; becomes healthy after Marathon-LB is installed. HealthCheck=elb.HealthCheck( Target="TCP:9090", HealthyThreshold="2", UnhealthyThreshold="2", Interval="30", Timeout="5", ), Tags=Tags(Application=ref_stack_id, Name=Join("", [Ref('AWS::StackName'), "-", nm])))) # Outputs t.add_output( Output("BootServer", Description="Name/IP of Boot Server", Value=Join( "/", [GetAtt(boot, "PublicDnsName"), GetAtt(boot, "PublicIp")]))) t.add_output( Output("MastersURL", Description="URL of the Masters", Value=Join( "", ["http://", GetAtt(elasticLBMasters, "DNSName")]))) t.add_output( Output( "PublicAgentsURL", Description="URL of the Public Agents haproxy stats.", Value=Join("", [ "http://", GetAtt(elasticLBPublicAgents, "DNSName"), ":9090/haproxy?stats" ]))) # Write json to file jsonStr = t.to_json() fout = open(outfilename, "w") fout.write(jsonStr) fout.close() # Print the json to screen print(jsonStr)
def add_resource(self): self.PublicRouteTable = self.template.add_resource( RouteTable( "PublicRouteTable", VpcId=self.sceptre_user_data.get("VpcId"), Tags=Tags( Application=Ref("AWS::StackName"), Network="Public", Environment=self.sceptre_user_data.get("Environment"), Name=Join("-", ["RT-PU", self.sceptre_user_data.get("Project")]), ), )) self.PubSubnet = self.template.add_resource( Subnet( "PubSubnet", Tags=Tags( Application=Ref("AWS::StackName"), Environment=self.sceptre_user_data.get("Environment"), Network="Public", Name=Join("-", ["NT-PU", self.sceptre_user_data.get("Project")]), ), VpcId=self.sceptre_user_data.get("VpcId"), CidrBlock=Ref(self.PublicSubnet), AvailabilityZone=Ref(self.AvailabilityZone), MapPublicIpOnLaunch=True, )) self.PriSubnet = self.template.add_resource( Subnet( "PriSubnet", Tags=Tags( Application=Ref("AWS::StackName"), Environment=self.sceptre_user_data.get("Environment"), Network="Private", Name=Join("-", ["NT-PR", self.sceptre_user_data.get("Project")]), ), VpcId=self.sceptre_user_data.get("VpcId"), CidrBlock=Ref(self.PrivateSubnet), AvailabilityZone=Ref(self.AvailabilityZone), )) self.PublicRoute = self.template.add_resource( Route( "PublicRoute", GatewayId=self.igw_id, DestinationCidrBlock="0.0.0.0/0", RouteTableId=Ref(self.PublicRouteTable), )) self.PrivateRouteTable = self.template.add_resource( RouteTable( "PrivateRouteTable", VpcId=self.sceptre_user_data.get("VpcId"), Tags=Tags( Application=Ref("AWS::StackName"), Environment=self.sceptre_user_data.get("Environment"), Network="Private", Name=Join("-", ["RT-PR", self.sceptre_user_data.get("Project")]), ), )) self.PubSubnetRTAssoc = self.template.add_resource( SubnetRouteTableAssociation( "PubSubnetRTAssoc", SubnetId=Ref(self.PubSubnet), RouteTableId=Ref(self.PublicRouteTable), )) self.PriSubnetRTAssoc = self.template.add_resource( SubnetRouteTableAssociation( "PriSubnetRTAssoc", SubnetId=Ref(self.PriSubnet), RouteTableId=Ref(self.PrivateRouteTable), )) self.nat_eip = self.template.add_resource(EIP( 'NatEip', Domain="vpc", )) self.NatGateway = self.template.add_resource( NatGateway( "NatGateway", AllocationId=GetAtt(self.nat_eip, 'AllocationId'), SubnetId=Ref(self.PriSubnet), Tags=Tags( Application=Ref("AWS::StackName"), Environment=self.sceptre_user_data.get("Environment"), Name=Join( "-", ["NAT-PR", self.sceptre_user_data.get("Project")]), ), )) self.NatRoute = self.template.add_resource( Route( 'NatRoute', RouteTableId=Ref(self.PrivateRouteTable), DestinationCidrBlock='0.0.0.0/0', NatGatewayId=Ref(self.NatGateway), ))
public_route = Route( "PublicRoute", template=template, GatewayId=Ref(internet_gateway), DestinationCidrBlock="0.0.0.0/0", RouteTableId=Ref(public_route_table), ) # Holds public instances public_subnet_cidr = "10.0.1.0/24" public_subnet = Subnet( "PublicSubnet", template=template, VpcId=Ref(vpc), CidrBlock=public_subnet_cidr, ) SubnetRouteTableAssociation( "PublicSubnetRouteTableAssociation", template=template, RouteTableId=Ref(public_route_table), SubnetId=Ref(public_subnet), ) # NAT nat_ip = EIP( "NatIp",
from troposphere import Parameter, Ref, Template from troposphere.autoscaling import AutoScalingGroup, LaunchConfiguration from troposphere.policies import AutoScalingReplacingUpdate, AutoScalingRollingUpdate, UpdatePolicy from troposphere.ec2 import VPC, Subnet, SecurityGroup, SecurityGroupRule t = Template() vpc = t.add_resource(VPC('TestVPC', CidrBlock="10.10.0.0/16")) subnet1 = t.add_resource( Subnet('TestSubnet1', CidrBlock='10.10.10.0/24', VpcId=Ref(vpc), AvailabilityZone='ap-northeast-2a')) subnet2 = t.add_resource( Subnet('TestSubnet2', CidrBlock='10.10.20.0/24', VpcId=Ref(vpc), AvailabilityZone='ap-northeast-2b')) instanceSecurityGroup = t.add_resource( SecurityGroup('TestSecurityGroup', GroupDescription='Test SG', SecurityGroupIngress=[ SecurityGroupRule(IpProtocol='tcp', FromPort='22', ToPort='22', CidrIp='10.10.0.0/32'), SecurityGroupRule(IpProtocol='tcp', FromPort='80',
def build_template(sierrafile): template = Template() template.add_version('2010-09-09') template.add_metadata(build_interface(sierrafile.extra_params)) parameters = AttrDict( # Network Parameters vpc_cidr=template.add_parameter(Parameter( 'VpcCidr', Type='String', Default='192.172.0.0/16', )), subnet1_cidr=template.add_parameter(Parameter( 'Subnet1Cidr', Type='String', Default='192.172.1.0/24', )), subnet2_cidr=template.add_parameter(Parameter( 'Subnet2Cidr', Type='String', Default='192.172.2.0/24', )), # ECS Parameters cluster_size=template.add_parameter(Parameter( 'ClusterSize', Type='Number', Default=2, )), instance_type=template.add_parameter(Parameter( 'InstanceType', Type='String', Default='t2.medium' )), key_name=template.add_parameter(Parameter( 'KeyName', Type='AWS::EC2::KeyPair::KeyName', )), image_id=template.add_parameter(Parameter( 'ImageId', Type='AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>', Default=( '/aws/service/ecs/optimized-ami' '/amazon-linux/recommended/image_id' ), Description=( 'An SSM parameter that resolves to a valid AMI ID.' ' This is the AMI that will be used to create ECS hosts.' ' The default is the current recommended ECS-optimized AMI.' ) )), # Other Parameters github_token=template.add_parameter(Parameter( 'GitHubToken', Type='String', NoEcho=True, )), ) # Environment Variable Parameters for env_var_param, env_var_name in sierrafile.extra_params: template.add_parameter(Parameter( env_var_param, Type='String', NoEcho=True, )) # Resource Declarations # # Network network_vpc = template.add_resource(VPC( 'NetworkVpc', CidrBlock=Ref(parameters.vpc_cidr), Tags=Tags(Name=Ref('AWS::StackName')), )) network_ig = template.add_resource(InternetGateway( 'NetworkInternetGateway', Tags=Tags(Name=Ref('AWS::StackName')), )) vpc_attach = template.add_resource(VPCGatewayAttachment( 'NetworkInternetGatewayAttachment', InternetGatewayId=Ref(network_ig), VpcId=Ref(network_vpc), )) route_table = template.add_resource(RouteTable( 'NetworkRouteTable', VpcId=Ref(network_vpc), Tags=Tags(Name=Ref('AWS::StackName')), )) template.add_resource(Route( 'NetworkDefaultRoute', DependsOn=[vpc_attach.title], RouteTableId=Ref(route_table), DestinationCidrBlock='0.0.0.0/0', GatewayId=Ref(network_ig), )) subnet1 = template.add_resource(Subnet( 'NetworkSubnet1', VpcId=Ref(network_vpc), AvailabilityZone=Select(0, GetAZs()), MapPublicIpOnLaunch=True, CidrBlock=Ref(parameters.subnet1_cidr), Tags=Tags(Name=Sub('${AWS::StackName} (Public)')), )) subnet2 = template.add_resource(Subnet( 'NetworkSubnet2', VpcId=Ref(network_vpc), AvailabilityZone=Select(1, GetAZs()), MapPublicIpOnLaunch=True, CidrBlock=Ref(parameters.subnet2_cidr), Tags=Tags(Name=Sub('${AWS::StackName} (Public)')), )) template.add_resource(SubnetRouteTableAssociation( 'NetworkSubnet1RouteTableAssociation', RouteTableId=Ref(route_table), SubnetId=Ref(subnet1), )) template.add_resource(SubnetRouteTableAssociation( 'NetworkSubnet2RouteTableAssociation', RouteTableId=Ref(route_table), SubnetId=Ref(subnet2), )) elb = template.add_resource(LoadBalancer( ELB_NAME, Name=Sub('${AWS::StackName}-elb'), Type='network', Subnets=[Ref(subnet1), Ref(subnet2)], )) # # Cluster ecs_host_role = template.add_resource(Role( 'EcsHostRole', AssumeRolePolicyDocument=PolicyDocument( Statement=[Statement( Effect=Allow, Principal=Principal('Service', 'ec2.amazonaws.com'), Action=[awacs.sts.AssumeRole] )], ), ManagedPolicyArns=[ 'arn:aws:iam::aws:policy/' 'service-role/AmazonEC2ContainerServiceforEC2Role' ] )) ecs_host_profile = template.add_resource(InstanceProfile( 'EcsHostInstanceProfile', Roles=[Ref(ecs_host_role)] )) ecs_host_sg = template.add_resource(SecurityGroup( 'EcsHostSecurityGroup', GroupDescription=Sub('${AWS::StackName}-hosts'), VpcId=Ref(network_vpc), SecurityGroupIngress=[SecurityGroupRule( CidrIp='0.0.0.0/0', IpProtocol='-1' )] )) cluster = template.add_resource(Cluster( 'EcsCluster', ClusterName=Ref('AWS::StackName') )) autoscaling_name = 'EcsHostAutoScalingGroup' launch_conf_name = 'EcsHostLaunchConfiguration' launch_conf = template.add_resource(LaunchConfiguration( launch_conf_name, ImageId=Ref(parameters.image_id), InstanceType=Ref(parameters.instance_type), IamInstanceProfile=Ref(ecs_host_profile), KeyName=Ref(parameters.key_name), SecurityGroups=[Ref(ecs_host_sg)], UserData=Base64(Sub( '#!/bin/bash\n' 'yum install -y aws-cfn-bootstrap\n' '/opt/aws/bin/cfn-init -v' ' --region ${AWS::Region}' ' --stack ${AWS::StackName}' f' --resource {launch_conf_name}\n' '/opt/aws/bin/cfn-signal -e $?' ' --region ${AWS::Region}' ' --stack ${AWS::StackName}' f' --resource {autoscaling_name}\n' )), Metadata={ 'AWS::CloudFormation::Init': { 'config': { 'commands': { '01_add_instance_to_cluster': { 'command': Sub( f'echo ECS_CLUSTER=${{{cluster.title}}}' f' > /etc/ecs/ecs.config' ), } }, 'files': { '/etc/cfn/cfn-hup.conf': { 'mode': 0o400, 'owner': 'root', 'group': 'root', 'content': Sub( '[main]\n' 'stack=${AWS::StackId}\n' 'region=${AWS::Region}\n' ), }, '/etc/cfn/hooks.d/cfn-auto-reloader.conf': { 'content': Sub( '[cfn-auto-reloader-hook]\n' 'triggers=post.update\n' 'path=Resources.ContainerInstances.Metadata' '.AWS::CloudFormation::Init\n' 'action=/opt/aws/bin/cfn-init -v' ' --region ${AWS::Region}' ' --stack ${AWS::StackName}' f' --resource {launch_conf_name}\n' ), }, }, 'services': { 'sysvinit': { 'cfn-hup': { 'enabled': True, 'ensureRunning': True, 'files': [ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ] } } } } } } )) autoscaling_group = template.add_resource(AutoScalingGroup( autoscaling_name, VPCZoneIdentifier=[Ref(subnet1), Ref(subnet2)], LaunchConfigurationName=Ref(launch_conf), DesiredCapacity=Ref(parameters.cluster_size), MinSize=Ref(parameters.cluster_size), MaxSize=Ref(parameters.cluster_size), Tags=[{ 'Key': 'Name', 'Value': Sub('${AWS::StackName} - ECS Host'), 'PropagateAtLaunch': True, }], CreationPolicy=CreationPolicy( ResourceSignal=ResourceSignal(Timeout='PT15M'), ), UpdatePolicy=UpdatePolicy( AutoScalingRollingUpdate=AutoScalingRollingUpdate( MinInstancesInService=1, MaxBatchSize=1, PauseTime='PT5M', WaitOnResourceSignals=True, ), ), )) # # Services task_role = template.add_resource(Role( 'TaskExecutionRole', AssumeRolePolicyDocument=PolicyDocument( Statement=[Statement( Effect=Allow, Principal=Principal('Service', 'ecs-tasks.amazonaws.com'), Action=[awacs.sts.AssumeRole], )], ), ManagedPolicyArns=[ 'arn:aws:iam::aws:policy/' 'service-role/AmazonECSTaskExecutionRolePolicy' ], )) artifact_bucket = template.add_resource(Bucket( 'ArtifactBucket', DeletionPolicy='Retain', )) codebuild_role = template.add_resource(Role( 'CodeBuildServiceRole', Path='/', AssumeRolePolicyDocument=PolicyDocument( Version='2012-10-17', Statement=[ Statement( Effect=Allow, Principal=Principal( 'Service', 'codebuild.amazonaws.com' ), Action=[ awacs.sts.AssumeRole, ], ), ], ), Policies=[Policy( PolicyName='root', PolicyDocument=PolicyDocument( Version='2012-10-17', Statement=[ Statement( Resource=['*'], Effect=Allow, Action=[ awacs.ssm.GetParameters, ], ), Statement( Resource=['*'], Effect=Allow, Action=[ awacs.s3.GetObject, awacs.s3.PutObject, awacs.s3.GetObjectVersion, ], ), Statement( Resource=['*'], Effect=Allow, Action=[ awacs.logs.CreateLogGroup, awacs.logs.CreateLogStream, awacs.logs.PutLogEvents, ], ), ], ), )], )) codepipeline_role = template.add_resource(Role( 'CodePipelineServiceRole', Path='/', AssumeRolePolicyDocument=PolicyDocument( Version='2012-10-17', Statement=[ Statement( Effect=Allow, Principal=Principal( 'Service', 'codepipeline.amazonaws.com' ), Action=[ awacs.sts.AssumeRole, ], ), ], ), Policies=[Policy( PolicyName='root', PolicyDocument=PolicyDocument( Version='2012-10-17', Statement=[ Statement( Resource=[ Sub(f'${{{artifact_bucket.title}.Arn}}/*') ], Effect=Allow, Action=[ awacs.s3.GetBucketVersioning, awacs.s3.GetObject, awacs.s3.GetObjectVersion, awacs.s3.PutObject, ], ), Statement( Resource=['*'], Effect=Allow, Action=[ awacs.ecs.DescribeServices, awacs.ecs.DescribeTaskDefinition, awacs.ecs.DescribeTasks, awacs.ecs.ListTasks, awacs.ecs.RegisterTaskDefinition, awacs.ecs.UpdateService, awacs.codebuild.StartBuild, awacs.codebuild.BatchGetBuilds, awacs.iam.PassRole, ], ), ], ), )], )) log_group = template.add_resource(LogGroup( 'LogGroup', LogGroupName=Sub('/ecs/${AWS::StackName}'), )) if any(conf.pipeline.enable for conf in sierrafile.services.values()): project = template.add_resource(Project( 'CodeBuildProject', Name=Sub('${AWS::StackName}-build'), ServiceRole=Ref(codebuild_role), Artifacts=Artifacts(Type='CODEPIPELINE'), Source=Source(Type='CODEPIPELINE'), Environment=Environment( ComputeType='BUILD_GENERAL1_SMALL', Image='aws/codebuild/docker:17.09.0', Type='LINUX_CONTAINER', ), )) for name, settings in sierrafile.services.items(): task_definition = template.add_resource(TaskDefinition( f'{name}TaskDefinition', RequiresCompatibilities=['EC2'], Cpu=str(settings.container.cpu), Memory=str(settings.container.memory), NetworkMode='bridge', ExecutionRoleArn=Ref(task_role.title), ContainerDefinitions=[ ContainerDefinition( Name=f'{name}', Image=settings.container.image, Memory=str(settings.container.memory), Essential=True, PortMappings=[ PortMapping( ContainerPort=settings.container.port, Protocol='tcp', ), ], Environment=[ troposphere.ecs.Environment(Name=k, Value=v) for k, v in sierrafile.env_vars.items() if k in settings.get('environment', []) ], LogConfiguration=LogConfiguration( LogDriver='awslogs', Options={ 'awslogs-region': Ref('AWS::Region'), 'awslogs-group': Ref(log_group.title), 'awslogs-stream-prefix': Ref('AWS::StackName'), }, ), ), ], )) target_group = template.add_resource(TargetGroup( f'{name}TargetGroup', Port=settings.container.port, Protocol='TCP', VpcId=Ref(network_vpc), Tags=Tags(Name=Sub(f'${{AWS::StackName}}-{name}')), )) listener = template.add_resource(Listener( f'{name}ElbListener', LoadBalancerArn=Ref(elb), Port=settings.container.port, Protocol='TCP', DefaultActions=[ Action(TargetGroupArn=Ref(target_group), Type='forward') ], )) service = template.add_resource(Service( f'{name}Service', Cluster=Ref(cluster), ServiceName=f'{name}-service', DependsOn=[autoscaling_group.title, listener.title], DesiredCount=settings.container.count, TaskDefinition=Ref(task_definition), LaunchType='EC2', LoadBalancers=[ troposphere.ecs.LoadBalancer( ContainerName=f'{name}', ContainerPort=settings.container.port, TargetGroupArn=Ref(target_group), ), ], )) if settings.pipeline.enable: pipeline = template.add_resource(Pipeline( f'{name}Pipeline', RoleArn=GetAtt(codepipeline_role, 'Arn'), ArtifactStore=ArtifactStore( Type='S3', Location=Ref(artifact_bucket), ), Stages=[ Stages( Name='Source', Actions=[Actions( Name='Source', ActionTypeId=ActionTypeId( Category='Source', Owner='ThirdParty', Version='1', Provider='GitHub', ), OutputArtifacts=[ OutputArtifacts(Name=f'{name}Source'), ], RunOrder='1', Configuration={ 'Owner': settings.pipeline.user, 'Repo': settings.pipeline.repo, 'Branch': settings.pipeline.branch, 'OAuthToken': Ref(parameters.github_token), }, )], ), Stages( Name='Build', Actions=[Actions( Name='Build', ActionTypeId=ActionTypeId( Category='Build', Owner='AWS', Version='1', Provider='CodeBuild', ), InputArtifacts=[ InputArtifacts(Name=f'{name}Source'), ], OutputArtifacts=[ OutputArtifacts(Name=f'{name}Build'), ], RunOrder='1', Configuration={ 'ProjectName': Ref(project), }, )], ), Stages( Name='Deploy', Actions=[Actions( Name='Deploy', ActionTypeId=ActionTypeId( Category='Deploy', Owner='AWS', Version='1', Provider='ECS', ), InputArtifacts=[ InputArtifacts(Name=f'{name}Build') ], RunOrder='1', Configuration={ 'ClusterName': Ref(cluster), 'ServiceName': Ref(service), 'FileName': 'image.json', }, )], ), ], )) template.add_resource(Webhook( f'{name}CodePipelineWebhook', Name=Sub(f'${{AWS::StackName}}-{name}-webhook'), Authentication='GITHUB_HMAC', AuthenticationConfiguration=AuthenticationConfiguration( SecretToken=Ref(parameters.github_token), ), Filters=[FilterRule( JsonPath='$.ref', MatchEquals=f'refs/heads/{settings.pipeline.branch}' )], TargetAction='Source', TargetPipeline=Ref(pipeline), TargetPipelineVersion=1, RegisterWithThirdParty=True, )) return template
subnetlist = [ "PUBA", "PUBB", "PRVA", "PRVB"] cidr_list = [ "10.0.0.0/26", "10.0.0.64/26", "10.0.0.128/26", "10.0.0.192/26"] i = 0 for subnet in subnetlist: resources[ subnet ] = template.add_resource(Subnet( subnet, DependsOn = [ resource for resource in [ "VPC" ] ], AvailabilityZone = azlist[ 0 ] if "A" in subnet else azlist[ 1 ], CidrBlock = cidr_list[i], Tags = [ { "Key": "Name", "Value": Join("-", [ Ref(parameters[ "Project" ]), subnet.lower() ]) }, { "Key": "Project", "Value": Ref(parameters[ "Project" ]) }], VpcId = Ref(resources[ "VPC" ]))) if "PRV" in subnet: if "A" in subnet: routetable = resources[ "PrivateRouteTableA" ] else: routetable = resources[ "PrivateRouteTableB" ] else: routetable = resources[ "PublicRouteTable" ] template.add_resource(SubnetRouteTableAssociation( "SubnetRouteTableAssociation" + subnet, DependsOn = [ resource for resource in [ routetable.name,
)) redshiftclustersubnetgroup = t.add_resource(ClusterSubnetGroup( "RedshiftClusterSubnetGroup", Description="Cluster subnet group", SubnetIds=Ref("Subnet"), )) vpc = t.add_resource(VPC( "VPC", CidrBlock="10.0.0.0/16", )) subnet = t.add_resource(Subnet( "Subnet", CidrBlock="10.0.0.0/24", VpcId=Ref("VPC"), )) internetgateway = t.add_resource(InternetGateway( "InternetGateway", )) gatewayattachment = t.add_resource(VPCGatewayAttachment( "GatewayAttachment", VpcId=Ref("VPC"), InternetGatewayId=Ref("InternetGateway"), )) securitygroupingress1 = SecurityGroupIngress( "SecurityGroupIngress1",
}, }) ref_stack_id = Ref('AWS::StackId') ref_region = Ref('AWS::Region') ref_stack_name = Ref('AWS::StackName') # VPC Parameters VPC = t.add_resource( VPC(config_file['vpc']['name'], CidrBlock=config_file['vpc']['cidr'], Tags=Tags(Application=ref_stack_id))) subnet = t.add_resource( Subnet(config_file['subnet']['name'], CidrBlock=config_file['subnet']['cidr'], VpcId=Ref(VPC), Tags=Tags(Application=ref_stack_id))) internetGateway = t.add_resource( InternetGateway(config_file['igw']['name'], Tags=Tags(Application=ref_stack_id))) gatewayAttachment = t.add_resource( VPCGatewayAttachment('AttachGateway', VpcId=Ref(VPC), InternetGatewayId=Ref(internetGateway))) routeTable = t.add_resource( RouteTable(config_file['rtable']['name'], VpcId=Ref(VPC), Tags=Tags(Application=ref_stack_id)))
'PrivateSubnet': 'veri-PrivateSubnet-id', 'PublicRouteTable': 'veri-PublicRoute-id', 'PrivateRouteTable': 'veri-PrivateRoute-id', 'NatGateway': 'veri-NatGateway-id' } }) VPC = t.add_resource( VPC('VPC', CidrBlock=FindInMap(Ref(environmentType_param), 'cidr', 'Vpc'), Tags=Tags(Name=FindInMap(Ref(environmentType_param), 'tags', 'Vpc')))) PublicSubnet = t.add_resource( Subnet('PublicSubnet', CidrBlock=FindInMap(Ref(environmentType_param), 'cidr', 'Public'), VpcId=Ref(VPC), Tags=Tags(Name=FindInMap(Ref(environmentType_param), 'tags', 'PublicSubnet')))) PrivateSubnet = t.add_resource( Subnet('PrivateSubnet', CidrBlock=FindInMap(Ref(environmentType_param), 'cidr', 'Private'), VpcId=Ref(VPC), Tags=Tags(Name=FindInMap(Ref(environmentType_param), 'tags', 'PrivateSubnet')))) InternetGateway = t.add_resource( InternetGateway( 'InternetGateway', Tags=Tags(Name=FindInMap(Ref(environmentType_param), 'tags', 'Igw'))))
SubnetId=Ref("ELBSubnet2"), RouteTableId=Ref("ELBRouteTable2"), )) ELBRouteTableAssociation3 = t.add_resource( SubnetRouteTableAssociation( "ELBRouteTableAssociation3", SubnetId=Ref("ELBSubnet3"), RouteTableId=Ref("ELBRouteTable3"), )) ELBSubnet1 = t.add_resource( Subnet( "ELBSubnet1", VpcId=Ref("VPC"), AvailabilityZone="eu-west-1a", CidrBlock="10." + str(environment_index) + ".32.0/20", Tags=Tags(Name=Join("-", [Ref("AWS::StackName"), "elb", "eu-west-1a"]), ), )) ELBSubnet2 = t.add_resource( Subnet( "ELBSubnet2", VpcId=Ref("VPC"), AvailabilityZone="eu-west-1b", CidrBlock="10." + str(environment_index) + ".96.0/20", Tags=Tags(Name=Join("-", [Ref("AWS::StackName"), "elb", "eu-west-1b"]), ), )) ELBSubnet3 = t.add_resource(
def vpcTemplate(name, app, env, cidrBlock, publicSubnets, privateSubnets): template = Template() vpc = template.add_resource( VPC( "VPC" + name + app + env, CidrBlock=cidrBlock, EnableDnsSupport=True, EnableDnsHostnames=True, Tags=Tags( Env=env, Name=name + "-" + env, ), )) internetGateway = template.add_resource( InternetGateway( "InternetGateway" + name + app + env, Tags=Tags( Env=env, Name="igw-" + env, ), )) gatewayAttachment = template.add_resource( VPCGatewayAttachment("InternetGatewayAttachment" + name + app + env, InternetGatewayId=Ref(internetGateway), VpcId=Ref(vpc), DependsOn="VPC" + name + app + env)) publicRouteTable = template.add_resource( RouteTable( "PublicRouteTable", VpcId=Ref(vpc), Tags=Tags( Name="rt-public" + env, Env=env, ), )) internetGWRoute = template.add_resource( Route("RouteToIGW", RouteTableId=Ref(publicRouteTable), DestinationCidrBlock='0.0.0.0/0', GatewayId=Ref(internetGateway))) privateNetworkAcl = template.add_resource( NetworkAcl( "PrivateNetworkAcl", VpcId=Ref(vpc), Tags=Tags(Name="PrivateNetworkAcl" + env, ), )) zones = ["a", "b", "c"] for index, subnet in enumerate(privateSubnets): template.add_resource( Subnet("PrivateSubnet" + zones[index], CidrBlock=subnet, AvailabilityZone=Join("", [Ref("AWS::Region"), zones[index]]), MapPublicIpOnLaunch=False, Tags=Tags(Env=env, Name="Private-Subnet-" + zones[index]), VpcId=Ref(vpc), DependsOn="VPC" + name + app + env)) template.add_resource( RouteTable("PrivateRouteTable" + zones[index], VpcId=Ref(vpc), Tags=Tags( Name="rt-private" + env + "-" + zones[index], Env=env, ), DependsOn="VPC" + name + app + env)) template.add_resource(EIP("EIP" + zones[index], )) template.add_resource( NatGateway("NatGWZone" + zones[index], AllocationId=GetAtt("EIP" + zones[index], 'AllocationId'), SubnetId=Ref("PublicSubnet" + zones[index]), DependsOn="PublicSubnet" + zones[index])) template.add_resource( Route('NatRoute' + zones[index], RouteTableId=Ref("PrivateRouteTable" + zones[index]), DestinationCidrBlock='0.0.0.0/0', NatGatewayId=Ref("NatGWZone" + zones[index]), DependsOn="PrivateRouteTable" + zones[index])) template.add_resource( SubnetRouteTableAssociation( "PrivateSubnetRouteTable" + zones[index], RouteTableId=Ref("PrivateRouteTable" + zones[index]), SubnetId=Ref("PrivateSubnet" + zones[index]), DependsOn="PrivateRouteTable" + zones[index])) template.add_resource( SubnetNetworkAclAssociation("PrivateNetworkAclAss" + zones[index], SubnetId=Ref("PrivateSubnet" + zones[index]), NetworkAclId=Ref(privateNetworkAcl), DependsOn="PrivateNetworkAcl")) for index, subnet in enumerate(publicSubnets): template.add_resource( Subnet("PublicSubnet" + zones[index], CidrBlock=subnet, AvailabilityZone=Join("", [Ref("AWS::Region"), zones[index]]), MapPublicIpOnLaunch=True, Tags=Tags(Env=env, Name="Public-Subnet-" + zones[index]), VpcId=Ref(vpc), DependsOn="VPC" + name + app + env)) template.add_resource( SubnetRouteTableAssociation( "PublicSubnetRouteTable" + zones[index], RouteTableId=Ref(publicRouteTable), SubnetId=Ref("PublicSubnet" + zones[index]), DependsOn="VPC" + name + app + env)) template.add_resource( NetworkAclEntry("PrivateNetworkAclEntryIngress" + env, CidrBlock=cidrBlock, Egress=False, NetworkAclId=Ref(privateNetworkAcl), Protocol=-1, RuleAction="allow", RuleNumber=200, DependsOn="PrivateNetworkAcl")) template.add_resource( NetworkAclEntry("PrivateNetworkAclEntryEgress" + env, CidrBlock=cidrBlock, Egress=True, NetworkAclId=Ref(privateNetworkAcl), Protocol=-1, RuleAction="allow", RuleNumber=200, DependsOn="PrivateNetworkAcl")) for zone in zones: template.add_output( Output( "PublicSubnetOutput" + zone, Value=Ref("PublicSubnet" + zone), Export=Export("PublicSubnet" + env + zone), )) template.add_output( Output("PrivateSubnetOutput" + zone, Value=Ref("PrivateSubnet" + zone), Export=Export("PrivateSubnet" + env + zone))) template.add_output( Output("VPCOutput" + env, Value=Ref(vpc), Export=Export("VPC" + env))) return (template.to_json())
"PublicRouteTable", VpcId=Ref(vpc), )) public_route = template.add_resource( Route( "PublicRoute", GatewayId=Ref(internet_gateway), DestinationCidrBlock="0.0.0.0/0", RouteTableId=Ref(public_route_table), )) public_subnet = template.add_resource( Subnet( "PublicSubnet", VpcId=Ref(vpc), CidrBlock=public_subnet_cidr, )) template.add_resource( SubnetRouteTableAssociation( "PublicSubnetRouteTableAssociation", RouteTableId=Ref(public_route_table), SubnetId=Ref(public_subnet), )) nat_ip = template.add_resource(EIP( "NatIp", Domain="vpc", ))
)) NatHTTPSIngress = t.add_resource( SecurityGroupIngress( "NatHTTPSIngress", ToPort="443", FromPort="443", IpProtocol="tcp", GroupId=Ref(NatSG), CidrIp=Ref(privatesubnetcidr_param), )) PublicSubnet = t.add_resource( Subnet("PublicSubnet", VpcId=Ref("VPC"), AvailabilityZone=Ref(availavilityzone_param), CidrBlock=Ref(publicsubnetcidr_param), Tags=Tags(Name=Join("", [Ref("AWS::StackName"), "-public"]), ))) PrivateSubnet = t.add_resource( Subnet("PrivateSubnet", VpcId=Ref("VPC"), AvailabilityZone=Ref(availavilityzone_param), CidrBlock=Ref(privatesubnetcidr_param), Tags=Tags(Name=Join("", [Ref("AWS::StackName"), "-private"]), ))) InternetGateway = t.add_resource( InternetGateway("InternetGateway", Tags=Tags(Name=Ref("AWS::StackName"), ))) DefaultPublicRoute = t.add_resource(
)) VPC = template.add_resource( VPC( "VPC", EnableDnsSupport=True, CidrBlock=Ref(VpcCIDR), EnableDnsHostnames=True, Tags=Tags(Name=Ref(EnvironmentName), ), )) Private2 = template.add_resource( Subnet( "Private2", Tags=Tags(Name=Sub("${EnvironmentName} Private Subnet (AZ2)"), ), VpcId=Ref(VPC), CidrBlock=Ref(Private2CIDR), MapPublicIpOnLaunch=False, AvailabilityZone=Select(1, GetAZs("")), )) Private1 = template.add_resource( Subnet( "Private1", Tags=Tags(Name=Sub("${EnvironmentName} Private Subnet (AZ1)"), ), VpcId=Ref(VPC), CidrBlock=Ref(Private1CIDR), MapPublicIpOnLaunch=False, AvailabilityZone=Select(0, GetAZs("")), )) IgwSubnet2 = template.add_resource(
Tags=Tags(Name=Join("-", [Ref("AWS::StackName"), "private-rt"]), ), )) internetRoute = t.add_resource( Route("RouteToInternet", DestinationCidrBlock="0.0.0.0/0", GatewayId=Ref(internetGateway), RouteTableId=Ref(publicRouteTable), DependsOn=gatewayAttachment.title)) # private subnetworks subnetPrivateA = t.add_resource( Subnet("StackPrivateSubnetA", AvailabilityZone=Join("", [Ref("AWS::Region"), "a"]), CidrBlock=VPC_PRIVATE_A, MapPublicIpOnLaunch=False, Tags=Tags(Name=Join( "", [Ref("AWS::StackName"), " private subnet A"]), ), VpcId=Ref(vpc))) t.add_resource( SubnetRouteTableAssociation("PrivateSubnetARouteTable", RouteTableId=Ref(privateRouteTable), SubnetId=Ref(subnetPrivateA))) subnetPrivateB = t.add_resource( Subnet("StackPrivateSubnetB", AvailabilityZone=Join("", [Ref("AWS::Region"), "b"]), CidrBlock=VPC_PRIVATE_B, MapPublicIpOnLaunch=False, Tags=Tags(Name=Join(
############################# VPC AND SUBNET ########################################### VPC = template.add_resource( VPC('VPC', CidrBlock=vpc.CidrBlock, EnableDnsSupport=True, EnableDnsHostnames=True, Tags=Tags(Name=environmentString + "VPC", Stack=Ref("AWS::StackName")))) vpc.instance = VPC for f in vpc.subnets: subnet = template.add_resource( Subnet(f.name, CidrBlock=f.CidrBlock, VpcId=Ref(VPC), MapPublicIpOnLaunch=f.MapPublicIpOnLaunch, AvailabilityZone=Select(f.AvailabilityZone, GetAZs()), Tags=Tags(Name=environmentString + f.name, Stack=Ref("AWS::StackName")))) f.instance = subnet ############################# ADD GATEWAY AND ROLE ########################### internetGateway = template.add_resource( InternetGateway('InternetGateway', Tags=Tags(Name=environmentString + "Internet-Gateway", Stack=Ref("AWS::StackName")))) gatewayAttachment = template.add_resource( VPCGatewayAttachment('AttachGateway', VpcId=Ref(VPC), InternetGatewayId=Ref(internetGateway)))
def build(ssh_keypair_name): template = Template() template.set_version("2010-09-09") keyname_param = template.add_parameter( Parameter( "KeyName", ConstraintDescription="must be the name of an existing EC2 KeyPair.", Description="Name of an existing EC2 KeyPair to enable SSH access to \ the instance", Type="AWS::EC2::KeyPair::KeyName", Default=ssh_keypair_name, ) ) sshlocation_param = template.add_parameter( Parameter( "SSHLocation", Description=" The IP address range that can be used to SSH to the EC2 \ instances", Type="String", MinLength="9", MaxLength="18", Default="0.0.0.0/0", AllowedPattern=r"(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})", ConstraintDescription=("must be a valid IP CIDR range of the form x.x.x.x/x."), ) ) instanceType_param = template.add_parameter( Parameter( "InstanceType", Type="String", Description="WebServer EC2 instance type", Default="t3a.small", AllowedValues=[ "t2.micro", "t2.small", "t2.medium", "t3a.small", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", ], ConstraintDescription="must be a valid EC2 instance type.", ) ) template.add_mapping( "AWSRegion2AMI", { "us-east-1": {"image": "ami-0d915a031cabac0e0"}, "us-east-2": {"image": "ami-0b97435028ca44fcc"}, "us-west-1": {"image": "ami-068d0753a46192935"}, "us-west-2": {"image": "ami-0c457f229774da543"}, "eu-west-1": {"image": "ami-046c6a0123bf94619"}, "eu-west-2": {"image": "ami-0dbe8ba0cd21ea12b"}, "eu-west-3": {"image": "ami-041bf9180061ce7ea"}, "eu-central-1": {"image": "ami-0f8184e6f30cc0c33"}, "eu-north-1": {"image": "ami-08dd1b893371bcaac"}, "ap-south-1": {"image": "ami-0ff23052091536db2"}, "ap-southeast-1": {"image": "ami-0527e82bae7c51958"}, "ap-southeast-2": {"image": "ami-0bae8773e653a32ec"}, "ap-northeast-1": {"image": "ami-060741a96307668be"}, "ap-northeast-2": {"image": "ami-0d991ac4f545a6b34"}, "sa-east-1": {"image": "ami-076f350d5a5ec448d"}, "ca-central-1": {"image": "ami-0071deaa12b66d1bf"}, }, ) vpc = template.add_resource(VPC("VPC", CidrBlock="10.0.0.0/16")) subnet = template.add_resource(Subnet("Subnet", CidrBlock="10.0.0.0/24", VpcId=Ref(vpc))) internet_gateway = template.add_resource(InternetGateway("InternetGateway")) attach_gateway = template.add_resource( VPCGatewayAttachment("AttachGateway", VpcId=Ref(vpc), InternetGatewayId=Ref(internet_gateway)) ) route_table = template.add_resource(RouteTable("RouteTable", VpcId=Ref(vpc))) template.add_resource( Route( "Route", DependsOn=attach_gateway, GatewayId=Ref(internet_gateway), DestinationCidrBlock="0.0.0.0/0", RouteTableId=Ref(route_table), ) ) template.add_resource( SubnetRouteTableAssociation("SubnetRouteTableAssociation", SubnetId=Ref(subnet), RouteTableId=Ref(route_table),) ) network_acl = template.add_resource(NetworkAcl("NetworkAcl", VpcId=Ref(vpc),)) template.add_resource( NetworkAclEntry( "InboundHTTPNetworkAclEntry", NetworkAclId=Ref(network_acl), RuleNumber="100", Protocol="6", PortRange=PortRange(To="80", From="80"), Egress="false", RuleAction="allow", CidrBlock="0.0.0.0/0", ) ) template.add_resource( NetworkAclEntry( "InboundSSHNetworkAclEntry", NetworkAclId=Ref(network_acl), RuleNumber="101", Protocol="6", PortRange=PortRange(To="22", From="22"), Egress="false", RuleAction="allow", CidrBlock="0.0.0.0/0", ) ) template.add_resource( NetworkAclEntry( "InboundResponsePortsNetworkAclEntry", NetworkAclId=Ref(network_acl), RuleNumber="102", Protocol="6", PortRange=PortRange(To="65535", From="1024"), Egress="false", RuleAction="allow", CidrBlock="0.0.0.0/0", ) ) template.add_resource( NetworkAclEntry( "OutBoundHTTPNetworkAclEntry", NetworkAclId=Ref(network_acl), RuleNumber="100", Protocol="6", PortRange=PortRange(To="80", From="80"), Egress="true", RuleAction="allow", CidrBlock="0.0.0.0/0", ) ) template.add_resource( NetworkAclEntry( "OutBoundHTTPSNetworkAclEntry", NetworkAclId=Ref(network_acl), RuleNumber="101", Protocol="6", PortRange=PortRange(To="443", From="443"), Egress="true", RuleAction="allow", CidrBlock="0.0.0.0/0", ) ) template.add_resource( NetworkAclEntry( "OutBoundResponsePortsNetworkAclEntry", NetworkAclId=Ref(network_acl), RuleNumber="102", Protocol="6", PortRange=PortRange(To="65535", From="1024"), Egress="true", RuleAction="allow", CidrBlock="0.0.0.0/0", ) ) template.add_resource( SubnetNetworkAclAssociation("SubnetNetworkAclAssociation", SubnetId=Ref(subnet), NetworkAclId=Ref(network_acl),) ) instance_security_group = template.add_resource( SecurityGroup( "InstanceSecurityGroup", GroupDescription="Enable SSH access via port 22", SecurityGroupIngress=[ SecurityGroupRule(IpProtocol="tcp", FromPort="22", ToPort="22", CidrIp=Ref(sshlocation_param)), SecurityGroupRule(IpProtocol="tcp", FromPort="80", ToPort="80", CidrIp="0.0.0.0/0"), ], VpcId=Ref(vpc), ) ) server_instance = template.add_resource( Instance( "ServerInstance", ImageId=FindInMap("AWSRegion2AMI", Ref("AWS::Region"), "image"), InstanceType=Ref(instanceType_param), KeyName=Ref(keyname_param), NetworkInterfaces=[ NetworkInterfaceProperty( GroupSet=[Ref(instance_security_group)], AssociatePublicIpAddress="true", DeviceIndex="0", DeleteOnTermination="true", SubnetId=Ref(subnet), ) ], ) ) template.add_output([Output("ServerIP", Value=GetAtt(server_instance, "PublicIp"))]) return template