def gen_postgis_function(): PostGisFunction = Function( "PostGisProvisionerFunction", Code=Code( S3Bucket=Ref("BucketName"), S3Key=Ref("BucketKey"), ), FunctionName=Sub("${AWS::StackName}-PostGisProvisioner"), Handler="postgis_provisioner.lambda_handler", Role=GetAtt("PostgisProvisionerExecutionRole", "Arn"), Timeout="60", Runtime="python3.6", VpcConfig=VPCConfig( SecurityGroupIds=[Ref("PostGisProvisionerSg")], SubnetIds=[ Select( 0, Split( ",", ImportValue( Sub("${NetworkName}-network-vpc-PrivateSubnets"))) ), Select( 1, Split( ",", ImportValue( Sub("${NetworkName}-network-vpc-PrivateSubnets")))) ])) return PostGisFunction
def items(config: Config) -> Iterable[AWSObject]: role = make_role(config) yield role func, sg = PackagedFunction.make(config, role) yield func if sg: yield sg if config.OPENAPI_FILE: yield awsλ.Permission( 'LambdaInvokePermission', FunctionName=Ref(func), Principal='apigateway.amazonaws.com', Action=awacs.awslambda.InvokeFunction.JSONrepr(), ) with config.openapi() as f: openapi_data = yaml.safe_load(f) yield APIContribution( 'BriteApiContribution', Version='1.0', ServiceToken=ImportValue(Sub('${Stage}-ApiContribution-Provider')), LambdaProxyArn=GetAtt(func, 'Arn'), RestApiId=ImportValue(Sub('${Stage}-BriteAPI')), SwaggerDefinition=openapi_data, ) else: warnings.warn('No OpenAPI file passed; not emitting BriteAPI')
def __create_load_balancer(): template = Template() load_balancer = template.add_resource(resource=LoadBalancer( title='SampleFargateLoadBalancer', Name='sample-fargate-load-balancer', Subnets=[ ImportValue(CommonResource.ExportName.PUBLIC_SUBNET_A_ID.value), ImportValue(CommonResource.ExportName.PUBLIC_SUBNET_B_ID.value) ], SecurityGroups=[ImportValue(ExportName.ALB_SECURITY_GROUP.value)], Scheme='internet-facing')) target_group = template.add_resource(resource=TargetGroup( title='SampleFargateTargetGroup', Port=80, Protocol='HTTP', TargetType='ip', VpcId=ImportValue(CommonResource.ExportName.VPC_ID.value))) template.add_output(output=Output(title=target_group.title, Value=Ref(target_group), Export=Export( name=ExportName.TARGET_GROUP.value))) template.add_resource(resource=Listener( title='SampleFargateListener', DefaultActions=[ Action(Type='forward', TargetGroupArn=Ref(target_group)) ], LoadBalancerArn=Ref(load_balancer), Port=80, Protocol='HTTP')) output_template_file(template, 'alb.yml') return target_group
def add_alb_secuirty_group(self): ''' Add security group to load balancer ''' self.cfn_template.add_resource(SecurityGroup( title=constants.ALB_SG, GroupDescription='Load balancer security group', SecurityGroupIngress=[ SecurityGroupRule( IpProtocol='tcp', FromPort=int('8228'), ToPort=int('8228'), CidrIp=Ref('CIDRBLK'), ), SecurityGroupRule( IpProtocol='-1', FromPort=int('-1'), ToPort=int('-1'), SourceSecurityGroupId=ImportValue(Sub('${Environment}-AppSecurityGroup')), ) ], SecurityGroupEgress=[ SecurityGroupRule( IpProtocol='-1', CidrIp='0.0.0.0/0' ) ], VpcId=ImportValue(Sub('${Environment}-${VpcId}')) )) return self.cfn_template
def add_ecs_service(self): ''' Add ECS service ''' self.cfn_template.add_resource( Service( title=constants.SERVICE, Cluster=ImportValue(Sub('${Environment}-CLUSTER')), LaunchType='EC2', DesiredCount=int('1'), TaskDefinition=Ref(constants.TASK), Role=Ref(constants.SERVICE_ROLE), DeploymentConfiguration=DeploymentConfiguration( MaximumPercent=int('200'), MinimumHealthyPercent=int('100')), LoadBalancers=[ LoadBalancer(ContainerName='anchore-engine', ContainerPort=int('8228'), TargetGroupArn=ImportValue( Sub('${Environment}-TARGETGROUP-ARN'))) ], PlacementStrategies=[ PlacementStrategy(Type='spread', Field='attribute:ecs.availability-zone'), PlacementStrategy(Type='spread', Field='instanceId') ])) return self.cfn_template
def gen_sg(): sg = SecurityGroup("DBSecurityGroup", GroupDescription="Enable Postgres on the inbound port", VpcId=ImportValue( Sub("${NetworkName}-network-vpc-VpcId"))) self_sg_rule = SecurityGroupIngress( "IngressFromSelfRule", GroupId=Ref("DBSecurityGroup"), IpProtocol="tcp", FromPort="5432", ToPort="5432", SourceSecurityGroupId=Ref("DBSecurityGroup"), ) lambda_sg_rule = SecurityGroupIngress( "IngressFromLambdaRule", Condition="InstallPostgis", GroupId=Ref("DBSecurityGroup"), IpProtocol="tcp", FromPort="5432", ToPort="5432", SourceSecurityGroupId=ImportValue( Sub("${ProvisionerStackName}-SecurityGroup")), ) return [sg, self_sg_rule, lambda_sg_rule]
def __init__(self, leaf_title, availability_zones, template, tree_name, database_config): """ Create an RDS as a leaf, part of cross referenced stack :param leaf_title: title of the API Gateway as part of cross referenced stack :param availability_zones: List of availability zones RDS resources can use :param tree_name: name of cross referenced stack :param template: Troposphere stack to append resources to :param database_config: object containing database related variables """ self.leaf_title = leaf_title self.availability_zones = availability_zones self.tree_name = tree_name self.tree_config = None self.set_tree_config(template=template, availability_zones=availability_zones, tree_name=tree_name) self.tree_config.private_hosted_zone_id = ImportValue( self.tree_name + '-PrivateHostedZoneId') self.tree_config.private_hosted_zone_domain = ImportValue( self.tree_name + '-PrivateHostedZoneDomain') super(DatabaseLeaf, self).__init__(template=template, title=leaf_title, network_config=self.tree_config, database_config=database_config) self.template.add_output( Output('rdsSecurityGroup', Description='RDS Security group', Value=self.security_group, Export=Export(self.tree_name + '-' + self.leaf_title + '-SecurityGroup')))
def configure_alb(self, t, service): service_target_group = t.add_resource(elasticloadbalancingv2.TargetGroup( self.resource_name_format % ('ServiceTargetGroup'), Port=80, Protocol="HTTP", HealthCheckPath=self.healthcheck_path, HealthCheckIntervalSeconds=self.healthcheck_interval, HealthCheckTimeoutSeconds=self.healthcheck_interval - 1, HealthyThresholdCount=2, UnhealthyThresholdCount=5, VpcId=ImportValue(Sub(self.imports_format % ('VpcId'))), TargetGroupAttributes=[ elasticloadbalancingv2.TargetGroupAttribute(Key=key, Value=value) for (key, value) in sorted(self.target_group_attributes().items()) ] )) listener_rule = t.add_resource(elasticloadbalancingv2.ListenerRule( self.resource_name_format % ('SecureListenerRule'), ListenerArn=ImportValue(Sub(self.imports_format % ('PublicListener' if self.public else 'InternalListener'))), Priority=self.priority, Actions=[elasticloadbalancingv2.Action(Type="forward", TargetGroupArn=Ref(service_target_group))], Conditions=[elasticloadbalancingv2.Condition(Field="host-header", Values=self.domains)] )) service.DependsOn.append(listener_rule.title) service.LoadBalancers = [ ecs.LoadBalancer( ContainerName=self.container_name, ContainerPort=self.port, TargetGroupArn=Ref(service_target_group) ) ]
def __init__(self, leaf_title, template, dependencies, public_cidr, public_hosted_zone_name, cd_service_role_arn, availability_zones, tree_name, elb_config, asg_config, keypair): """ Create autoscaling resources within a cross referenced stack :param leaf_title: title of the amazonia leaf and associated resources to be used in cloud formation :param public_cidr: public cidr pattern, this can either allow public access or restrict to an organisation :param public_hosted_zone_name: the hosted zone name to create R53 records in :param cd_service_role_arn: ARN of the code deploy service role :param availability_zones: List of availability zones autoscaling resources can use :param tree_name: name of cross referenced stack :param keypair: keypair to use with autoscaling instances :param template: Troposphere template to append resources to :param dependencies: list of unit names this unit needs access to :param elb_config: config related to Elastic Load Balancer :param asg_config: config related to AutoScaling Group """ self.set_tree_config(template=template, availability_zones=availability_zones, tree_name=tree_name) self.tree_config.public_hosted_zone_name = public_hosted_zone_name self.tree_config.cd_service_role_arn = cd_service_role_arn self.tree_config.availability_zones = availability_zones self.tree_config.keypair = keypair self.tree_config.public_cidr = public_cidr self.tree_config.private_hosted_zone_id = ImportValue( self.tree_name + '-PrivateHostedZoneId') self.tree_config.private_hosted_zone_domain = ImportValue( self.tree_name + '-PrivateHostedZoneDomain') super(AutoscalingLeaf, self).__init__(leaf_title, template, self.tree_config, elb_config, asg_config, dependencies, asg_config.ec2_scheduled_shutdown) self.template.add_output( Output('elbSecurityGroup', Description='ELB Security group', Value=self.elb.security_group, Export=Export(tree_name + '-' + leaf_title + '-SecurityGroup'))) self.template.add_output( Output('elbEndpoint', Description='Endpoint of the {0} ELB'.format(self.title), Value=GetAtt(self.elb.trop_elb, 'DNSName'), Export=Export(tree_name + '-' + leaf_title + '-Endpoint'))) for dependency in self.dependencies: portless_dependency_name = dependency.split(':')[0] dependency_port = dependency.split(':')[1] target_leaf_sg = RemoteReferenceSecurityEnabledObject( template=template, reference_title=self.tree_name + '-' + portless_dependency_name + '-SecurityGroup') self.asg.add_flow(receiver=target_leaf_sg, port=dependency_port)
def gen_sg(): sg = SecurityGroup( "PostGisProvisionerSg", GroupDescription="Allow PostGis Provisioner access to Postgres", VpcId=ImportValue(Sub("${NetworkName}-network-vpc-VpcId"))) sg_rule = SecurityGroupEgress( "EgressToPrivateSubnets", GroupId=Ref("PostGisProvisionerSg"), IpProtocol="tcp", FromPort="5432", ToPort="5432", CidrIp=ImportValue(Sub("${NetworkName}-network-vpc-PrivateCIDR")), ) return [sg, sg_rule]
def add_launch_config(self): ''' Add autoscaling launch configurastion ''' self.cfn_template.add_resource( LaunchConfiguration( title=constants.INST_LC, AssociatePublicIpAddress=False, BlockDeviceMappings=[ BlockDeviceMapping( DeviceName='/dev/sda1', Ebs=EBSBlockDevice( DeleteOnTermination=True, VolumeSize=int('100'), VolumeType='gp2' ) ) ], IamInstanceProfile=Ref(constants.INST_PROFILE), ImageId=Ref('AmiId'), InstanceType=Ref('InstanceType'), SecurityGroups=[ Ref(constants.SSH_SG), ImportValue(Sub('${Environment}-AppSecurityGroup')), ], UserData=Base64( Sub(constants.USERDATA) ) ) ) return self.cfn_template
def get_custom_reference(self, domain_name): """ Return the endpoint from a different stack in the same tree :param domain_name: amazonia name of the endpoint :return: The endpoint of the specified amazonia object """ return ImportValue(self.tree_name + '-' + domain_name + '-Endpoint')
def get_lambda_reference(self, lambda_name): """ Return the lambda arn from a different stack in the same tree :param lambda_name: amazonia name of lamda :return: The ARN of the target Lambda """ return ImportValue(self.tree_name + '-' + lambda_name + '-Arn')
def get_default_security_groups(self): """ This function will set self._security_groups to include a pre-configured list of SGs to use based on tags in contants.py """ # Add managed security groups using for sg in constants.ENVIRONMENTS[ self.env]['security_groups']['default']: self.add_security_group( ImportValue(self.default_sg_name(sg['name']))) # Add unmanaged (created outside CloudFormation) security groups to instances _unmanaged_filters = [{ 'Name': 'vpc-id', 'Values': [self.vpc_id] }, { 'Name': 'tag:{}:environment'.format(constants.TAG), 'Values': [self.env] }] for sg_filters in constants.ENVIRONMENTS[ self.env]['security_groups'].get('default_unmanaged'): for sg in self.ec2_conn.describe_security_groups( Filters=_unmanaged_filters + sg_filters).get('SecurityGroups'): self.add_security_group(sg['GroupId'])
def parse_managed_policies(c, managed_policies, working_on): managed_policy_list = [] for managed_policy in managed_policies: # If we have an ARN then we're explicit if re.match("arn:aws", managed_policy): managed_policy_list.append(managed_policy) # If we have an import: then we're importing from another template. elif re.match("^import:", managed_policy): m = re.match("^import:(.*)", managed_policy) managed_policy_list.append(ImportValue(m.group(1))) # Alternately we're dealing with a managed policy locally that # we need to 'Ref' to get an ARN. else: # Confirm this is a local policy, otherwise we'll error out. if c.is_local_managed_policy(managed_policy): # Policy name exists in the template, # lets make sure it will exist in this account. if c.is_managed_policy_in_account( managed_policy, c.map_account(c.current_account)): # If this is a ref we'll need to assure it's scrubbed managed_policy_list.append(Ref(scrub_name(managed_policy))) else: raise ValueError( "Working on: '{}' - Managed Policy: '{}' " "is not configured to go into account: '{}'".format( working_on, managed_policy, c.current_account)) else: raise ValueError( "Working on: '{}' - Managed Policy: '{}' " "does not exist in the configuration file".format( working_on, managed_policy)) return (managed_policy_list)
def __init__(self, template, reference_title): """ Create a security enabled object for referencing an amazonia object in another stack :param template: The troposphere template object that will be updated with this object :param reference_title: name of target security enabled object to reference """ super(RemoteReferenceSecurityEnabledObject, self).__init__(title=reference_title, template=template) self.security_group = ImportValue(reference_title)
def get_import_service_group_id(remote_service_name): """ Function to return the ImportValue(Sub()) for given ecs_service name """ return ImportValue( Sub( f"${{{ROOT_STACK_NAME_T}}}{delim}{remote_service_name}{delim}{SERVICE_GROUP_ID_T}" ) )
def add_load_balancer(self): ''' Add load balancer to template ''' self.cfn_template.add_resource(LoadBalancer( title=constants.ALB, LoadBalancerAttributes=[LoadBalancerAttributes( Key='deletion_protection.enabled', Value='false' )], Scheme='internal', SecurityGroups=[Ref(constants.ALB_SG)], Subnets=[ ImportValue(Sub('${Environment}-${Subnet1}')), ImportValue(Sub('${Environment}-${Subnet2}')) ] )) return self.cfn_template
def create_service(self, t, task_definition): return t.add_resource(ecs.Service( self.resource_name_format % ('Service'), Cluster=ImportValue(Sub(self.imports_format % ('ECSCluster'))), DesiredCount=self.desired_count, DeploymentConfiguration=self.deployment_configuration, Role=Sub('arn:aws:iam::${AWS::AccountId}:role/ecsServiceRole'), TaskDefinition=Ref(task_definition), DependsOn=[] ))
def instance_adder(self, name, size, ami_id, role, extra_roles, index, common_tags, user_data_file=False): instance_sec_group = name + "group" instance_sec_group = instance_sec_group.translate(None, '_') instance_id = ''.join(ch for ch in name if ch.isalnum()) + str(index) instance = None extra_tags = self.__tag_role_generator(role, extra_roles) userdata = "" instance_name = Join("", [Ref("AWS::StackName"), str(index)]) app_config = self.config['apps'].values()[0] if user_data_file: userdata = self.__loaduserdata(user_data_file) blockmap = self.__generate_blockmap() instance = self.template.add_resource( ec2.Instance( instance_id, ImageId=FindInMap("RegionMap", Ref("AWS::Region"), ami_id), KeyName=self.config['keyname'], Tags=common_tags + Tags(Name=instance_name, Role=role) + extra_tags, IamInstanceProfile=self.config['iam_role'], SecurityGroupIds=[ Ref(instance_sec_group), ImportValue( self.config['monitoring_security_group_export_name']), ImportValue( self.config['admin_security_group_export_name']) ], InstanceType=size, SubnetId=random.choice(self.config['subnets']), UserData=userdata, BlockDeviceMappings=blockmap)) if 'dns_host' in app_config and app_config['dns_host']: self.host_dns_adder(instance_name, instance_id) return instance
def add_ssm_parameters(self, Params=None, EncParams=None, Global=False): varparams = {} path = "globals" if Global else Ref("AWS::StackName") if Params is None and EncParams is None: raise ValueError( 'add_ssm_parameters requires {Params:Value} or [EncParams]') if Params is None: Params = {} if EncParams is None: EncParams = [] for (paramname, paramvalue) in Params.items(): varparams[paramname] = super(NCTemplate, self).add_parameter( Parameter(paramname.replace('_', ''), Type="String", Description="Environment variable " + paramname, NoEcho=False, Default=paramvalue)) super(NCTemplate, self).add_resource( ssm.Parameter("Param" + paramname.replace('_', ''), Name=Join("/", ["", path, paramname]), Type="String", Description="Environment variable " + paramname, Value=Ref(varparams[paramname]))) for paramname in EncParams: varparams[paramname] = super(NCTemplate, self).add_parameter( Parameter( paramname.replace('_', ''), Type="String", Description="Encrypted environment variable " + paramname, NoEcho=True, )) super(NCTemplate, self).add_resource( SecureParameter( "Param" + paramname.replace('_', ''), Name=Join("/", ["", Ref("AWS::StackName"), paramname]), ServiceToken=ImportValue( Sub("${EncryptLambdaStack}-SsmParameterLambdaArn")), Description="Encrypted environment variable " + paramname, Value=Ref(varparams[paramname]), KeyId=ImportValue(Sub("${EncryptLambdaStack}-KmsKeyArn")))) return varparams
def test_http_api_with_domain(self): certificate = Parameter("certificate", Type="String") serverless_http_api = HttpApi( "SomeHttpApi", StageName="testHttp", Domain=HttpApiDomainConfiguration( BasePath=["/"], CertificateArn=Ref(certificate), DomainName=Sub("subdomain.${Zone}", Zone=ImportValue("MyZone")), EndpointConfiguration="REGIONAL", Route53=Route53( HostedZoneId=ImportValue("MyZone"), IpV6=True, ), ), ) t = Template() t.add_parameter(certificate) t.add_resource(serverless_http_api) t.to_json()
def gen_postgis_provisioner(): postgis_provisioner = PostGisProvisioner( "PostGisProvisioner", Condition="InstallPostgis", DBName=Ref("DBName"), DependsOn="DB", Host=GetAtt("DB", "Endpoint.Address"), Password=Ref("Password"), ServiceToken=ImportValue(Sub("${ProvisionerStackName}-LambdaArn")), Username=Ref("Username"), ) return [postgis_provisioner]
def test_api_with_domain(self): certificate = Parameter('certificate', Type='String') serverless_api = Api( 'SomeApi', StageName='test', Domain=Domain( BasePath=['/'], CertificateArn=Ref(certificate), DomainName=Sub('subdomain.${Zone}', Zone=ImportValue('MyZone')), EndpointConfiguration='REGIONAL', Route53=Route53( HostedZoneId=ImportValue('MyZone'), IpV6=True, ), ), ) t = Template() t.add_parameter(certificate) t.add_resource(serverless_api) t.to_json()
def create_peering(self): template = Template() template.add_version('2010-09-09') source_vpc_name_formatted = ''.join( e for e in self.source_vpc_name if e.isalnum()).capitalize() target_vpc_name_formatted = ''.join( e for e in self.target_vpc_name if e.isalnum()).capitalize() vpc_peering_connection = template.add_resource( VPCPeeringConnection( '{}{}{}VpcPeering'.format(self.stage,source_vpc_name_formatted,target_vpc_name_formatted), VpcId=ImportValue("{}{}VpcId".format(self.stage,source_vpc_name_formatted)), PeerVpcId=ImportValue("{}{}VpcId".format(self.stage,target_vpc_name_formatted)), Tags=Tags( Name="{}_{}_{}_peering".format(self.stage,source_vpc_name_formatted,target_vpc_name_formatted) ) ) ) template.add_resource( Route( '{}{}PublicRoutePeeringRule'.format(self.stage,source_vpc_name_formatted), VpcPeeringConnectionId=Ref(vpc_peering_connection), DestinationCidrBlock=self.target_cidr_block, RouteTableId=ImportValue("{}{}PublicRouteTableId".format(self.stage,source_vpc_name_formatted)) ) ) template.add_resource( Route( '{}{}PrivateRoutePeeringRule'.format(self.stage,source_vpc_name_formatted), VpcPeeringConnectionId=Ref(vpc_peering_connection), DestinationCidrBlock=self.target_cidr_block, RouteTableId=ImportValue("{}{}PrivateRouteTableId".format(self.stage,source_vpc_name_formatted)) ) ) template.add_resource( Route( '{}{}PublicRoutePeeringRule'.format(self.stage,target_vpc_name_formatted), VpcPeeringConnectionId=Ref(vpc_peering_connection), DestinationCidrBlock=self.source_cidr_block, RouteTableId=ImportValue("{}{}PublicRouteTableId".format(self.stage,target_vpc_name_formatted)) ) ) template.add_resource( Route( '{}{}PrivateRoutePeeringRule'.format(self.stage,target_vpc_name_formatted), VpcPeeringConnectionId=Ref(vpc_peering_connection), DestinationCidrBlock=self.source_cidr_block, RouteTableId=ImportValue("{}{}PrivateRouteTableId".format(self.stage,target_vpc_name_formatted)) ) ) f = open("modules/template_peer_vpcs.yaml", 'w') print(template.to_yaml(), file=f)
def parse_imports(c, element_list): return_list = [] for element in element_list: # See if we match an import if re.match("^import:", element): m = re.match("^import:(.*)", element) return_list.append(ImportValue(m.group(1))) # Otherwise we're verbatim as there's no real way to know if this # is within the template or existing. else: return_list.append(element) return (return_list)
def add_private_network_interface(self): self.private_interface = self.template.add_resource( NetworkInterface( "Eth1", Description="eth1", GroupSet=[Ref(self.securityGroup)], SourceDestCheck=True, SubnetId=ImportValue('deploy-dev-vpc-PrivateSubnet'), Tags=Tags( Name="private_vpn_interface", Interface="eth1", ), ))
def __create_security_group(): template = Template() alb_security_group = template.add_resource(resource=SecurityGroup( title='SampleAlbSecurityGroup', GroupDescription='sample-fargate', SecurityGroupIngress=[{ 'IpProtocol': 'tcp', 'ToPort': 80, 'FromPort': 80, 'CidrIp': '0.0.0.0/0' }], VpcId=ImportValue(CommonResource.ExportName.VPC_ID.value))) template.add_output( output=Output(title=alb_security_group.title, Value=Ref(alb_security_group), Export=Export(name=ExportName.ALB_SECURITY_GROUP.value))) task_security_group = template.add_resource(resource=SecurityGroup( title='SampleTaskSecurityGroup', GroupDescription='sample-fargate', SecurityGroupIngress=[ { 'IpProtocol': 'tcp', 'ToPort': 80, 'FromPort': 80, 'CidrIp': '0.0.0.0/0' }, ], VpcId=ImportValue(CommonResource.ExportName.VPC_ID.value))) template.add_output( output=Output(title=task_security_group.title, Value=Ref(task_security_group), Export=Export( name=ExportName.TASK_SECURITY_GROUP.value))) output_template_file(template, 'sg.yml') return alb_security_group, task_security_group
def define_import(resource_name, attribute_name, delimiter=None): """ Wrapper function to define ImportValue for defined resource name :param delimiter: delimiter between stack name, resource name and attribute :param resource_name: name of the resource exported :param attribute_name: attribute exported :type attribute_name: str :type resource_name: str :return: """ if delimiter is None: delimiter = CFN_EXPORT_DELIMITER return If( USE_STACK_NAME_CON_T, ImportValue( Sub(f"${{AWS::StackName}}{delimiter}{resource_name}{delimiter}{attribute_name}" )), ImportValue( Sub(f"${{{ROOT_STACK_NAME_T}}}{delimiter}{resource_name}{delimiter}{attribute_name}" )), )
def gen_rds_db(service_name): db_subnet_group = DBSubnetGroup( "DBSubnetGroup", DBSubnetGroupDescription="Subnets available for the RDS DB Instance", SubnetIds=[ Select( 0, Split( ",", ImportValue( Sub("${NetworkName}-network-vpc-PrivateSubnets")))), Select( 1, Split( ",", ImportValue( Sub("${NetworkName}-network-vpc-PrivateSubnets")))) ], ) db = DBInstance("DB", DBName=Ref(parameters['DBName']), AllocatedStorage=Ref(parameters['DBStorage']), DBInstanceClass=Ref(parameters['DBClass']), DBInstanceIdentifier=service_name, VPCSecurityGroups=[Ref('DBSecurityGroup')], Engine=Ref(parameters['DBEngine']), EngineVersion=Ref(parameters['DBEngineVersion']), StorageType=Ref(parameters['DBStorageType']), Iops=Ref(parameters['Iops']), MasterUsername=Ref(parameters['Username']), MasterUserPassword=Ref(parameters['Password']), MultiAZ=Ref(parameters['MultiAZ']), PubliclyAccessible=Ref(parameters['PubliclyAccessible']), DBSubnetGroupName=Ref("DBSubnetGroup"), Tags=gen_tags(service_name)) return [db, db_subnet_group]