├── .github └── workflows │ └── manual.yml ├── CODEOWNERS ├── README.md ├── project_starter ├── README.md ├── final-project-starter.yml └── server-parameters.json └── supporting_material ├── AWSWebApp.jpeg ├── challenges ├── challenge1-parameters.json ├── challenge1.yml ├── challenge2-solution-parameters.json ├── challenge2-solution.yml ├── challenge3-parameters.json └── challenge3.yml ├── create copy.bat ├── create.sh ├── network-parameters.json ├── network.yml ├── server-parameters.json ├── servers.yml ├── update.bat └── update.sh /.github/workflows/manual.yml: -------------------------------------------------------------------------------- 1 | # Workflow to ensure whenever a Github PR is submitted, 2 | # a JIRA ticket gets created automatically. 3 | name: Manual Workflow 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on pull request events but only for the master branch 8 | pull_request_target: 9 | types: [opened, reopened] 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | jobs: 15 | test-transition-issue: 16 | name: Convert Github Issue to Jira Issue 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@master 21 | 22 | - name: Login 23 | uses: atlassian/gajira-login@master 24 | env: 25 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 26 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 27 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 28 | 29 | - name: Create NEW JIRA ticket 30 | id: create 31 | uses: atlassian/gajira-create@master 32 | with: 33 | project: CONUPDATE 34 | issuetype: Task 35 | summary: | 36 | Github PR nd9991 - Cloud DevOps Engineer | Repo: ${{ github.repository }} | PR# ${{github.event.number}} 37 | description: | 38 | Repo link: https://github.com/${{ github.repository }} 39 | PR no. ${{ github.event.pull_request.number }} 40 | PR title: ${{ github.event.pull_request.title }} 41 | PR description: ${{ github.event.pull_request.description }} 42 | In addition, please resolve other issues, if any. 43 | fields: '{"components": [{"name":"nd9991 - Cloud DevOps Engineer"}], "customfield_16449":"https://classroom.udacity.com/", "customfield_16450":"Resolve the PR", "labels": ["github"], "priority":{"id": "4"}}' 44 | 45 | - name: Log created issue 46 | run: echo "Issue ${{ steps.create.outputs.issue }} was created" 47 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @udacity/active-public-content -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ND9991 - C2- Infrastructure as Code - Supporting Material and Starter Code 2 | This folder provides the supporting material and starter code for the "ND9991 - C2- Infrastructure as Code" course. This folder contains the following folders: 3 | 1. project_starter - It contains the starter code. 4 | 2. supporting_material - It contains the essential files (.yml, .json, .bat, .sh, and .jpeg) that were referred in the different lessons of this course. 5 | 6 | In addition to the current repo, there is one more repository, [nd9991-c2-Infrastructure-as-Code-v1-Exercises_Solution](https://github.com/udacity/nd9991-c2-Infrastructure-as-Code-v1-Exercises_Solution) that contains the solution to the exercises and video demos. 7 | 8 | ### Dependencies 9 | ##### 1. AWS account 10 | You would require to have an AWS account to be able to build cloud infrastructure. 11 | 12 | ##### 2. VS code editor 13 | An editor would be helpful to visualize the image as well as code. Download the VS Code editor [here](https://code.visualstudio.com/download). 14 | 15 | ##### 3. An account on www.lucidchart.com 16 | A free user-account on [www.lucidchart.com](www.lucidchart.com) is required to be able to draw the web app architecture diagrams for AWS. 17 | 18 | 19 | ### How to run the supporting material? 20 | You can run the supporting material in two easy steps: 21 | ```bash 22 | # Ensure that the AWS CLI is configured before runniing the command below 23 | # Create the network infrastructure 24 | # Check the region in the create.sh file 25 | ./create.sh myFirstStack network.yml network-parameters.json 26 | # Create servers 27 | # Change the AMI ID and key-pair name in the servers.yml 28 | # Check the region in the update.sh file 29 | ./update.sh mySecStack servers.yml server-parameters.json 30 | ``` -------------------------------------------------------------------------------- /project_starter/README.md: -------------------------------------------------------------------------------- 1 | ### Project Title - Deploy a high-availability web app using CloudFormation 2 | This folder provides the starter code for the "ND9991 - C2- Infrastructure as Code - Deploy a high-availability web app using CloudFormation" project. This folder contains the following files: 3 | 4 | 5 | #### final-project-starter.yml 6 | Students have to write the CloudFormation code using this YAML template for building the cloud infrastructure, as required for the project. 7 | 8 | #### server-parameters.json 9 | Students may use a JSON file for increasing the generic nature of the YAML code. For example, the JSON file contains a "ParameterKey" as "EnvironmentName" and "ParameterValue" as "UdacityProject". 10 | 11 | In YAML code, the `${EnvironmentName}` would be substituted with `UdacityProject` accordingly. -------------------------------------------------------------------------------- /project_starter/final-project-starter.yml: -------------------------------------------------------------------------------- 1 | Parameters: 2 | # Paramenters are entirely optional. 3 | # but using them will make your cloudformation templates more reusable 4 | # use them for things that may change over time, such as instance type, 5 | # VPCs and so on. 6 | Resources: 7 | # instace profile contains the IAM Role name(s) that we want to associate to our auto scaling EC2 Servers 8 | # never give too much permissions to your EC2 instances! if they get hacked, the permissions get hacked also! 9 | # in this example, I create a Role called UdacityS3ReadOnlyC2 and just give it a policy of S3 Read-Only Access 10 | ProfileWithRolesForOurApp: 11 | Type: AWS::IAM::InstanceProfile 12 | Properties: 13 | Roles: 14 | - UdacityS3ReadOnlyEC2 15 | Outputs: 16 | # This is also optional. 17 | # Bonus points for useful outputs! 18 | # for example, if you create a Load Balancer 19 | # it's nice to output the URL to it here, so that we don't have to go to the console to get it. 20 | 21 | # Sample UserData 22 | # When creating your Launch Configuration, you may need a UserData script 23 | # here's one that you can use for Ubuntu Linux that will: 24 | # Install Apache Web Server, Start it, and create an index.html that will be displayed 25 | # when you visit the IP address of this server with your web browser 26 | #Here it is: 27 | # 28 | # #!/bin/bash 29 | # apt-get update -y 30 | # apt-get install apache2 -y 31 | # systemctl start apache2.service 32 | # cd /var/www/html 33 | # echo "Udacity Demo Web Server Up and Running!" > index.html 34 | -------------------------------------------------------------------------------- /project_starter/server-parameters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ParameterKey": "EnvironmentName", 4 | "ParameterValue": "UdacityProject" 5 | } 6 | ] -------------------------------------------------------------------------------- /supporting_material/AWSWebApp.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/nd9991-c2-Infrastructure-as-Code-v1/0b54583260f2692b385cd0fe6a645a02a3a67661/supporting_material/AWSWebApp.jpeg -------------------------------------------------------------------------------- /supporting_material/challenges/challenge1-parameters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ParameterKey": "myVPC", 4 | "ParameterValue": "vpc-cb298db6" 5 | }, 6 | { 7 | "ParameterKey": "PublicSubnet", 8 | "ParameterValue": "subnet-3425b06b" 9 | }, 10 | { 11 | "ParameterKey": "AMItoUse", 12 | "ParameterValue": "ami-047a51fa27710816e" 13 | } 14 | ] -------------------------------------------------------------------------------- /supporting_material/challenges/challenge1.yml: -------------------------------------------------------------------------------- 1 | Parameters: 2 | myVPC: 3 | Description: VPC used to deploy our resources below 4 | Type: AWS::EC2::VPC::Id 5 | PublicSubnet: 6 | Description: Subnet to be used for our Web Server 7 | Type: AWS::EC2::Subnet::Id 8 | AMItoUse: 9 | Description: AMI to use for our base image 10 | Type: String 11 | Resources: 12 | myWebAccessSecurityGroup: 13 | Type: AWS::EC2::SecurityGroup 14 | Properties: 15 | GroupDescription: Allow http to our test host 16 | VpcId: 17 | Ref: myVPC 18 | SecurityGroupIngress: 19 | - IpProtocol: tcp 20 | FromPort: 80 21 | ToPort: 80 22 | CidrIp: 0.0.0.0/0 23 | SecurityGroupEgress: 24 | - IpProtocol: -1 25 | FromPort: -1 26 | ToPort: -1 27 | CidrIp: 0.0.0.0/0 28 | myWebServerInstance: 29 | Type: AWS::EC2::Instance 30 | Properties: 31 | InstanceType: t3.micro 32 | ImageId: !Ref AMItoUse 33 | NetworkInterfaces: 34 | - AssociatePublicIpAddress: "true" 35 | DeviceIndex: "0" 36 | GroupSet: 37 | - Ref: "myWebAccessSecurityGroup" 38 | SubnetId: 39 | Ref: "PublicSubnet" 40 | UserData: 41 | Fn::Base64: !Sub | 42 | #!/bin/bash 43 | yum update -y 44 | yum install -y httpd 45 | systemctl start httpd 46 | -------------------------------------------------------------------------------- /supporting_material/challenges/challenge2-solution-parameters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ParameterKey": "VPCCIDR", 4 | "ParameterValue": "10.0.0.0/16" 5 | }, 6 | { 7 | "ParameterKey": "PubSubnetCIDR", 8 | "ParameterValue": "10.0.1.0/24" 9 | }, 10 | { 11 | "ParameterKey": "PrivSubnetCIDR", 12 | "ParameterValue": "10.0.2.0/24" 13 | } 14 | ] -------------------------------------------------------------------------------- /supporting_material/challenges/challenge2-solution.yml: -------------------------------------------------------------------------------- 1 | # Infrastructure as Code 2 | # Exercise solution 3 | # Carlos Rivas February 2021 4 | 5 | AWSTemplateFormatVersion: "2010-09-09" 6 | Description: Creates the required network infrastructure for Public and Private routing with Internet access 7 | Parameters: 8 | VPCCIDR: 9 | Type: String 10 | PrivSubnetCIDR: 11 | Type: String 12 | PubSubnetCIDR: 13 | Type: String 14 | Resources: 15 | MainVPC: 16 | Type: AWS::EC2::VPC 17 | Properties: 18 | CidrBlock: !Ref VPCCIDR 19 | Tags: 20 | - Key: Name 21 | Value: "Main VPC" 22 | InternetGW: 23 | Type: AWS::EC2::InternetGateway 24 | AttachInternetGateway: 25 | Type: AWS::EC2::VPCGatewayAttachment 26 | Properties: 27 | VpcId: !Ref MainVPC 28 | InternetGatewayId: !Ref InternetGW 29 | PublicSubnet1: 30 | Type: AWS::EC2::Subnet 31 | Properties: 32 | # Availability zone at your discretion or 33 | # as a parameter 34 | AvailabilityZone: 'us-east-1a' 35 | CidrBlock: !Ref PubSubnetCIDR 36 | MapPublicIpOnLaunch: true 37 | Tags: 38 | - Key: Name 39 | Value: "Public Subnet AZ1" 40 | VpcId: !Ref MainVPC 41 | PrivateSubnet1: 42 | Type: AWS::EC2::Subnet 43 | Properties: 44 | AvailabilityZone: 'us-east-1b' 45 | CidrBlock: !Ref PrivSubnetCIDR 46 | MapPublicIpOnLaunch: false 47 | Tags: 48 | - Key: Name 49 | Value: "Private Subnet AZ1" 50 | VpcId: !Ref MainVPC 51 | NAT: 52 | Type: AWS::EC2::NatGateway 53 | Properties: 54 | AllocationId: 55 | Fn::GetAtt: 56 | - EIP 57 | - AllocationId 58 | SubnetId: !Ref PublicSubnet1 59 | Tags: 60 | - Key: Name 61 | Value: "NAT to be used by servers in the private subnet" 62 | EIP: 63 | Type: AWS::EC2::EIP 64 | Properties: 65 | Tags: 66 | - Key: Name 67 | Value: "Elastic IP for our NAT Gateway" 68 | PrivateRouteTable: 69 | Type: AWS::EC2::RouteTable 70 | Properties: 71 | Tags: 72 | - Key: Name 73 | Value: "Private Route Table" 74 | VpcId: !Ref MainVPC 75 | PublicRouteTable: 76 | Type: AWS::EC2::RouteTable 77 | Properties: 78 | Tags: 79 | - Key: Name 80 | Value: "Public Route Table" 81 | VpcId: !Ref MainVPC 82 | AssociatePUBRT: 83 | Type: AWS::EC2::SubnetRouteTableAssociation 84 | Properties: 85 | RouteTableId: !Ref PublicRouteTable 86 | SubnetId: !Ref PublicSubnet1 87 | AssociatePRIVRT: 88 | Type: AWS::EC2::SubnetRouteTableAssociation 89 | Properties: 90 | RouteTableId: !Ref PrivateRouteTable 91 | SubnetId: !Ref PrivateSubnet1 92 | PublicInternetRoute: 93 | Type: AWS::EC2::Route 94 | Properties: 95 | RouteTableId: 96 | Ref: PublicRouteTable 97 | DestinationCidrBlock: 0.0.0.0/0 98 | GatewayId: 99 | Ref: InternetGW 100 | PrivateInternetOutboundRoute: 101 | Type: AWS::EC2::Route 102 | Properties: 103 | RouteTableId: 104 | Ref: PrivateRouteTable 105 | DestinationCidrBlock: 0.0.0.0/0 106 | NatGatewayId: 107 | Ref: NAT -------------------------------------------------------------------------------- /supporting_material/challenges/challenge3-parameters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ParameterKey": "myVPC", 4 | "ParameterValue": "vpc-049aec40a1d6c62ad" 5 | }, 6 | { 7 | "ParameterKey": "SubnetForServer", 8 | "ParameterValue": "subnet-086fb2bdbcbd5fd67" 9 | }, 10 | { 11 | "ParameterKey": "AMItoUse", 12 | "ParameterValue": "ami-047a51fa27710816e" 13 | } 14 | ] -------------------------------------------------------------------------------- /supporting_material/challenges/challenge3.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Exercise 3 Solution 3 | # Carlos Rivas / February 2021 4 | # 5 | Parameters: 6 | myVPC: 7 | Description: VPC used to deploy our resources below 8 | Type: AWS::EC2::VPC::Id 9 | SubnetForServer: 10 | Description: Subnet to be used for our Web Server 11 | Type: AWS::EC2::Subnet::Id 12 | AMItoUse: 13 | Description: AMI to use for our base image 14 | Type: String 15 | Resources: 16 | # IAM Role to allow EC2 Session Manager to access our server 17 | RoleForSSMAccess: 18 | Type: "AWS::IAM::Role" 19 | Properties: 20 | AssumeRolePolicyDocument: 21 | Version: "2012-10-17" 22 | Statement: 23 | - Effect: Allow 24 | Principal: 25 | Service: 26 | - ec2.amazonaws.com 27 | Action: 28 | - 'sts:AssumeRole' 29 | ManagedPolicyArns: 30 | - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore 31 | # Instance Profile 32 | ServerInstanceProfile: 33 | Type: "AWS::IAM::InstanceProfile" 34 | Properties: 35 | Roles: 36 | - !Ref RoleForSSMAccess 37 | # Security Group 38 | WebAccessSecurityGroup: 39 | Type: AWS::EC2::SecurityGroup 40 | Properties: 41 | GroupDescription: Allow http to our test host 42 | VpcId: 43 | Ref: myVPC 44 | SecurityGroupIngress: 45 | - IpProtocol: tcp 46 | FromPort: 80 47 | ToPort: 80 48 | CidrIp: 0.0.0.0/0 49 | SecurityGroupEgress: 50 | - IpProtocol: -1 51 | FromPort: -1 52 | ToPort: -1 53 | CidrIp: 0.0.0.0/0 54 | # Server EC2 Instance 55 | ServerInstance: 56 | Type: AWS::EC2::Instance 57 | Properties: 58 | InstanceType: t3.micro 59 | ImageId: !Ref AMItoUse 60 | IamInstanceProfile: !Ref ServerInstanceProfile 61 | NetworkInterfaces: 62 | - AssociatePublicIpAddress: "true" 63 | DeviceIndex: "0" 64 | GroupSet: 65 | - Ref: "WebAccessSecurityGroup" 66 | SubnetId: 67 | Ref: "SubnetForServer" 68 | -------------------------------------------------------------------------------- /supporting_material/create copy.bat: -------------------------------------------------------------------------------- 1 | aws cloudformation create-stack --stack-name %1 --template-body file://%2 --parameters file://%3 --capabilities "CAPABILITY_IAM" "CAPABILITY_NAMED_IAM" --region=us-west-2 -------------------------------------------------------------------------------- /supporting_material/create.sh: -------------------------------------------------------------------------------- 1 | aws cloudformation create-stack --stack-name $1 --template-body file://$2 --parameters file://$3 --capabilities "CAPABILITY_IAM" "CAPABILITY_NAMED_IAM" --region=us-east-1 2 | -------------------------------------------------------------------------------- /supporting_material/network-parameters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ParameterKey": "EnvironmentName", 4 | "ParameterValue": "UdacityProject" 5 | }, 6 | { 7 | "ParameterKey": "VpcCIDR", 8 | "ParameterValue": "10.0.0.0/16" 9 | }, 10 | { 11 | "ParameterKey": "PublicSubnet1CIDR", 12 | "ParameterValue": "10.0.0.0/24" 13 | }, 14 | { 15 | "ParameterKey": "PublicSubnet2CIDR", 16 | "ParameterValue": "10.0.1.0/24" 17 | }, 18 | { 19 | "ParameterKey": "PrivateSubnet1CIDR", 20 | "ParameterValue": "10.0.2.0/24" 21 | }, 22 | { 23 | "ParameterKey": "PrivateSubnet2CIDR", 24 | "ParameterValue": "10.0.3.0/24" 25 | } 26 | ] -------------------------------------------------------------------------------- /supporting_material/network.yml: -------------------------------------------------------------------------------- 1 | Description: > 2 | Carlos Rivas / Udacity 3 | This template deploys a VPC, with a pair of public and private subnets spread 4 | across two Availabilty Zones. It deploys an Internet Gateway, with a default 5 | route on the public subnets. It deploys a pair of NAT Gateways (one in each AZ), 6 | and default routes for them in the private subnets. 7 | 8 | Parameters: 9 | 10 | EnvironmentName: 11 | Description: An environment name that will be prefixed to resource names 12 | Type: String 13 | 14 | VpcCIDR: 15 | Description: Please enter the IP range (CIDR notation) for this VPC 16 | Type: String 17 | Default: 10.0.0.0/16 18 | 19 | PublicSubnet1CIDR: 20 | Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone 21 | Type: String 22 | Default: 10.0.0.0/24 23 | 24 | PublicSubnet2CIDR: 25 | Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone 26 | Type: String 27 | Default: 10.0.1.0/24 28 | 29 | PrivateSubnet1CIDR: 30 | Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone 31 | Type: String 32 | Default: 10.0.2.0/24 33 | 34 | PrivateSubnet2CIDR: 35 | Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone 36 | Type: String 37 | Default: 10.0.3.0/24 38 | 39 | Resources: 40 | 41 | VPC: 42 | Type: AWS::EC2::VPC 43 | Properties: 44 | CidrBlock: !Ref VpcCIDR 45 | EnableDnsHostnames: true 46 | Tags: 47 | - Key: Name 48 | Value: !Ref EnvironmentName 49 | 50 | InternetGateway: 51 | Type: AWS::EC2::InternetGateway 52 | Properties: 53 | Tags: 54 | - Key: Name 55 | Value: !Ref EnvironmentName 56 | 57 | InternetGatewayAttachment: 58 | Type: AWS::EC2::VPCGatewayAttachment 59 | Properties: 60 | InternetGatewayId: !Ref InternetGateway 61 | VpcId: !Ref VPC 62 | 63 | PublicSubnet1: 64 | Type: AWS::EC2::Subnet 65 | Properties: 66 | VpcId: !Ref VPC 67 | AvailabilityZone: !Select [ 0, !GetAZs '' ] 68 | CidrBlock: !Ref PublicSubnet1CIDR 69 | MapPublicIpOnLaunch: true 70 | Tags: 71 | - Key: Name 72 | Value: !Sub ${EnvironmentName} Public Subnet (AZ1) 73 | 74 | PublicSubnet2: 75 | Type: AWS::EC2::Subnet 76 | Properties: 77 | VpcId: !Ref VPC 78 | AvailabilityZone: !Select [ 1, !GetAZs '' ] 79 | CidrBlock: !Ref PublicSubnet2CIDR 80 | MapPublicIpOnLaunch: true 81 | Tags: 82 | - Key: Name 83 | Value: !Sub ${EnvironmentName} Public Subnet (AZ2) 84 | 85 | PrivateSubnet1: 86 | Type: AWS::EC2::Subnet 87 | Properties: 88 | VpcId: !Ref VPC 89 | AvailabilityZone: !Select [ 0, !GetAZs '' ] 90 | CidrBlock: !Ref PrivateSubnet1CIDR 91 | MapPublicIpOnLaunch: false 92 | Tags: 93 | - Key: Name 94 | Value: !Sub ${EnvironmentName} Private Subnet (AZ1) 95 | 96 | PrivateSubnet2: 97 | Type: AWS::EC2::Subnet 98 | Properties: 99 | VpcId: !Ref VPC 100 | AvailabilityZone: !Select [ 1, !GetAZs '' ] 101 | CidrBlock: !Ref PrivateSubnet2CIDR 102 | MapPublicIpOnLaunch: false 103 | Tags: 104 | - Key: Name 105 | Value: !Sub ${EnvironmentName} Private Subnet (AZ2) 106 | 107 | NatGateway1EIP: 108 | Type: AWS::EC2::EIP 109 | DependsOn: InternetGatewayAttachment 110 | Properties: 111 | Domain: vpc 112 | 113 | NatGateway2EIP: 114 | Type: AWS::EC2::EIP 115 | DependsOn: InternetGatewayAttachment 116 | Properties: 117 | Domain: vpc 118 | 119 | NatGateway1: 120 | Type: AWS::EC2::NatGateway 121 | Properties: 122 | AllocationId: !GetAtt NatGateway1EIP.AllocationId 123 | SubnetId: !Ref PublicSubnet1 124 | 125 | NatGateway2: 126 | Type: AWS::EC2::NatGateway 127 | Properties: 128 | AllocationId: !GetAtt NatGateway2EIP.AllocationId 129 | SubnetId: !Ref PublicSubnet2 130 | 131 | PublicRouteTable: 132 | Type: AWS::EC2::RouteTable 133 | Properties: 134 | VpcId: !Ref VPC 135 | Tags: 136 | - Key: Name 137 | Value: !Sub ${EnvironmentName} Public Routes 138 | 139 | DefaultPublicRoute: 140 | Type: AWS::EC2::Route 141 | DependsOn: InternetGatewayAttachment 142 | Properties: 143 | RouteTableId: !Ref PublicRouteTable 144 | DestinationCidrBlock: 0.0.0.0/0 145 | GatewayId: !Ref InternetGateway 146 | 147 | PublicSubnet1RouteTableAssociation: 148 | Type: AWS::EC2::SubnetRouteTableAssociation 149 | Properties: 150 | RouteTableId: !Ref PublicRouteTable 151 | SubnetId: !Ref PublicSubnet1 152 | 153 | PublicSubnet2RouteTableAssociation: 154 | Type: AWS::EC2::SubnetRouteTableAssociation 155 | Properties: 156 | RouteTableId: !Ref PublicRouteTable 157 | SubnetId: !Ref PublicSubnet2 158 | 159 | 160 | PrivateRouteTable1: 161 | Type: AWS::EC2::RouteTable 162 | Properties: 163 | VpcId: !Ref VPC 164 | Tags: 165 | - Key: Name 166 | Value: !Sub ${EnvironmentName} Private Routes (AZ1) 167 | 168 | DefaultPrivateRoute1: 169 | Type: AWS::EC2::Route 170 | Properties: 171 | RouteTableId: !Ref PrivateRouteTable1 172 | DestinationCidrBlock: 0.0.0.0/0 173 | NatGatewayId: !Ref NatGateway1 174 | 175 | PrivateSubnet1RouteTableAssociation: 176 | Type: AWS::EC2::SubnetRouteTableAssociation 177 | Properties: 178 | RouteTableId: !Ref PrivateRouteTable1 179 | SubnetId: !Ref PrivateSubnet1 180 | 181 | PrivateRouteTable2: 182 | Type: AWS::EC2::RouteTable 183 | Properties: 184 | VpcId: !Ref VPC 185 | Tags: 186 | - Key: Name 187 | Value: !Sub ${EnvironmentName} Private Routes (AZ2) 188 | 189 | DefaultPrivateRoute2: 190 | Type: AWS::EC2::Route 191 | Properties: 192 | RouteTableId: !Ref PrivateRouteTable2 193 | DestinationCidrBlock: 0.0.0.0/0 194 | NatGatewayId: !Ref NatGateway2 195 | 196 | PrivateSubnet2RouteTableAssociation: 197 | Type: AWS::EC2::SubnetRouteTableAssociation 198 | Properties: 199 | RouteTableId: !Ref PrivateRouteTable2 200 | SubnetId: !Ref PrivateSubnet2 201 | 202 | Outputs: 203 | 204 | VPC: 205 | Description: A reference to the created VPC 206 | Value: !Ref VPC 207 | Export: 208 | Name: !Sub ${EnvironmentName}-VPCID 209 | 210 | VPCPublicRouteTable: 211 | Description: Public Routing 212 | Value: !Ref PublicRouteTable 213 | Export: 214 | Name: !Sub ${EnvironmentName}-PUB-RT 215 | 216 | VPCPrivateRouteTable1: 217 | Description: Private Routing AZ1 218 | Value: !Ref PrivateRouteTable1 219 | Export: 220 | Name: !Sub ${EnvironmentName}-PRI1-RT 221 | 222 | VPCPrivateRouteTable2: 223 | Description: Private Routing AZ2 224 | Value: !Ref PrivateRouteTable2 225 | Export: 226 | Name: !Sub ${EnvironmentName}-PRI2-RT 227 | 228 | PublicSubnets: 229 | Description: A list of the public subnets 230 | Value: !Join [ ",", [ !Ref PublicSubnet1, !Ref PublicSubnet2 ]] 231 | Export: 232 | Name: !Sub ${EnvironmentName}-PUB-NETS 233 | 234 | PrivateSubnets: 235 | Description: A list of the private subnets 236 | Value: !Join [ ",", [ !Ref PrivateSubnet1, !Ref PrivateSubnet2 ]] 237 | Export: 238 | Name: !Sub ${EnvironmentName}-PRIV-NETS 239 | 240 | PublicSubnet1: 241 | Description: A reference to the public subnet in the 1st Availability Zone 242 | Value: !Ref PublicSubnet1 243 | Export: 244 | Name: !Sub ${EnvironmentName}-PUB1-SN 245 | 246 | PublicSubnet2: 247 | Description: A reference to the public subnet in the 2nd Availability Zone 248 | Value: !Ref PublicSubnet2 249 | Export: 250 | Name: !Sub ${EnvironmentName}-PUB2-SN 251 | 252 | PrivateSubnet1: 253 | Description: A reference to the private subnet in the 1st Availability Zone 254 | Value: !Ref PrivateSubnet1 255 | Export: 256 | Name: !Sub ${EnvironmentName}-PRI1-SN 257 | 258 | PrivateSubnet2: 259 | Description: A reference to the private subnet in the 2nd Availability Zone 260 | Value: !Ref PrivateSubnet2 261 | Export: 262 | Name: !Sub ${EnvironmentName}-PRI2-SN -------------------------------------------------------------------------------- /supporting_material/server-parameters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ParameterKey": "EnvironmentName", 4 | "ParameterValue": "UdacityProject" 5 | } 6 | ] -------------------------------------------------------------------------------- /supporting_material/servers.yml: -------------------------------------------------------------------------------- 1 | Description: > 2 | Carlos Rivas / Udacity 2019 3 | 4 | Parameters: 5 | 6 | EnvironmentName: 7 | Description: An environment name that will be prefixed to resource names 8 | Type: String 9 | Resources: 10 | LBSecGroup: 11 | Type: AWS::EC2::SecurityGroup 12 | Properties: 13 | GroupDescription: Allow http to our load balancer 14 | VpcId: 15 | Fn::ImportValue: 16 | !Sub "${EnvironmentName}-VPCID" 17 | SecurityGroupIngress: 18 | - IpProtocol: tcp 19 | FromPort: 80 20 | ToPort: 80 21 | CidrIp: 0.0.0.0/0 22 | SecurityGroupEgress: 23 | - IpProtocol: tcp 24 | FromPort: 80 25 | ToPort: 80 26 | CidrIp: 0.0.0.0/0 27 | WebServerSecGroup: 28 | Type: AWS::EC2::SecurityGroup 29 | Properties: 30 | GroupDescription: Allow http to our hosts and SSH from local only 31 | VpcId: 32 | Fn::ImportValue: 33 | !Sub "${EnvironmentName}-VPCID" 34 | SecurityGroupIngress: 35 | - IpProtocol: tcp 36 | FromPort: 8080 37 | ToPort: 8080 38 | CidrIp: 0.0.0.0/0 39 | - IpProtocol: tcp 40 | FromPort: 22 41 | ToPort: 22 42 | CidrIp: 0.0.0.0/0 43 | SecurityGroupEgress: 44 | - IpProtocol: tcp 45 | FromPort: 0 46 | ToPort: 65535 47 | CidrIp: 0.0.0.0/0 48 | WebAppLaunchConfig: 49 | Type: AWS::AutoScaling::LaunchConfiguration 50 | Properties: 51 | UserData: 52 | Fn::Base64: !Sub | 53 | #!/bin/bash 54 | sudo apt-get update -y 55 | sudo apt-get install apache2 -y 56 | sudo systemctl start apache2.service 57 | # ToDo: AMI ID of Ubuntu Linux machine. Too get one, try creating a VM from the web console. 58 | ImageId: ami-0747bdcabd34c712a 59 | # ToDo: Change the key-pair name, as applicable to you. 60 | KeyName: nd9990_keypair 61 | SecurityGroups: 62 | - Ref: WebServerSecGroup 63 | InstanceType: t3.medium 64 | BlockDeviceMappings: 65 | - DeviceName: "/dev/sdk" 66 | Ebs: 67 | VolumeSize: '10' 68 | WebAppGroup: 69 | Type: AWS::AutoScaling::AutoScalingGroup 70 | Properties: 71 | VPCZoneIdentifier: 72 | - Fn::ImportValue: 73 | !Sub "${EnvironmentName}-PRIV-NETS" 74 | LaunchConfigurationName: 75 | Ref: WebAppLaunchConfig 76 | MinSize: '3' 77 | MaxSize: '5' 78 | TargetGroupARNs: 79 | - Ref: WebAppTargetGroup 80 | WebAppLB: 81 | Type: AWS::ElasticLoadBalancingV2::LoadBalancer 82 | Properties: 83 | Subnets: 84 | - Fn::ImportValue: !Sub "${EnvironmentName}-PUB1-SN" 85 | - Fn::ImportValue: !Sub "${EnvironmentName}-PUB2-SN" 86 | SecurityGroups: 87 | - Ref: LBSecGroup 88 | Listener: 89 | Type: AWS::ElasticLoadBalancingV2::Listener 90 | Properties: 91 | DefaultActions: 92 | - Type: forward 93 | TargetGroupArn: 94 | Ref: WebAppTargetGroup 95 | LoadBalancerArn: 96 | Ref: WebAppLB 97 | Port: '80' 98 | Protocol: HTTP 99 | ALBListenerRule: 100 | Type: AWS::ElasticLoadBalancingV2::ListenerRule 101 | Properties: 102 | Actions: 103 | - Type: forward 104 | TargetGroupArn: !Ref 'WebAppTargetGroup' 105 | Conditions: 106 | - Field: path-pattern 107 | Values: [/] 108 | ListenerArn: !Ref 'Listener' 109 | Priority: 1 110 | WebAppTargetGroup: 111 | Type: AWS::ElasticLoadBalancingV2::TargetGroup 112 | Properties: 113 | HealthCheckIntervalSeconds: 10 114 | HealthCheckPath: / 115 | HealthCheckProtocol: HTTP 116 | HealthCheckTimeoutSeconds: 8 117 | HealthyThresholdCount: 2 118 | Port: 8080 119 | Protocol: HTTP 120 | UnhealthyThresholdCount: 5 121 | VpcId: 122 | Fn::ImportValue: 123 | Fn::Sub: "${EnvironmentName}-VPCID" 124 | -------------------------------------------------------------------------------- /supporting_material/update.bat: -------------------------------------------------------------------------------- 1 | aws cloudformation update-stack --stack-name %1 --template-body file://%2 --parameters file://%3 --capabilities "CAPABILITY_IAM" "CAPABILITY_NAMED_IAM" --region=us-west-2 2 | -------------------------------------------------------------------------------- /supporting_material/update.sh: -------------------------------------------------------------------------------- 1 | aws cloudformation update-stack --stack-name $1 --template-body file://$2 --parameters file://$3 --capabilities "CAPABILITY_IAM" "CAPABILITY_NAMED_IAM" --region=us-east-1 2 | --------------------------------------------------------------------------------