CloudFormation Network Experimentation Stack: Difference between revisions
Jump to navigation
Jump to search
(→Stack) |
|||
(2 intermediate revisions by the same user not shown) | |||
Line 7: | Line 7: | ||
=Stack= | =Stack= | ||
<syntaxhighlight lang='yaml'> | |||
AWSTemplateFormatVersion: '2010-09-09' | |||
Description: Public Load Balancer Tests | |||
Parameters: | |||
Color: | |||
Type: String | |||
Default: green | |||
ApplicationPort: | |||
Type: Number | |||
Default: 10003 | |||
Image: | |||
Type: String | |||
Default: 777777777777.dkr.ecr.ap-northeast-1.amazonaws.com/themyscira:latest | |||
BastionAmi: | |||
Type: String | |||
Default: ami-0f9ae750e8274075b | |||
AvailabilityZoneSuffix1: | |||
Type: String | |||
Default: a | |||
AvailabilityZoneSuffix2: | |||
Type: String | |||
Default: c | |||
Resources: | |||
VPC: | |||
Type: AWS::EC2::VPC | |||
Properties: | |||
CidrBlock: 10.20.0.0/16 | |||
EnableDnsSupport: true | |||
EnableDnsHostnames: false | |||
InstanceTenancy: "default" | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-vpc | |||
InternetGateway: | |||
Type: AWS::EC2::InternetGateway | |||
Properties: | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-igw | |||
InternetGatewayVpcAttachment: | |||
Type: AWS::EC2::VPCGatewayAttachment | |||
Properties: | |||
InternetGatewayId: !Ref InternetGateway | |||
VpcId: !Ref VPC | |||
# | |||
# This is required to give container downloading capabilities to processes only having access to private subnets | |||
# | |||
ElasticIP: | |||
Type: AWS::EC2::EIP | |||
DependsOn: | |||
- InternetGatewayVpcAttachment | |||
Properties: | |||
Domain: vpc | |||
NATGateway: | |||
Type: AWS::EC2::NatGateway | |||
Properties: | |||
SubnetId: !Ref PublicSubnet1 | |||
AllocationId: !GetAtt ElasticIP.AllocationId | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-nat | |||
# | |||
# Public/private subnet pair 1 | |||
# | |||
PublicSubnet1: | |||
Type: AWS::EC2::Subnet | |||
Properties: | |||
VpcId: !Ref VPC | |||
CidrBlock: 10.20.1.0/24 | |||
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix1} | |||
MapPublicIpOnLaunch: false | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-public-subnet-1 | |||
PublicSubnet1RouteTable: | |||
Type: AWS::EC2::RouteTable | |||
Properties: | |||
VpcId: !Ref VPC | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-public-subnet-1-rt | |||
PublicSubnet1RouteTableAssociation: | |||
Type: AWS::EC2::SubnetRouteTableAssociation | |||
Properties: | |||
RouteTableId: !Ref PublicSubnet1RouteTable | |||
SubnetId: !Ref PublicSubnet1 | |||
InternetRoute1: | |||
Type: AWS::EC2::Route | |||
Properties: | |||
RouteTableId: !Ref PublicSubnet1RouteTable | |||
DestinationCidrBlock: 0.0.0.0/0 | |||
GatewayId: !Ref InternetGateway | |||
PrivateSubnet1: | |||
Type: AWS::EC2::Subnet | |||
Properties: | |||
VpcId: !Ref VPC | |||
CidrBlock: 10.20.3.0/24 | |||
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix1} | |||
MapPublicIpOnLaunch: false | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-private-subnet-1 | |||
PrivateSubnet1RouteTable: | |||
Type: AWS::EC2::RouteTable | |||
Properties: | |||
VpcId: !Ref VPC | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-private-subnet-1-rt | |||
PrivateSubnet1RouteTableAssociation: | |||
Type: AWS::EC2::SubnetRouteTableAssociation | |||
Properties: | |||
RouteTableId: !Ref PrivateSubnet1RouteTable | |||
SubnetId: !Ref PrivateSubnet1 | |||
# | |||
# This is required to give container downloading capabilities to processes only having access to private subnets | |||
# | |||
PrivateSubnet1RouteToNAT: | |||
Type: AWS::EC2::Route | |||
Properties: | |||
RouteTableId: !Ref PrivateSubnet1RouteTable | |||
DestinationCidrBlock: 0.0.0.0/0 | |||
NatGatewayId: !Ref NATGateway | |||
# | |||
# Public/private subnet pair 2 | |||
# | |||
PublicSubnet2: | |||
Type: AWS::EC2::Subnet | |||
Properties: | |||
VpcId: !Ref VPC | |||
CidrBlock: 10.20.2.0/24 | |||
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix2} | |||
MapPublicIpOnLaunch: false | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-public-subnet-2 | |||
PublicSubnet2RouteTable: | |||
Type: AWS::EC2::RouteTable | |||
Properties: | |||
VpcId: !Ref VPC | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-public-subnet-2-rt | |||
PublicSubnet2RouteTableAssociation: | |||
Type: AWS::EC2::SubnetRouteTableAssociation | |||
Properties: | |||
RouteTableId: !Ref PublicSubnet2RouteTable | |||
SubnetId: !Ref PublicSubnet2 | |||
InternetRoute2: | |||
Type: AWS::EC2::Route | |||
Properties: | |||
RouteTableId: !Ref PublicSubnet2RouteTable | |||
DestinationCidrBlock: 0.0.0.0/0 | |||
GatewayId: !Ref InternetGateway | |||
PrivateSubnet2: | |||
Type: AWS::EC2::Subnet | |||
Properties: | |||
VpcId: !Ref VPC | |||
CidrBlock: 10.20.4.0/24 | |||
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix2} | |||
MapPublicIpOnLaunch: false | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-private-subnet-2 | |||
PrivateSubnet2RouteTable: | |||
Type: AWS::EC2::RouteTable | |||
Properties: | |||
VpcId: !Ref VPC | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-private-subnet-2-rt | |||
PrivateSubnet2RouteTableAssociation: | |||
Type: AWS::EC2::SubnetRouteTableAssociation | |||
Properties: | |||
RouteTableId: !Ref PrivateSubnet2RouteTable | |||
SubnetId: !Ref PrivateSubnet2 | |||
# | |||
# This is required to give container downloading capabilities to processes only having access to private subnets | |||
# | |||
PrivateSubnet2RouteToNAT: | |||
Type: AWS::EC2::Route | |||
Properties: | |||
RouteTableId: !Ref PrivateSubnet2RouteTable | |||
DestinationCidrBlock: 0.0.0.0/0 | |||
NatGatewayId: !Ref NATGateway | |||
# | |||
# Bastion | |||
# | |||
BastionInstance: | |||
Type: AWS::EC2::Instance | |||
Properties: | |||
ImageId: !Ref BastionAmi | |||
KeyName: !Sub infinity-${AWS::Region} | |||
InstanceType: t2.micro | |||
NetworkInterfaces: | |||
- AssociatePublicIpAddress: 'true' | |||
DeviceIndex: '0' | |||
GroupSet: | |||
- !Ref BastionSecurityGroup | |||
SubnetId: !Ref PublicSubnet1 | |||
Tags: | |||
- Key: Name | |||
Value: !Sub ${Color}-bastion | |||
BastionSecurityGroup: | |||
Type: AWS::EC2::SecurityGroup | |||
Properties: | |||
GroupName: !Sub ${Color}-bastion-sg | |||
VpcId: !Ref VPC | |||
GroupDescription: !Sub Security group for ${Color} bastion | |||
SecurityGroupIngress: | |||
- IpProtocol: -1 | |||
CidrIp: 0.0.0.0/0 | |||
# | |||
# The application load balancer | |||
# | |||
ApplicationLoadBalancer: | |||
Type: AWS::ElasticLoadBalancingV2::LoadBalancer | |||
Properties: | |||
Name: !Sub ${Color}-public-alb | |||
Scheme: internet-facing | |||
Type: application | |||
IpAddressType: ipv4 | |||
LoadBalancerAttributes: | |||
- Key: access_logs.s3.enabled | |||
Value: false | |||
Subnets: | |||
- !Ref PublicSubnet1 | |||
- !Ref PublicSubnet2 | |||
SecurityGroups: | |||
- !Ref ApplicationLoadBalancerSecurityGroup | |||
ApplicationLoadBalancerSecurityGroup: | |||
Type: AWS::EC2::SecurityGroup | |||
Properties: | |||
GroupName: !Sub ${Color}-public-alb-sg | |||
GroupDescription: something | |||
VpcId: !Ref VPC | |||
SecurityGroupIngress: | |||
- IpProtocol: -1 | |||
CidrIp: 0.0.0.0/0 | |||
# | |||
# The service to balance load for | |||
# | |||
ApplicationLoadBalancerListener: | |||
Type: AWS::ElasticLoadBalancingV2::Listener | |||
Properties: | |||
LoadBalancerArn: !Ref ApplicationLoadBalancer | |||
Port: !Ref ApplicationPort | |||
Protocol: HTTP | |||
DefaultActions: | |||
- TargetGroupArn: !Ref TargetGroup | |||
Type: 'forward' | |||
TargetGroup: | |||
Type: AWS::ElasticLoadBalancingV2::TargetGroup | |||
# | |||
# DependsOn is important, I've seen race conditions with the load balancer | |||
# | |||
DependsOn: ApplicationLoadBalancer | |||
Properties: | |||
Name: !Sub ${Color}-themyscira-tg | |||
VpcId: !Ref VPC | |||
Protocol: HTTP | |||
Port: !Ref ApplicationPort | |||
TargetType: ip | |||
HealthCheckProtocol: HTTP | |||
HealthCheckIntervalSeconds: 60 | |||
HealthCheckTimeoutSeconds: 10 | |||
HealthyThresholdCount: 3 | |||
UnhealthyThresholdCount: 3 | |||
HealthCheckPath: '/actuator/health' | |||
# | |||
# Elastic Container Service Resources | |||
# | |||
Cluster: | |||
Type: AWS::ECS::Cluster | |||
Properties: | |||
ClusterName: !Sub ${Color}-cluster | |||
ServiceSecurityGroup: | |||
Type: AWS::EC2::SecurityGroup | |||
Properties: | |||
GroupDescription: themyscira security group | |||
VpcId: !Ref VPC | |||
GroupName: !Sub ${Color}-service-sg | |||
SecurityGroupIngress: | |||
- IpProtocol: -1 | |||
CidrIp: 0.0.0.0/0 | |||
ServiceDefinition: | |||
Type: AWS::ECS::Service | |||
Properties: | |||
ServiceName: !Sub ${Color}-themyscira | |||
LaunchType: FARGATE | |||
Cluster: !Ref Cluster | |||
TaskDefinition: !Ref TaskDefinition | |||
DesiredCount: 1 | |||
HealthCheckGracePeriodSeconds: 60 | |||
LoadBalancers: | |||
- ContainerName: !Sub themyscira-container | |||
ContainerPort: !Ref ApplicationPort | |||
TargetGroupArn: !Ref TargetGroup | |||
NetworkConfiguration: | |||
AwsvpcConfiguration: | |||
AssignPublicIp: DISABLED | |||
SecurityGroups: | |||
- !Ref ServiceSecurityGroup | |||
Subnets: | |||
- !Ref PrivateSubnet1 | |||
- !Ref PrivateSubnet2 | |||
TaskDefinition: | |||
Type: AWS::ECS::TaskDefinition | |||
DependsOn: ServiceLogGroup | |||
Properties: | |||
Family: themyscira | |||
RequiresCompatibilities: [ FARGATE ] | |||
NetworkMode: awsvpc | |||
Cpu: '2048' | |||
Memory: '4096' | |||
TaskRoleArn: !GetAtt TaskRole.Arn | |||
ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn | |||
ContainerDefinitions: | |||
- Name: !Sub themyscira-container | |||
Cpu: '2048' | |||
Memory: '4096' | |||
Essential: 'true' | |||
Environment: | |||
- Name: SPRING_PROFILES_ACTIVE | |||
Value: !Sub generic-profile | |||
- Name: SERVER_PORT | |||
Value: !Ref ApplicationPort | |||
Image: !Ref Image | |||
PortMappings: | |||
- HostPort: !Ref ApplicationPort | |||
ContainerPort: !Ref ApplicationPort | |||
LogConfiguration: | |||
LogDriver: awslogs | |||
Options: | |||
awslogs-group: !Sub /${Color}/themyscira | |||
awslogs-region: !Sub ${AWS::Region} | |||
awslogs-stream-prefix: task | |||
# | |||
# ECS Roles | |||
# | |||
TaskRole: | |||
Type: AWS::IAM::Role | |||
Properties: | |||
RoleName: !Sub ${AWS::Region}-${Color}-task-role | |||
Path: /service-role/ | |||
AssumeRolePolicyDocument: | |||
Statement: | |||
- Effect: Allow | |||
Principal: | |||
Service: | |||
- ecs-tasks.amazonaws.com | |||
Action: | |||
- sts:AssumeRole | |||
Policies: | |||
- PolicyName: generic-in-line-policy | |||
PolicyDocument: | |||
Version: 2012-10-17 | |||
Statement: | |||
- Resource: '*' | |||
Effect: Allow | |||
Action: | |||
# Rules which allow ECS to attach network interfaces to instances | |||
# on your behalf in order for awsvpc networking mode to work right | |||
- ec2:AttachNetworkInterface | |||
- ec2:CreateNetworkInterface | |||
- ec2:CreateNetworkInterfacePermission | |||
- ec2:DeleteNetworkInterface | |||
- ec2:DeleteNetworkInterfacePermission | |||
- 'ec2:Describe*' | |||
- ec2:DetachNetworkInterface | |||
# Rules which allow ECS to update load balancers on your behalf | |||
# with the information about how to send traffic to your containers | |||
- elasticloadbalancing:DeregisterInstancesFromLoadBalancer | |||
- elasticloadbalancing:DeregisterTargets | |||
- 'elasticloadbalancing:Describe*' | |||
- elasticloadbalancing:RegisterInstancesWithLoadBalancer | |||
- elasticloadbalancing:RegisterTargets | |||
# Allow the ECS Tasks resource access | |||
- sns:Publish | |||
- dynamodb:GetItem | |||
- dynamodb:BatchGetItem | |||
- dynamodb:PutItem | |||
- dynamodb:UpdateItem | |||
- dynamodb:DescribeTable | |||
- dynamodb:CreateTable | |||
- dynamodb:Query | |||
- dynamodb:Scan | |||
- kinesis:DescribeStream | |||
- kinesis:PutRecord | |||
- kinesis:PutRecords | |||
- firehose:DescribeDeliveryStream | |||
- firehose:ListDeliveryStreams | |||
- firehose:PutRecord | |||
- firehose:PutRecordBatch | |||
- kinesis:GetShardIterator | |||
- kinesis:GetRecords | |||
- kinesis:ListStreams | |||
- kinesis:ListShards | |||
- kinesis:CreateStream | |||
- 's3:*' | |||
# Required by Kasa campaign library | |||
- ssm:GetParametersByPath | |||
# Required by all applications that use the encryption library and need access to the microworld's | |||
# master key | |||
- 'kms:*' | |||
TaskExecutionRole: | |||
Type: AWS::IAM::Role | |||
Properties: | |||
RoleName: !Sub ${AWS::Region}-${Color}-task-execution-role | |||
Path: /service-role/ | |||
AssumeRolePolicyDocument: | |||
Statement: | |||
- Effect: Allow | |||
Principal: | |||
Service: | |||
- ecs-tasks.amazonaws.com | |||
Action: | |||
- sts:AssumeRole | |||
Policies: | |||
- PolicyName: generic-in-line-policy | |||
PolicyDocument: | |||
Version: 2012-10-17 | |||
Statement: | |||
- Resource: '*' | |||
Effect: Allow | |||
Action: | |||
- ecr:GetAuthorizationToken | |||
- ecr:GetDownloadUrlForLayer | |||
- ecr:BatchGetImage | |||
- ecr:BatchCheckLayerAvailability | |||
- Resource: '*' | |||
Effect: Allow | |||
Action: | |||
- logs:CreateLogGroup | |||
- logs:CreateLogStream | |||
- logs:PutLogEvents | |||
- Resource: '*' | |||
Effect: Allow | |||
Action: | |||
- ec2:AuthorizeSecurityGroupIngress | |||
- ec2:Describe* | |||
- elasticloadbalancing:DeregisterInstancesFromLoadBalancer | |||
- elasticloadbalancing:Describe* | |||
- elasticloadbalancing:RegisterInstancesWithLoadBalancer | |||
- elasticloadbalancing:DeregisterTargets | |||
- elasticloadbalancing:DescribeTargetGroups | |||
- elasticloadbalancing:DescribeTargetHealth | |||
- elasticloadbalancing:RegisterTargets | |||
ServiceLogGroup: | |||
Type: AWS::Logs::LogGroup | |||
Properties: | |||
LogGroupName: !Sub /${Color}/themyscira | |||
RetentionInDays: 1 | |||
</syntaxhighlight> | |||
=Auxiliary Wrapper Scripts= | |||
==create== | |||
<syntaxhighlight lang='bash'> | |||
#!/usr/bin/env bash | |||
[[ -z $1 ]] && { echo "specify color" 1>&2; exit 1; } | |||
color=$1 | |||
aws --region ap-northeast-1 cloudformation create-stack --stack-name=${color} --capabilities CAPABILITY_NAMED_IAM --parameters "ParameterKey=Color,ParameterValue=${color}" --template-body file://./experimental.yaml | |||
</syntaxhighlight> | |||
==delete== | |||
<syntaxhighlight lang='bash'> | |||
#!/usr/bin/env bash | |||
[[ -z $1 ]] && { echo "specify color" 1>&2; exit 1; } | |||
color=$1 | |||
aws --region ap-northeast-1 cloudformation delete-stack --stack-name=${color} | |||
</syntaxhighlight> |
Latest revision as of 21:09, 1 May 2019
Internal
Overview
Network Experimentation Stack (public and private subnets, internet and NAT gateways, ALB and a ECS-based application.
Stack
AWSTemplateFormatVersion: '2010-09-09'
Description: Public Load Balancer Tests
Parameters:
Color:
Type: String
Default: green
ApplicationPort:
Type: Number
Default: 10003
Image:
Type: String
Default: 777777777777.dkr.ecr.ap-northeast-1.amazonaws.com/themyscira:latest
BastionAmi:
Type: String
Default: ami-0f9ae750e8274075b
AvailabilityZoneSuffix1:
Type: String
Default: a
AvailabilityZoneSuffix2:
Type: String
Default: c
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.20.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: false
InstanceTenancy: "default"
Tags:
- Key: Name
Value: !Sub ${Color}-vpc
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${Color}-igw
InternetGatewayVpcAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
#
# This is required to give container downloading capabilities to processes only having access to private subnets
#
ElasticIP:
Type: AWS::EC2::EIP
DependsOn:
- InternetGatewayVpcAttachment
Properties:
Domain: vpc
NATGateway:
Type: AWS::EC2::NatGateway
Properties:
SubnetId: !Ref PublicSubnet1
AllocationId: !GetAtt ElasticIP.AllocationId
Tags:
- Key: Name
Value: !Sub ${Color}-nat
#
# Public/private subnet pair 1
#
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.20.1.0/24
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix1}
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${Color}-public-subnet-1
PublicSubnet1RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${Color}-public-subnet-1-rt
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicSubnet1RouteTable
SubnetId: !Ref PublicSubnet1
InternetRoute1:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicSubnet1RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.20.3.0/24
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix1}
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${Color}-private-subnet-1
PrivateSubnet1RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${Color}-private-subnet-1-rt
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateSubnet1RouteTable
SubnetId: !Ref PrivateSubnet1
#
# This is required to give container downloading capabilities to processes only having access to private subnets
#
PrivateSubnet1RouteToNAT:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateSubnet1RouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway
#
# Public/private subnet pair 2
#
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.20.2.0/24
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix2}
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${Color}-public-subnet-2
PublicSubnet2RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${Color}-public-subnet-2-rt
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicSubnet2RouteTable
SubnetId: !Ref PublicSubnet2
InternetRoute2:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicSubnet2RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.20.4.0/24
AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZoneSuffix2}
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${Color}-private-subnet-2
PrivateSubnet2RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${Color}-private-subnet-2-rt
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateSubnet2RouteTable
SubnetId: !Ref PrivateSubnet2
#
# This is required to give container downloading capabilities to processes only having access to private subnets
#
PrivateSubnet2RouteToNAT:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateSubnet2RouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway
#
# Bastion
#
BastionInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref BastionAmi
KeyName: !Sub infinity-${AWS::Region}
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: 'true'
DeviceIndex: '0'
GroupSet:
- !Ref BastionSecurityGroup
SubnetId: !Ref PublicSubnet1
Tags:
- Key: Name
Value: !Sub ${Color}-bastion
BastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${Color}-bastion-sg
VpcId: !Ref VPC
GroupDescription: !Sub Security group for ${Color} bastion
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
#
# The application load balancer
#
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub ${Color}-public-alb
Scheme: internet-facing
Type: application
IpAddressType: ipv4
LoadBalancerAttributes:
- Key: access_logs.s3.enabled
Value: false
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
SecurityGroups:
- !Ref ApplicationLoadBalancerSecurityGroup
ApplicationLoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${Color}-public-alb-sg
GroupDescription: something
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
#
# The service to balance load for
#
ApplicationLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: !Ref ApplicationPort
Protocol: HTTP
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: 'forward'
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
#
# DependsOn is important, I've seen race conditions with the load balancer
#
DependsOn: ApplicationLoadBalancer
Properties:
Name: !Sub ${Color}-themyscira-tg
VpcId: !Ref VPC
Protocol: HTTP
Port: !Ref ApplicationPort
TargetType: ip
HealthCheckProtocol: HTTP
HealthCheckIntervalSeconds: 60
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 3
UnhealthyThresholdCount: 3
HealthCheckPath: '/actuator/health'
#
# Elastic Container Service Resources
#
Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub ${Color}-cluster
ServiceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: themyscira security group
VpcId: !Ref VPC
GroupName: !Sub ${Color}-service-sg
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
ServiceDefinition:
Type: AWS::ECS::Service
Properties:
ServiceName: !Sub ${Color}-themyscira
LaunchType: FARGATE
Cluster: !Ref Cluster
TaskDefinition: !Ref TaskDefinition
DesiredCount: 1
HealthCheckGracePeriodSeconds: 60
LoadBalancers:
- ContainerName: !Sub themyscira-container
ContainerPort: !Ref ApplicationPort
TargetGroupArn: !Ref TargetGroup
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: DISABLED
SecurityGroups:
- !Ref ServiceSecurityGroup
Subnets:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
TaskDefinition:
Type: AWS::ECS::TaskDefinition
DependsOn: ServiceLogGroup
Properties:
Family: themyscira
RequiresCompatibilities: [ FARGATE ]
NetworkMode: awsvpc
Cpu: '2048'
Memory: '4096'
TaskRoleArn: !GetAtt TaskRole.Arn
ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
ContainerDefinitions:
- Name: !Sub themyscira-container
Cpu: '2048'
Memory: '4096'
Essential: 'true'
Environment:
- Name: SPRING_PROFILES_ACTIVE
Value: !Sub generic-profile
- Name: SERVER_PORT
Value: !Ref ApplicationPort
Image: !Ref Image
PortMappings:
- HostPort: !Ref ApplicationPort
ContainerPort: !Ref ApplicationPort
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Sub /${Color}/themyscira
awslogs-region: !Sub ${AWS::Region}
awslogs-stream-prefix: task
#
# ECS Roles
#
TaskRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${AWS::Region}-${Color}-task-role
Path: /service-role/
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: generic-in-line-policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource: '*'
Effect: Allow
Action:
# Rules which allow ECS to attach network interfaces to instances
# on your behalf in order for awsvpc networking mode to work right
- ec2:AttachNetworkInterface
- ec2:CreateNetworkInterface
- ec2:CreateNetworkInterfacePermission
- ec2:DeleteNetworkInterface
- ec2:DeleteNetworkInterfacePermission
- 'ec2:Describe*'
- ec2:DetachNetworkInterface
# Rules which allow ECS to update load balancers on your behalf
# with the information about how to send traffic to your containers
- elasticloadbalancing:DeregisterInstancesFromLoadBalancer
- elasticloadbalancing:DeregisterTargets
- 'elasticloadbalancing:Describe*'
- elasticloadbalancing:RegisterInstancesWithLoadBalancer
- elasticloadbalancing:RegisterTargets
# Allow the ECS Tasks resource access
- sns:Publish
- dynamodb:GetItem
- dynamodb:BatchGetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DescribeTable
- dynamodb:CreateTable
- dynamodb:Query
- dynamodb:Scan
- kinesis:DescribeStream
- kinesis:PutRecord
- kinesis:PutRecords
- firehose:DescribeDeliveryStream
- firehose:ListDeliveryStreams
- firehose:PutRecord
- firehose:PutRecordBatch
- kinesis:GetShardIterator
- kinesis:GetRecords
- kinesis:ListStreams
- kinesis:ListShards
- kinesis:CreateStream
- 's3:*'
# Required by Kasa campaign library
- ssm:GetParametersByPath
# Required by all applications that use the encryption library and need access to the microworld's
# master key
- 'kms:*'
TaskExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${AWS::Region}-${Color}-task-execution-role
Path: /service-role/
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: generic-in-line-policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource: '*'
Effect: Allow
Action:
- ecr:GetAuthorizationToken
- ecr:GetDownloadUrlForLayer
- ecr:BatchGetImage
- ecr:BatchCheckLayerAvailability
- Resource: '*'
Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource: '*'
Effect: Allow
Action:
- ec2:AuthorizeSecurityGroupIngress
- ec2:Describe*
- elasticloadbalancing:DeregisterInstancesFromLoadBalancer
- elasticloadbalancing:Describe*
- elasticloadbalancing:RegisterInstancesWithLoadBalancer
- elasticloadbalancing:DeregisterTargets
- elasticloadbalancing:DescribeTargetGroups
- elasticloadbalancing:DescribeTargetHealth
- elasticloadbalancing:RegisterTargets
ServiceLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /${Color}/themyscira
RetentionInDays: 1
Auxiliary Wrapper Scripts
create
#!/usr/bin/env bash
[[ -z $1 ]] && { echo "specify color" 1>&2; exit 1; }
color=$1
aws --region ap-northeast-1 cloudformation create-stack --stack-name=${color} --capabilities CAPABILITY_NAMED_IAM --parameters "ParameterKey=Color,ParameterValue=${color}" --template-body file://./experimental.yaml
delete
#!/usr/bin/env bash
[[ -z $1 ]] && { echo "specify color" 1>&2; exit 1; }
color=$1
aws --region ap-northeast-1 cloudformation delete-stack --stack-name=${color}