CloudFormation Network Experimentation Stack
Jump to navigation
Jump to search
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}