AWSTemplateFormatVersion: 2010-09-09 Description: This template deploys a VPC, with a pair of public and private subnets spread across two Availability Zones. It deploys an internet gateway, with a default route on the public subnets. It deploys a pair of NAT gateways (one in each AZ), and default routes for them in the private subnets. Parameters: VpcCIDR: Description: Please enter the IP range (CIDR notation) for this VPC Type: String Default: 10.0.0.0/16 LatestAmiId: Description: Region specific image from the Parameter Store Type: 'AWS::SSM::Parameter::Value' Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' InstanceType: Description: Amazon EC2 instance type for the instances Type: String AllowedValues: - t2.micro Default: t2.micro PublicSubnet1CIDR: Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone Type: String Default: 10.0.0.0/20 PublicSubnet2CIDR: Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone Type: String Default: 10.0.16.0/20 PrivateSubnet1CIDR: Description: Please enter the IP range (CIDR notation) for the first private subnet in the first Availability Zone Type: String Default: 10.0.128.0/20 PrivateSubnet2CIDR: Description: Please enter the IP range (CIDR notation) for the second private subnet in the second Availability Zone Type: String Default: 10.0.144.0/20 Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCIDR EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: Project1VPC - Key: Department Value: Digital InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: Project1IGW - Key: Department Value: Digital InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC Project1PublicSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select - 0 - !GetAZs Ref: 'AWS::Region' CidrBlock: !Ref PublicSubnet1CIDR MapPublicIpOnLaunch: true Project1PublicSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select - 1 - !GetAZs Ref: 'AWS::Region' CidrBlock: !Ref PublicSubnet2CIDR MapPublicIpOnLaunch: true Project1PrivateSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select - 0 - !GetAZs Ref: 'AWS::Region' CidrBlock: !Ref PrivateSubnet1CIDR MapPublicIpOnLaunch: false Project1PrivateSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select - 1 - !GetAZs Ref: 'AWS::Region' CidrBlock: !Ref PrivateSubnet2CIDR MapPublicIpOnLaunch: false Project1NatGatewayEIP: Type: AWS::EC2::EIP DependsOn: InternetGatewayAttachment Properties: Domain: vpc Project1NatGateway: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt Project1NatGatewayEIP.AllocationId SubnetId: !Ref Project1PublicSubnet1 Tags: - Key: Name Value: Project1NatGateway - Key: Department Value: Digital #Public Route Table PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC DefaultPublicRoute: Type: AWS::EC2::Route DependsOn: InternetGatewayAttachment Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway Project1PublicSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref Project1PublicSubnet1 Project1PublicSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref Project1PublicSubnet2 #AZ1 Route Table PrivateRouteTable1: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC DefaultPrivateRoute1: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable1 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref Project1NatGateway PrivateSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable1 SubnetId: !Ref Project1PrivateSubnet1 #AZ2 Route Table PrivateRouteTable2: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC DefaultPrivateRoute2: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable2 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref Project1NatGateway Project1PrivateSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable2 SubnetId: !Ref Project1PrivateSubnet2 #SecurityGroups, make sure your Egress rule are correct or it will not talk to back end. #You can lock your inbound on the Project1webapp to just your IP if you so choose to be more secure ApplicationLoadBalancerSG: Type: AWS::EC2::SecurityGroup DependsOn: VPC Properties: GroupDescription: http traffic to web tier VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 WebProject1SG: Type: AWS::EC2::SecurityGroup DependsOn: VPC Properties: GroupDescription: Allow http to client host VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 WebAppSG: Type: AWS::EC2::SecurityGroup DependsOn: VPC Properties: GroupDescription: Load Balancer to WebTier VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !Ref ApplicationLoadBalancerSG SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 DatabaseSG: Type: AWS::EC2::SecurityGroup DependsOn: VPC Properties: GroupDescription: web to database tier VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 3306 ToPort: 3306 SourceSecurityGroupId: !Ref WebProject1SG SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 #Web tier infrastructure, This will be an ASG, Launchconfig, some autoscaling alarms and scaling polices. InstanceRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - 'sts:AssumeRole' Path: / Policies: - PolicyName: taginstancepolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'ec2:Describe*' Resource: '*' - Effect: Allow Action: - 'ec2:CreateTags' Resource: - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:volume/*' - !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/*' InstanceProfile: Type: 'AWS::IAM::InstanceProfile' Properties: Path: / Roles: - !Ref InstanceRole myASG: Type: AWS::AutoScaling::AutoScalingGroup Properties: LaunchConfigurationName: !Ref myLaunchConfig MaxSize: '2' MinSize: '1' DesiredCapacity: '1' VPCZoneIdentifier: - !Ref Project1PublicSubnet1 - !Ref Project1PublicSubnet2 MetricsCollection: - Granularity: 1Minute Metrics: - GroupMinSize - GroupMaxSize TargetGroupARNs: - Ref: WebTierALBTargetGroup Tags: - Key: Name PropagateAtLaunch: true Value: Project1webapp - Key: Department PropagateAtLaunch: true Value: Digital myLaunchConfig: Type: AWS::AutoScaling::LaunchConfiguration Properties: ImageId: !Ref LatestAmiId SecurityGroups: - !GetAtt WebAppSG.GroupId InstanceType: !Ref InstanceType IamInstanceProfile: !Ref InstanceProfile UserData: Fn::Base64: | #!/bin/bash AWS_AVAIL_ZONE=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone) AWS_REGION=${AWS_AVAIL_ZONE::-1} AWS_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id) ROOT_VOLUME_IDS=$(aws ec2 describe-instances --region $AWS_REGION --instance-id $AWS_INSTANCE_ID --output text --query Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId) aws ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=Name,Value=Project1Volume Key=Department,Value=Digital yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd echo '

Hello World

' > /var/www/html/index.html WebTierLoadBalancer: Type: "AWS::ElasticLoadBalancingV2::LoadBalancer" Properties: Name: Project1WebTierLoadBalancer Subnets: - !Ref Project1PublicSubnet1 - !Ref Project1PublicSubnet2 SecurityGroups: - !GetAtt ApplicationLoadBalancerSG.GroupId Tags: - Key: Name Value: Project1WebTierLoadBalancer - Key: Department Value: Digital WebTierListener: Type: "AWS::ElasticLoadBalancingV2::Listener" Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref WebTierALBTargetGroup LoadBalancerArn: !Ref WebTierLoadBalancer Port: "80" Protocol: HTTP WebTierALBTargetGroup: Type: "AWS::ElasticLoadBalancingV2::TargetGroup" Properties: HealthCheckIntervalSeconds: 30 HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 2 Port: 80 Protocol: HTTP UnhealthyThresholdCount: 5 VpcId: !Ref VPC Database: Type: AWS::RDS::DBInstance Properties: VPCSecurityGroups: - !GetAtt DatabaseSG.GroupId AllocatedStorage: '20' PubliclyAccessible: 'false' DBInstanceClass: db.t2.micro Engine: MySQL DBInstanceIdentifier: Project1Database MasterUsername: MyName MasterUserPassword: MyPassword DBSubnetGroupName: !Ref DatabaseSubnetGroup AutoMinorVersionUpgrade: false BackupRetentionPeriod: '0' AvailabilityZone: !Select - 0 - !GetAZs Ref: 'AWS::Region' Tags: - Key: Name Value: Project1Database - Key: Department Value: Digital #must have this or your VPC isnt a VPC Database, this allows the DB to know which instances to be in DatabaseSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: subnet group SubnetIds: - !Ref Project1PublicSubnet1 - !Ref Project1PublicSubnet2 - !Ref Project1PrivateSubnet1 - !Ref Project1PrivateSubnet2