diff --git a/infra/aws/.vscode/settings.json b/infra/aws/.vscode/settings.json new file mode 100644 index 0000000..043fd62 --- /dev/null +++ b/infra/aws/.vscode/settings.json @@ -0,0 +1,26 @@ +{ + "yaml.customTags": [ + "!Base64 scalar", + "!Cidr scalar", + "!And sequence", + "!Equals sequence", + "!If sequence", + "!Not sequence", + "!Or sequence", + "!Condition scalar", + "!FindInMap sequence", + "!GetAtt scalar", + "!GetAtt sequence", + "!GetAZs scalar", + "!ImportValue scalar", + "!Join sequence", + "!Select sequence", + "!Split sequence", + "!Sub scalar", + "!Transform mapping", + "!Ref scalar", + ], + "yaml.schemas": { + "https://raw.githubusercontent.com/awslabs/goformation/master/schema/cloudformation.schema.json": "formation.yml" + } +} \ No newline at end of file diff --git a/infra/aws/README.md b/infra/aws/README.md new file mode 100644 index 0000000..c4cbd87 --- /dev/null +++ b/infra/aws/README.md @@ -0,0 +1,6 @@ +# このディレクトリについて + +このディレクトリのテンプレート全般には`ApplicationTag`と`ApplicationId`の2つのパラメータが定義されている。これらはmyApplicationsの紐づけのためのものである。 + +* ApplicationId - Service CatalogのアプリケーションARNを指定 +* ApplicationTag - myApplicationsの指定すべきタグ diff --git a/infra/aws/ecr/formation.yml b/infra/aws/ecr/formation.yml new file mode 100644 index 0000000..6e65f77 --- /dev/null +++ b/infra/aws/ecr/formation.yml @@ -0,0 +1,29 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Disaster posts container registry +Parameters: + ApplicationTag: + Type: String + Description: Application tag + ApplicationId: + Type: String + Description: Application ARN +Resources: + # Application relationship definition + AppAssoc: + Type: AWS::ServiceCatalogAppRegistry::ResourceAssociation + Properties: + Application: !Ref ApplicationId + Resource: !Ref AWS::StackId + ResourceType: CFN_STACK + Repository: + Type: AWS::ECR::Repository + Properties: + EmptyOnDelete: true + ImageTagMutability: IMMUTABLE + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-Repository" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag diff --git a/infra/aws/ses/formation.yml b/infra/aws/ses/formation.yml new file mode 100644 index 0000000..5a369b9 --- /dev/null +++ b/infra/aws/ses/formation.yml @@ -0,0 +1,109 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Disaster posts SES +Parameters: + ApplicationTag: + Type: String + Description: Application tag + ApplicationId: + Type: String + Description: Application ARN + DomainName: + Type: String + Description: Send domain name + ZoneId: + Type: AWS::Route53::HostedZone::Id + Description: Route 53 zone ID +Resources: + # Application relationship definition + AppAssoc: + Type: AWS::ServiceCatalogAppRegistry::ResourceAssociation + Properties: + Application: !Ref ApplicationId + Resource: !Ref AWS::StackId + ResourceType: CFN_STACK + # Bounce and complaint handling mechanism definition + Topic: + Type: AWS::SNS::Topic + Properties: + DisplayName: !Sub "${AWS::StackName}-Topic" + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-Topic" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + ConfigSet: + Type: AWS::SES::ConfigurationSet + Properties: + ReputationOptions: + ReputationMetricsEnabled: true + SendingOptions: + SendingEnabled: true + ConfigSetEventDestination: + Type: AWS::SES::ConfigurationSetEventDestination + Properties: + ConfigurationSetName: !Ref ConfigSet + EventDestination: + Enabled: true + MatchingEventTypes: + - bounce + - complaint + SnsDestination: + TopicARN: !Ref Topic + # SES identity definition + Identity: + Type: AWS::SES::EmailIdentity + Properties: + EmailIdentity: !Ref DomainName + ConfigurationSetAttributes: + ConfigurationSetName: !Ref ConfigSet + DkimAttributes: + SigningEnabled: true + DkimSigningAttributes: + NextSigningKeyLength: RSA_2048_BIT + MailFromAttributes: + MailFromDomain: !Sub "ses-${AWS::Region}.${DomainName}" + # SES DKIM and verification records + DkimRecords: + Type: AWS::Route53::RecordSetGroup + Properties: + Comment: !Sub "${AWS::StackName} DKIM records" + HostedZoneId: !Ref ZoneId + RecordSets: + - Name: !GetAtt Identity.DkimDNSTokenName1 + Type: CNAME + TTL: "900" + ResourceRecords: + - !GetAtt Identity.DkimDNSTokenValue1 + - Name: !GetAtt Identity.DkimDNSTokenName2 + Type: CNAME + TTL: "900" + ResourceRecords: + - !GetAtt Identity.DkimDNSTokenValue2 + - Name: !GetAtt Identity.DkimDNSTokenName3 + Type: CNAME + TTL: "900" + ResourceRecords: + - !GetAtt Identity.DkimDNSTokenValue3 + # SES SPF and MX records + SpfRecord: + Type: AWS::Route53::RecordSet + Properties: + Comment: SPF record + HostedZoneId: !Ref ZoneId + Name: !Sub "ses-${AWS::Region}.${DomainName}" + Type: TXT + TTL: "900" + ResourceRecords: + - '"v=spf1 include:amazonses.com ~all"' + MxRecord: + Type: AWS::Route53::RecordSet + Properties: + Comment: MX record + HostedZoneId: !Ref ZoneId + Name: !Sub "ses-${AWS::Region}.${DomainName}" + Type: MX + TTL: "900" + ResourceRecords: + - !Sub "10 feedback-smtp.${AWS::Region}.amazonses.com" diff --git a/infra/aws/table/formation.yml b/infra/aws/table/formation.yml new file mode 100644 index 0000000..54d6883 --- /dev/null +++ b/infra/aws/table/formation.yml @@ -0,0 +1,63 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Disaster posts DynamoDB global table +Parameters: + ApplicationTag: + Type: String + Description: Application tag + ApplicationId: + Type: String + Description: Application ARN + SubRegion: + Type: String + Description: Sub region + Default: ap-northeast-3 + SubRegionApplicationTag: + Type: String + Description: Sub region Application tag +Resources: + # Application relationship definition + AppAssoc: + Type: AWS::ServiceCatalogAppRegistry::ResourceAssociation + Properties: + Application: !Ref ApplicationId + Resource: !Ref AWS::StackId + ResourceType: CFN_STACK + # DynamoDB table definition + # TODO: テーブルスキーマの決定 + Table: + Type: AWS::DynamoDB::GlobalTable + Properties: + AttributeDefinitions: + - AttributeName: id + AttributeType: S + - AttributeName: timestamp + AttributeType: 'N' + BillingMode: PAY_PER_REQUEST + KeySchema: + - AttributeName: id + KeyType: HASH + - AttributeName: timestamp + KeyType: RANGE + Replicas: + - Region: !Ref AWS::Region + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-Table-Replica-${AWS::Region}" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + - Region: !Ref SubRegion + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-Table-Replica-${SubRegion}" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + StreamSpecification: + StreamViewType: NEW_AND_OLD_IMAGES diff --git a/infra/aws/vpc/formation.yml b/infra/aws/vpc/formation.yml new file mode 100644 index 0000000..503b1de --- /dev/null +++ b/infra/aws/vpc/formation.yml @@ -0,0 +1,737 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Disaster posts VPC +Parameters: + ApplicationTag: + Type: String + Description: Application tag + ApplicationId: + Type: String + Description: Application ARN + VpcCidr: + Type: String + Description: VPC CIDR + AllowedPattern: '^(10\.([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-6\5]))\.([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-6\5]))/(1[6-9]|2[0-6])$' + Default: '10.0.0.0/16' + CreateNATGateway: + Type: String + Description: Whether to create NAT gateway or not + AllowedValues: + - "EachAZ" + - "OneAZ" + - "None" + Default: "None" + CreateEc2MessagesEndpoint: + Type: String + Description: Whether to create EC2 messages endpoint + AllowedValues: + - "true" + - "false" + Default: "false" + CreateSsmEndpoint: + Type: String + Description: Whether to create SSM endpoint + AllowedValues: + - "true" + - "false" + Default: "false" + CreateSsmMessagesEndpoint: + Type: String + Description: Whether to create SSM messages endpoint + AllowedValues: + - "true" + - "false" + Default: "false" + CreateKmsEndpoint: + Type: String + Description: Whether to create KMS endpoint + AllowedValues: + - "true" + - "false" + Default: "false" + CreateCloudWatchLogsEndpoint: + Type: String + Description: Whether to create CloudWatch Logs endpoint + AllowedValues: + - "true" + - "false" + Default: "false" + CreateEcrDockerEndpoint: + Type: String + Description: Whether to create ECR Docker endpoint + AllowedValues: + - "true" + - "false" + Default: "false" + CreateEcrApiEndpoint: + Type: String + Description: Whether to create ECR API endpoint + AllowedValues: + - "true" + - "false" + Default: "false" +Conditions: + HasNATGateway: !Not + - !Equals + - !Ref CreateNATGateway + - "None" + HasEacnAZNatGateway: !Equals + - !Ref CreateNATGateway + - "EachAZ" + HasEc2MessagesEndpoint: !Equals + - !Ref CreateEc2MessagesEndpoint + - "true" + HasSsmEndpoint: !Equals + - !Ref CreateSsmEndpoint + - "true" + HasSsmMessagesEndpoint: !Equals + - !Ref CreateSsmMessagesEndpoint + - "true" + HasKmsEndpoint: !Equals + - !Ref CreateKmsEndpoint + - "true" + HasCloudWatchLogsEndpoint: !Equals + - !Ref CreateCloudWatchLogsEndpoint + - "true" + HasEcrDockerEndpoint: !Equals + - !Ref CreateEcrDockerEndpoint + - "true" + HasEcrApiEndpoint: !Equals + - !Ref CreateEcrApiEndpoint + - "true" +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: Application settings + Parameters: + - ApplicationTag + - ApplicationId + - Label: + default: VPC base settings + Parameters: + - VpcCidr + - Label: + default: Gateway settings + Parameters: + - CreateNATGateway + - CreateEc2MessagesEndpoint + - CreateSsmEndpoint + - CreateSsmMessagesEndpoint + - CreateKmsEndpoint + - CreateCloudWatchLogsEndpoint + - CreateEcrDockerEndpoint + - CreateEcrApiEndpoint +Resources: + # Application relationship definition + AppAssoc: + Type: AWS::ServiceCatalogAppRegistry::ResourceAssociation + Properties: + Application: !Ref ApplicationId + Resource: !Ref AWS::StackId + ResourceType: CFN_STACK + # VPC definition + Vpc: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Ref VpcCidr + EnableDnsHostnames: true + EnableDnsSupport: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-Vpc" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + VpcIpv6Cidr: + Type: AWS::EC2::VPCCidrBlock + Properties: + VpcId: !Ref Vpc + AmazonProvidedIpv6CidrBlock: true + # Internet Gateway definition + InternetGateway: + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-InternetGateway" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + InternetGatewayAttachment: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: !Ref Vpc + InternetGatewayId: !Ref InternetGateway + EgressOnlyGateway: + Type: AWS::EC2::EgressOnlyInternetGateway + DependsOn: VpcIpv6Cidr + Properties: + VpcId: !Ref Vpc + # Subnets definition + PublicSubnet1: + Type: AWS::EC2::Subnet + DependsOn: VpcIpv6Cidr + Properties: + VpcId: !Ref Vpc + AvailabilityZone: !Select + - 0 + - Fn::GetAZs: !Ref AWS::Region + CidrBlock: !Select + - 0 + - !Cidr + - !GetAtt Vpc.CidrBlock + - 6 + - 13 + Ipv6CidrBlock: !Select + - 0 + - !Cidr + - !Select + - 0 + - !GetAtt Vpc.Ipv6CidrBlocks + - 6 + - 64 + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PublicSubnet1" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Public + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet1: + Type: AWS::EC2::Subnet + DependsOn: VpcIpv6Cidr + Properties: + VpcId: !Ref Vpc + AvailabilityZone: !Select + - 0 + - Fn::GetAZs: !Ref AWS::Region + CidrBlock: !Select + - 1 + - !Cidr + - !GetAtt Vpc.CidrBlock + - 6 + - 13 + Ipv6CidrBlock: !Select + - 1 + - !Cidr + - !Select + - 0 + - !GetAtt Vpc.Ipv6CidrBlocks + - 6 + - 64 + AssignIpv6AddressOnCreation: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet1" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Private + - Key: awsApplication + Value: !Ref ApplicationTag + PublicSubnet2: + Type: AWS::EC2::Subnet + DependsOn: VpcIpv6Cidr + Properties: + VpcId: !Ref Vpc + AvailabilityZone: !Select + - 1 + - Fn::GetAZs: !Ref AWS::Region + CidrBlock: !Select + - 2 + - !Cidr + - !GetAtt Vpc.CidrBlock + - 6 + - 13 + Ipv6CidrBlock: !Select + - 2 + - !Cidr + - !Select + - 0 + - !GetAtt Vpc.Ipv6CidrBlocks + - 6 + - 64 + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PublicSubnet2" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Public + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet2: + Type: AWS::EC2::Subnet + DependsOn: VpcIpv6Cidr + Properties: + VpcId: !Ref Vpc + AvailabilityZone: !Select + - 1 + - Fn::GetAZs: !Ref AWS::Region + CidrBlock: !Select + - 3 + - !Cidr + - !GetAtt Vpc.CidrBlock + - 6 + - 13 + Ipv6CidrBlock: !Select + - 3 + - !Cidr + - !Select + - 0 + - !GetAtt Vpc.Ipv6CidrBlocks + - 6 + - 64 + AssignIpv6AddressOnCreation: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet2" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Private + - Key: awsApplication + Value: !Ref ApplicationTag + PublicSubnet3: + Type: AWS::EC2::Subnet + DependsOn: VpcIpv6Cidr + Properties: + VpcId: !Ref Vpc + AvailabilityZone: !Select + - 2 + - Fn::GetAZs: !Ref AWS::Region + CidrBlock: !Select + - 4 + - !Cidr + - !GetAtt Vpc.CidrBlock + - 6 + - 13 + Ipv6CidrBlock: !Select + - 4 + - !Cidr + - !Select + - 0 + - !GetAtt Vpc.Ipv6CidrBlocks + - 6 + - 64 + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PublicSubnet3" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Public + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet3: + Type: AWS::EC2::Subnet + DependsOn: VpcIpv6Cidr + Properties: + VpcId: !Ref Vpc + AvailabilityZone: !Select + - 2 + - Fn::GetAZs: !Ref AWS::Region + CidrBlock: !Select + - 5 + - !Cidr + - !GetAtt Vpc.CidrBlock + - 6 + - 13 + Ipv6CidrBlock: !Select + - 5 + - !Cidr + - !Select + - 0 + - !GetAtt Vpc.Ipv6CidrBlocks + - 6 + - 64 + AssignIpv6AddressOnCreation: true + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet3" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Private + - Key: awsApplication + Value: !Ref ApplicationTag + # Route tables and NAT Gateways definition + PublicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref Vpc + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PublicRouteTable" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Public + - Key: awsApplication + Value: !Ref ApplicationTag + PublicRouteIpv4: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref PublicRouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref InternetGateway + PublicRouteIpv6: + Type: AWS::EC2::Route + DependsOn: VpcIpv6Cidr + Properties: + RouteTableId: !Ref PublicRouteTable + DestinationIpv6CidrBlock: '::/0' + GatewayId: !Ref InternetGateway + PublicSutnet1RouteTableAssoc: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnet1 + PublicSubnet2RouteTableAssoc: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnet2 + PublicSubnet3RouteTableAssoc: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnet3 + PrivateSubnet1RouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref Vpc + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet1RouteTable" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Private + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet1RouteIpv6: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref PrivateSubnet1RouteTable + DestinationIpv6CidrBlock: '::/0' + EgressOnlyInternetGatewayId: !Ref EgressOnlyGateway + PrivateSubnet1NatEIP: + Type: AWS::EC2::EIP + Condition: HasNATGateway + Properties: + Domain: vpc + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet1NatEIP" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet1NatGateway: + Type: AWS::EC2::NatGateway + Condition: HasNATGateway + Properties: + SubnetId: !Ref PublicSubnet1 + AllocationId: !GetAtt PrivateSubnet1NatEIP.AllocationId + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet1NatGateway" + - Key: CostTag + Value: !Ref AWS::StackName + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet1RouteIpv4: + Type: AWS::EC2::Route + Condition: HasNATGateway + Properties: + RouteTableId: !Ref PrivateSubnet1RouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !Ref PrivateSubnet1NatGateway + PrivateSubnet1RouteTableAssoc: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PrivateSubnet1RouteTable + SubnetId: !Ref PrivateSubnet1 + PrivateSubnet2RouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref Vpc + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet2RouteTable" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Private + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet2RouteIpv6: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref PrivateSubnet2RouteTable + DestinationIpv6CidrBlock: '::/0' + EgressOnlyInternetGatewayId: !Ref EgressOnlyGateway + PrivateSubnet2NatEIP: + Type: AWS::EC2::EIP + Condition: HasEacnAZNatGateway + Properties: + Domain: vpc + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet2NatEIP" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet2NatGateway: + Type: AWS::EC2::NatGateway + Condition: HasEacnAZNatGateway + Properties: + SubnetId: !Ref PublicSubnet2 + AllocationId: !GetAtt PrivateSubnet2NatEIP.AllocationId + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet2NatGateway" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet2RouteIpv4: + Type: AWS::EC2::Route + Condition: HasNATGateway + Properties: + RouteTableId: !Ref PrivateSubnet2RouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !If + - HasEacnAZNatGateway + - !Ref PrivateSubnet2NatGateway + - !Ref PrivateSubnet1NatGateway + PrivateSubnet2RouteTableAssoc: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PrivateSubnet2RouteTable + SubnetId: !Ref PrivateSubnet2 + PrivateSubnet3RouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref Vpc + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet3RouteTable" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: SubnetType + Value: Private + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet3RouteIpv6: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref PrivateSubnet3RouteTable + DestinationIpv6CidrBlock: '::/0' + EgressOnlyInternetGatewayId: !Ref EgressOnlyGateway + PrivateSubnet3NatEIP: + Type: AWS::EC2::EIP + Condition: HasEacnAZNatGateway + Properties: + Domain: vpc + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet3NatEIP" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet3NatGateway: + Type: AWS::EC2::NatGateway + Condition: HasEacnAZNatGateway + Properties: + SubnetId: !Ref PublicSubnet3 + AllocationId: !GetAtt PrivateSubnet3NatEIP.AllocationId + Tags: + - Key: Name + Value: !Sub "${AWS::StackName}-PrivateSubnet3NatGateway" + - Key: AppManagerCFNStackKey + Value: !Ref AWS::StackName + - Key: awsApplication + Value: !Ref ApplicationTag + PrivateSubnet3RouteIpv4: + Type: AWS::EC2::Route + Condition: HasNATGateway + Properties: + RouteTableId: !Ref PrivateSubnet3RouteTable + DestinationCidrBlock: 0.0.0.0/0 + NatGatewayId: !If + - HasEacnAZNatGateway + - !Ref PrivateSubnet3NatGateway + - !Ref PrivateSubnet1NatGateway + PrivateSubnet3RouteTableAssoc: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + RouteTableId: !Ref PrivateSubnet3RouteTable + SubnetId: !Ref PrivateSubnet3 + # VPC endpoints definition + S3Endpoint: + Type: AWS::EC2::VPCEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3" + VpcId: !Ref Vpc + RouteTableIds: + - !Ref PrivateSubnet1RouteTable + - !Ref PrivateSubnet2RouteTable + - !Ref PrivateSubnet3RouteTable + VpcEndpointType: Gateway + DynaoDbEndpoint: + Type: AWS::EC2::VPCEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.dynamodb" + VpcId: !Ref Vpc + RouteTableIds: + - !Ref PrivateSubnet1RouteTable + - !Ref PrivateSubnet2RouteTable + - !Ref PrivateSubnet3RouteTable + VpcEndpointType: Gateway + Ec2MessagesEndpoint: + Type: AWS::EC2::VPCEndpoint + Condition: HasEc2MessagesEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.ec2messages" + VpcId: !Ref Vpc + PrivateDnsEnabled: true + SecurityGroupIds: + - !Ref VpcEndpointSecurityGroup + SubnetIds: + - !Ref PrivateSubnet1 + - !Ref PrivateSubnet2 + - !Ref PrivateSubnet3 + VpcEndpointType: Interface + SsmEndpoint: + Type: AWS::EC2::VPCEndpoint + Condition: HasSsmEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm" + VpcId: !Ref Vpc + PrivateDnsEnabled: true + SecurityGroupIds: + - !Ref VpcEndpointSecurityGroup + SubnetIds: + - !Ref PrivateSubnet1 + - !Ref PrivateSubnet2 + - !Ref PrivateSubnet3 + VpcEndpointType: Interface + SsmMessagesEndpoint: + Type: AWS::EC2::VPCEndpoint + Condition: HasSsmMessagesEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssmmessages" + VpcId: !Ref Vpc + PrivateDnsEnabled: true + SecurityGroupIds: + - !Ref VpcEndpointSecurityGroup + SubnetIds: + - !Ref PrivateSubnet1 + - !Ref PrivateSubnet2 + - !Ref PrivateSubnet3 + VpcEndpointType: Interface + KmsEndpoint: + Type: AWS::EC2::VPCEndpoint + Condition: HasKmsEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.kms" + VpcId: !Ref Vpc + PrivateDnsEnabled: true + SecurityGroupIds: + - !Ref VpcEndpointSecurityGroup + SubnetIds: + - !Ref PrivateSubnet1 + - !Ref PrivateSubnet2 + - !Ref PrivateSubnet3 + VpcEndpointType: Interface + CloudWatchLogsEndpoint: + Type: AWS::EC2::VPCEndpoint + Condition: HasCloudWatchLogsEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.logs" + VpcId: !Ref Vpc + PrivateDnsEnabled: true + SecurityGroupIds: + - !Ref VpcEndpointSecurityGroup + SubnetIds: + - !Ref PrivateSubnet1 + - !Ref PrivateSubnet2 + - !Ref PrivateSubnet3 + VpcEndpointType: Interface + EcrDockerEndpoint: + Type: AWS::EC2::VPCEndpoint + Condition: HasEcrDockerEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.dkr" + VpcId: !Ref Vpc + PrivateDnsEnabled: true + SecurityGroupIds: + - !Ref VpcEndpointSecurityGroup + SubnetIds: + - !Ref PrivateSubnet1 + - !Ref PrivateSubnet2 + - !Ref PrivateSubnet3 + VpcEndpointType: Interface + EcrApiEndpoint: + Type: AWS::EC2::VPCEndpoint + Condition: HasEcrApiEndpoint + Properties: + ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.api" + VpcId: !Ref Vpc + PrivateDnsEnabled: true + SecurityGroupIds: + - !Ref VpcEndpointSecurityGroup + SubnetIds: + - !Ref PrivateSubnet1 + - !Ref PrivateSubnet2 + - !Ref PrivateSubnet3 + VpcEndpointType: Interface +Outputs: + VpcId: + Value: !Ref Vpc + Description: VPC ID + Export: + Name: !Sub "${AWS::StackName}-Vpc" + PublicSubnet1Id: + Value: !Ref PublicSubnet1 + Description: Public subnet 1 ID + Export: + Name: !Sub "${AWS::StackName}-PublicSubnet1" + PrivateSubnet1Id: + Value: !Ref PrivateSubnet1 + Description: Private subnet 1 ID + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet1" + PublicSubnet2Id: + Value: !Ref PublicSubnet2 + Description: Public subnet 1 ID + Export: + Name: !Sub "${AWS::StackName}-PublicSubnet2" + PrivateSubnet2Id: + Value: !Ref PrivateSubnet2 + Description: Private subnet 1 ID + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet2" + PublicSubnet3Id: + Value: !Ref PublicSubnet3 + Description: Public subnet 1 ID + Export: + Name: !Sub "${AWS::StackName}-PublicSubnet3" + PrivateSubnet3Id: + Value: !Ref PrivateSubnet3 + Description: Private subnet 1 ID + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet3"