uacbt_2_web.yaml
---

CloudFormation template for UACBT (Computer-Based Training) authentication server (2 of 2)

  • Deploys an ELBv2 (ALB)
  • Deploys a Windows EC2 instance via an Auto Scaling Group with min/max/desired = 1 tied to the ELBv2 target group
  • Installs IIS & Shibboleth SP on EC2 and pulls code/config from S3 bucket
  • Configures IIS, enables CloudWatch Logs via SSM agent
  • Creates a Route53 alias to the ELBv2 DNS name
AWSTemplateFormatVersion: 2010-09-09 Description: UACBT (Web)

Parameters

These are the input parameters for this template. All of these parameters must be supplied for this template to be deployed.

Parameters:

RedirectURL is the URL that the site will redirect all non-login requests to

RedirectURL: Description: URL that the site will redirect all non-login requests to Type: String Default: https://it.arizona.edu/service/ua-computer-based-training

EmailForSNSSubscription is the email address to use for the SNS subscription

EmailForSNSSubscription: Description: Email address to use for the SNS subscription Type: String Default: uacbt-aws@list.arizona.edu

S3BucketName name of the S3 bucket (created in template 1 of 2)

  • ua-uits-general-nonprod: edu-arizona-uits-general-nonprod-uacbt-tst
  • ua-erp: edu-arizona-uits-general-prod-uacbt-prd
S3BucketName: Description: Name of the S3 bucket(created in template 1 of 2) Type: String Default: edu-arizona-uits-general-prod-uacbt-prd

WebServerInstanceType is the instance type to use for EC2 instance

WebServerInstanceType: Description: Instance type to use for EC2 instance Type: String Default: t2.micro

AMI to use for the Windows EC2 instance

AmiId: Description: AMI ID to use for the Windows EC2 instance Type: String Default: ami-3c4ba944

Key Pair to be used on the EC2 instance (for retrieving the Windows administrator password)

  • ua-uits-general-nonprod: dbaty-keypair
  • ua-erp: uacbt-keypair
KeyName: Description: EC2 Keypair Name Type: AWS::EC2::KeyPair::KeyName Default: uacbt-keypair

VPCID is the ID of the VPC where this template will be deployed.

VPCID:
  • ua-uits-general-nonprod: vpc-23b34745
  • ua-erp: vpc-a6d6fdc3
Description: Target VPC Type: AWS::EC2::VPC::Id Default: vpc-a6d6fdc3

PublicSubnetA is the public Subnet ID for us-west-2a

PublicSubnetA:
  • ua-uits-general-nonprod: subnet-834f4ee4
  • ua-erp: subnet-7eccf01b
Description: Public Subnet (us-west-2a) Type: AWS::EC2::Subnet::Id Default: subnet-7eccf01b

PublicSubnetB is the public Subnet ID for us-west-2b

  • ua-uits-general-nonprod: subnet-a00e56e9
  • ua-erp: subnet-2f9ac858
PublicSubnetB: Description: Public Subnet (us-west-2b) Type: AWS::EC2::Subnet::Id Default: subnet-2f9ac858

PrivateSubnetA is the private Subnet ID for us-west-2a

PrivateSubnetA:
  • ua-uits-general-nonprod: subnet-8f5051e8
  • ua-erp: subnet-79ccf01c
Description: Private Subnet (us-west-2a) Type: AWS::EC2::Subnet::Id Default: subnet-79ccf01c

PrivateSubnetB is the private Subnet ID for us-west-2b

  • ua-uits-general-nonprod: subnet-1c0c5455
  • ua-erp: subnet-2e9ac859
PrivateSubnetB: Description: Private Subnet (us-west-2b) Type: AWS::EC2::Subnet::Id Default: subnet-2e9ac859

HostedDNSZoneName is the named of the DNS hosted zone

  • ua-uits-general-nonprod: uits-nonprod-aws.arizona.edu
  • ua-erp: uits-prod-aws.arizona.edu
HostedDNSZoneName: Description: Name of the hosted DNS zone to use for the Route53 records (do NOT enter trailing period) Type: String Default: uits-prod-aws.arizona.edu

SSLCertARN is the ARN of the SSL certificate to use for the ELB

  • ua-uits-general-nonprod: arn:aws:acm:us-west-2:722748364533:certificate/351af538-7667-4961-8590-ea6dc116ab8c
  • ua-erp: arn:aws:acm:us-west-2:760232551367:certificate/a1cebc98-6742-48db-8669-93c232c5fb09
SSLCertARN: Description: ARN of the SSL certificate to use for the ELB (US-West-2) Type: String Default: arn:aws:acm:us-west-2:760232551367:certificate/a1cebc98-6742-48db-8669-93c232c5fb09

Tags

TagService: Description: Name of the service associated with this resource (as listed in the service catalog) Type: String Default: UACBT TagEnvironment: Description: Environment type of this resource (dev, tst, rpt, trn, prd) Type: String Default: prd AllowedValues: - dev - tst - rpt - trn - prd TagContactNetID: Description: NetID of the primary technical resource Type: String Default: dbaty TagTicketNumber: Description: Ticket number for the CLOUD Jira project Type: String Default: CLOUD-219 TagAccountNumber: Description: Account number associated with the service Type: String Default: 1192661 # Campus Software TagSubAccount: Description: Sub account associated with the service Type: String Default: Software Licensing Services

Metadata

Metadata is mostly for organizing and presenting Parameters in a better way when using CloudFormation in the AWS Web UI.

Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Settings Parameters: - RedirectURL - EmailForSNSSubscription - S3BucketName - WebServerInstanceType - KeyName - AmiId - VPCID - PrivateSubnetA - PrivateSubnetB - PublicSubnetA - PublicSubnetB - HostedDNSZoneName - SSLCertARN - Label: default: Tags Parameters: - TagService - TagEnvironment - TagContactNetID - TagTicketNumber - TagAccountNumber - TagSubAccount ParameterLabels: {}

Resources

Resources:

EC2 Security Groups

EC2 Security Group for the Elastic Load Balancer (ELB)

SecurityGroupForELB: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Sub EC2 Security Group for uacbt ELB (${TagEnvironment}) VpcId: !Ref VPCID SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: !Sub uacbt-${TagEnvironment}-sg--elb - Key: environment Value: !Ref TagEnvironment - Key: contactnetid Value: !Ref TagContactNetID - Key: ticketnumber Value: !Ref TagTicketNumber - Key: accountnumber Value: !Ref TagAccountNumber - Key: service Value: !Ref TagService

EC2 Security Group for the web server

SecurityGroupForWebServer: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Sub EC2 Security Group for uacbt web server (${TagEnvironment}) VpcId: !Ref VPCID SecurityGroupIngress: - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: 150.135.112.64/27 # InfraDev VPN - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: 150.135.112.96/27 # EntApp VPN - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !Ref SecurityGroupForELB Tags: - Key: Name Value: !Sub uacbt-${TagEnvironment}-sg-web - Key: environment Value: !Ref TagEnvironment - Key: contactnetid Value: !Ref TagContactNetID - Key: ticketnumber Value: !Ref TagTicketNumber - Key: accountnumber Value: !Ref TagAccountNumber - Key: service Value: !Ref TagService - Key: subaccount Value: !Ref TagSubAccount

Auto Scaling Groups

 - includes ASG, Scaling Policy, Launch Config & CW Alarms

Launch Configuration

LaunchConfig: Type: AWS::AutoScaling::LaunchConfiguration Properties: ImageId: !Ref AmiId KeyName: !Ref KeyName InstanceType: !Ref WebServerInstanceType InstanceMonitoring: true BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeType: gp2 DeleteOnTermination: true VolumeSize: 30 - DeviceName: xvdd Ebs: VolumeType: gp2 DeleteOnTermination: true VolumeSize: 4 IamInstanceProfile: !Ref IAMProfileWebServer SecurityGroups: - !Ref SecurityGroupForWebServer UserData: Fn::Base64: !Sub | <powershell> mkdir C:\bootstrap $( $environmentName = "${TagEnvironment}"
   $environmentName = "tst" #~~~ swap when in the CloudFormation template
$redirectURL = "${RedirectURL}"
   $redirectURL = "https://it.arizona.edu/service/ua-computer-based-training"  #~~~ swap when in the CloudFormation template
$hostHeaderRoot = "uacbt.arizona.edu" $hostHeader = Switch ($environmentName) { "prd" {"$($hostheaderRoot)"; break} "tst" {"test-login.$($hostheaderRoot)"; break} default {"$($environmentName)-login.$($hostheaderRoot)"; break} } $rootBootstrap = "C:\bootstrap" $rootApps = "D:\inetpub" $rootShib = "D:\opt\shibboleth-sp\etc\shibboleth"
  $s3bucket = "edu-arizona-pilots-uacbt-tst" #~~~ swap when in CloudFormation template 
$s3bucket = "${S3BucketName}" $s3keyApps = "WebServer\Apps\" $s3keyShib = "WebServer\Shibboleth\" $s3keySoftware = "WebServer\Software\" $s3keyScripts = "WebServer\Scripts\" $s3keyCerts = "WebServer\Certs\" $s3keySSM = "WebServer\SSM\" $iisLogFolder = "D:\IISLogs" $windowsFeatures = @("Web-WebServer", "Web-Mgmt-Console", "NET-Framework-45-ASPNET", "Web-IP-Security", "Web-Net-Ext45", "Web-Asp-Net45", "Web-ISAPI-Ext", "Web-ISAPI-Filter", "Web-Http-Redirect") $msiInstalls = @{} $msiInstalls.Add("UrlRewrite", "http://download.microsoft.com/download/6/7/D/67D80164-7DD0-48AF-86E3-DE7A182D6815/rewrite_2.0_rtw_x64.msi") $msiInstalls.Add("Shibboleth", "http://shibboleth.net/downloads/service-provider/2.6.0/win64/shibboleth-sp-2.6.0.1-win64.msi") $iisSites = @{} $iisSites.Add("UACBT", "D:\inetpub\UACBT") $cwLogJsonPath = 'C:\Program Files\Amazon\SSM\Plugins\awsCloudWatch' $cwLogJsonFile = 'AWS.EC2.Windows.CloudWatch.json' try {

Install Windows features

Install-WindowsFeature -Name $windowsFeatures -LogPath (Join-Path -Path $rootBootstrap -ChildPath "windows_features-log.txt")

Download and install MSIs

foreach ($msi in $msiInstalls.Keys) {

Testing revealed just how subject to change vendor URLs are so we'll maintain the MSIs ourselves in our S3 bucket (New-Object System.Net.WebClient).DownloadFile($msiInstalls.Item($msi), (Join-Path -Path $rootBootstrap -ChildPath "$($msi).msi"))

Read-S3Object -BucketName $s3bucket -Folder $rootBootstrap -KeyPrefix $s3keySoftware if ($msi -eq "Shibboleth") { & msiexec /i (Join-Path -Path $rootBootstrap -ChildPath "$($msi).msi") /qn /log (Join-Path -Path $rootBootstrap -ChildPath "install_$($msi)-log.txt") REBOOT=ReallySupress INSTALL_ISAPI_FILTER=FALSE INSTALL_32BIT=TRUE INSTALLDIR=D:\opt\shibboleth-sp\ | Out-Null } else { & msiexec /i (Join-Path -Path $rootBootstrap -ChildPath "$($msi).msi") /qn /log (Join-Path -Path $rootBootstrap -ChildPath "install_$($msi)-log.txt") | Out-Null } }

Make folders for web content

mkdir D:\IISLogs mkdir $rootApps foreach ($site in $iisSites.Keys) { mkdir $iisSites.Item($site) } mkdir D:\inetpub\UACBT\login

Create the web site, app pool & enable 32-bit apps on the app pool NOTE: forcing sort to get a consistent IIS site Id for use with Shibboleth SP

foreach ($site in $iisSites.GetEnumerator() | Sort-Object Name) { New-WebAppPool -Name $site.Key Set-ItemProperty IIS:\AppPools\$($site.Key) -Name enable32BitAppOnWin64 -Value true New-Website -Name $site.Key -ApplicationPool $site.Key -Port 80 -HostHeader $hostHeader -PhysicalPath $site.Value }

Create a separate web application at /login for UACBT authentication code

New-WebApplication -Name "login" -Site "UACBT" -PhysicalPath "D:\inetpub\uacbt\login" -ApplicationPool "UACBT"

Set default IIS logging folder

Set-WebConfigurationProperty "/system.applicationHost/sites/siteDefaults" -Name logfile.directory -Value $iisLogFolder

Download zipped apps from S3

Read-S3Object -BucketName $s3bucket -Folder $rootApps -KeyPrefix $s3keyApps

Unzip zipped app & delete zip when done

Add-Type -As System.IO.Compression.FileSystem $ZipFile = Get-Item (Join-Path -Path $rootApps -ChildPath "UACBT.zip") $Archive = [System.IO.Compression.ZipFile]::Open( $ZipFile, "Read" ) [System.IO.Compression.ZipFileExtensions]::ExtractToDirectory( $Archive, "D:\inetpub\UACBT\login" ) $Archive.Dispose() Remove-Item -Path (Join-Path -Path $rootApps -ChildPath "*.zip")

Download Shibboleth configuration from S3

Read-S3Object -BucketName $s3bucket -Folder $rootShib -KeyPrefix $s3keyShib

Override lock & set config for an ISAPI filter on UACBT site for Shibboleth

Set-WebConfiguration -Filter "//isapiFilters" -PSPath "IIS:\" -Metadata overrideMode -Value Allow Add-WebConfiguration -Filter "//isapiFilters" -PSPath "IIS:\sites\UACBT" -Value @{ name = 'Shibboleth'; path = 'D:\opt\shibboleth-sp\lib\shibboleth\isapi_shib.dll' }

Override lock & set config for an ISAPI & CGI Restrictions for Shibboleth

Set-WebConfiguration -Filter "//isapiCgiRestriction" -PSPath "IIS:\" -Metadata "overrideMode" -Value "Allow" Add-WebConfiguration -Filter "//isapiCgiRestriction" -PSPath "IIS:\" -Value @{ description = 'Shibboleth'; path = 'D:\opt\shibboleth-sp\lib\shibboleth\isapi_shib.dll'; allowed = 'True' }

Add a Handler Mapping for Shibboleth

New-WebHandler -PSPath "IIS:\sites\UACBT\login" -Name "Shibboleth" -Path "*.sso" -ScriptProcessor "D:\opt\shibboleth-sp\lib\shibboleth\isapi_shib.dll" -Verb "*" -Modules "IsapiModule" -ResourceType "Unspecified"

Add a default document to the "login" application

Add-WebConfiguration -Filter "//defaultDocument/files" -PSPath "IIS:\sites\UACBT\login" -atIndex 0 -Value @{value="AccessUACBT.aspx"}

Create UrlRewrite rules to redirect HTTP>HTTPS

Add-WebConfigurationProperty -PSPath "IIS:\sites\UACBT\login" -Filter "system.webServer/rewrite/rules" -Name "." -Value @{name='HTTPS redirect';stopProcessing='True'} Set-WebConfigurationProperty -PSPath "IIS:\sites\UACBT\login" -Filter "system.webServer/rewrite/rules/rule[@name='HTTPS redirect']/match" -Name "url" -Value "^(.*)$" Add-WebConfigurationProperty -PSPath "IIS:\sites\UACBT\login" -Filter "system.webServer/rewrite/rules/rule[@name='HTTPS redirect']/conditions" -Name "." -Value @{input='{HTTP_X_FORWARDED_PROTO}';pattern='^http$'} Set-WebConfigurationProperty -PSPath "IIS:\sites\UACBT\login" -Filter "system.webServer/rewrite/rules/rule[@name='HTTPS redirect']/action" -Name "type" -Value "Redirect" Set-WebConfigurationProperty -PSPath "IIS:\sites\UACBT\login" -Filter "system.webServer/rewrite/rules/rule[@name='HTTPS redirect']/action" -Name "url" -Value "https://{SERVER_NAME}{URL}" Set-WebConfigurationProperty -PSPath "IIS:\sites\UACBT\login" -Filter "system.webServer/rewrite/rules/rule[@name='HTTPS redirect']/action" -Name "redirectType" -Value "Found"

Redirect all traffic to the UACBT service page on the IT website

Set-WebConfiguration -Filter "system.webServer/httpRedirect" -PSPath "IIS:\sites\UACBT" -Value @{enabled="true";destination="$($redirectURL)";exactDestination="true";httpResponseStatus="Found"}

Disable redirect for the "login" application

Set-WebConfiguration -Filter "system.webServer/httpRedirect" -PSPath "IIS:\sites\UACBT\login" -Value @{enabled="false"}

Create a default document on the Default Web Site for the ELB health check (lest you end up with 403.14 errors)

Set-Content C:\inetpub\wwwroot\default.htm -Value "<html><body>up</body></html>"

Restart Shibboleth service (so that config changes take effect)

Restart-Service "shibd_default"

Perform an IISReset (else the Shibboleth ISAPI filter won't load)

& iisreset

Download PowerShell scripts and schedule a task to cleanup the IIS logs

mkdir D:\Scripts Read-S3Object -BucketName $s3bucket -Folder "D:\Scripts" -KeyPrefix $s3keyScripts $taskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy bypass -NonInteractive -NoLogo -NoProfile D:\Scripts\Remove-IISLogsOlderThan3Days.ps1" $taskUser = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount # -RunLevel Highest $taskTrigger = New-ScheduledTaskTrigger -Daily -At 7:05am $task = New-ScheduledTask -Action $taskAction -Principal $taskUser -Trigger $taskTrigger Register-ScheduledTask "Remove-IISLogsOlderThan3Days" -InputObject $task -Force

Download CloudWatch Logs JSON configuration file, modify to update target Log Group, restart SSM Agent to take effect

Read-S3Object -BucketName $s3bucket -Folder $cwLogJsonPath -KeyPrefix $s3keySSM $cwLogJson = Get-Content (Join-Path -Path $cwLogJsonPath -ChildPath $cwLogJsonFile) -Raw | ConvertFrom-Json $cwLogJson.EngineConfiguration.Components | ForEach-Object { If ($_.Id -Eq "CloudWatchLogs") { $_.Parameters.LogGroup = "uacbt-$($environmentName)" }} $cwLogJson | ConvertTo-Json -Depth 10 | Set-Content (Join-Path -Path $cwLogJsonPath -ChildPath $cwLogJsonFile) Restart-Service AmazonSSMAgent

Get the instanceId & availiability zone

$awsInstanceId = Invoke-RestMethod -Uri "http://169.254.169.254/latest/meta-data/instance-id" $awsAZ = Invoke-RestMethod -Uri "http://169.254.169.254/latest/meta-data/placement/availability-zone"

Assign a "Name" tag to the instance to be friendly to the console UI

$awsTags = @() $awsNameTag = New-Object Amazon.EC2.Model.Tag $awsNameTag.Key = "Name" $awsNameTag.Value = "uacbt-$($environmentName)-web_$($awsAZ)_$($awsInstanceId)" $awsTags += $awsNameTag New-EC2Tag -ResourceId $awsInstanceId -Tags $awsTags } catch { Set-Content C:\bootstrap\bootstrap-error-exception.txt -Value $Error[0].Exception $Error[0] | Export-Clixml -Path C:\bootstrap\bootstrap-error-complete.xml throw } ) *> C:\bootstrap\bootstrap-output.txt </powershell>

Auto Scaling Group

WebServerAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: Cooldown: 900 HealthCheckGracePeriod: 0 HealthCheckType: EC2 LaunchConfigurationName: !Ref LaunchConfig MinSize: 1 MaxSize: 1 TargetGroupARNs: - !Ref ElbTargetGroup MetricsCollection: - Granularity: 1Minute VPCZoneIdentifier: - !Ref PrivateSubnetA - !Ref PrivateSubnetB NotificationConfigurations: - TopicARN: !Ref SNSTopic NotificationTypes: - autoscaling:EC2_INSTANCE_LAUNCH - autoscaling:EC2_INSTANCE_LAUNCH_ERROR - autoscaling:EC2_INSTANCE_TERMINATE - autoscaling:EC2_INSTANCE_TERMINATE_ERROR Tags: - Key: Name Value: !Sub uacbt-${TagEnvironment}-asg PropagateAtLaunch: false - Key: environment Value: !Ref TagEnvironment PropagateAtLaunch: true - Key: contactnetid Value: !Ref TagContactNetID PropagateAtLaunch: true - Key: ticketnumber Value: !Ref TagTicketNumber PropagateAtLaunch: true - Key: accountnumber Value: !Ref TagAccountNumber PropagateAtLaunch: true - Key: service Value: !Ref TagService PropagateAtLaunch: true - Key: subaccount Value: !Ref TagSubAccount PropagateAtLaunch: true

Elastic Load Balancers (ELB) v2

 - Includes ELB, target group & listeners

ELB itself

WebServerLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Sub uacbt-${TagEnvironment}-elb Scheme: internet-facing LoadBalancerAttributes: - Key: idle_timeout.timeout_seconds Value: 180 Subnets: - Ref: PublicSubnetA - Ref: PublicSubnetB SecurityGroups: - Ref: SecurityGroupForELB Tags: - Key: Name Value: !Sub uacbt-${TagEnvironment}-elb - Key: environment Value: !Ref TagEnvironment - Key: contactnetid Value: !Ref TagContactNetID - Key: ticketnumber Value: !Ref TagTicketNumber - Key: accountnumber Value: !Ref TagAccountNumber - Key: service Value: !Ref TagService

ELB Target Group

ElbTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 UnhealthyThresholdCount: 2 HealthCheckPath: / Name: !Sub uacbt-${TagEnvironment}-tg Port: 80 Protocol: HTTP VpcId: !Ref VPCID TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: 60 - Key: stickiness.enabled Value: true - Key: stickiness.type Value: lb_cookie - Key: stickiness.lb_cookie.duration_seconds Value: 3600 Tags: - Key: Name Value: !Sub uacbt-${TagEnvironment}-tg - Key: environment Value: !Ref TagEnvironment - Key: contactnetid Value: !Ref TagContactNetID - Key: ticketnumber Value: !Ref TagTicketNumber - Key: accountnumber Value: !Ref TagAccountNumber - Key: service Value: !Ref TagService

ELB Listeners

ElbListenerHTTP: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref ElbTargetGroup LoadBalancerArn: !Ref WebServerLoadBalancer Port: 80 Protocol: HTTP ElbListenerHTTPS: Type: AWS::ElasticLoadBalancingV2::Listener Properties: Certificates: - CertificateArn: !Ref SSLCertARN DefaultActions: - Type: forward TargetGroupArn: !Ref ElbTargetGroup LoadBalancerArn: !Ref WebServerLoadBalancer Port: 443 Protocol: HTTPS

SNS

SNS Topic

SNSTopic: Type: AWS::SNS::Topic Properties: TopicName: !Sub uacbt-${TagEnvironment} DisplayName: !Sub UACBT (${TagEnvironment}) Subscription: - Endpoint: !Ref EmailForSNSSubscription Protocol: email

CloudWatch Logs

 - Includes Log Group & SSM Document

CloudWatch Log Group

LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub uacbt-${TagEnvironment} RetentionInDays: 90 # 90 day retention requested by stevenbhicks, 08/23/2017

IAM

IAM Roles

IAMRoleWebServer: Type: AWS::IAM::Role Properties: RoleName: !Sub uacbt-${TagEnvironment}-role-webserver AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: /

IAM Instance Profiles

IAMProfileWebServer: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref IAMRoleWebServer

IAM Policies

IAMPolicyS3Bucket: Type: AWS::IAM::Policy Properties: PolicyName: !Sub uacbt-${TagEnvironment}-policy-s3bucket-read PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - s3:ListBucket - s3:GetBucketLocation Resource: - !Sub arn:aws:s3:::${S3BucketName} - Effect: Allow Action: - s3:GetObject Resource: - !Sub arn:aws:s3:::${S3BucketName}/* Roles: - !Ref IAMRoleWebServer IAMPolicyTagEC2: Type: AWS::IAM::Policy Properties: PolicyName: !Sub uacbt-${TagEnvironment}-policy-ec2-tagging PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - ec2:CreateTags Resource: - "*" Roles: - !Ref IAMRoleWebServer IAMPolicyDecryptKMS: Type: AWS::IAM::Policy Properties: PolicyName: !Sub uacbt-${TagEnvironment}-policy-kms PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - kms:Decrypt Resource: - !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:key/alias/aws/ssm Roles: - !Ref IAMRoleWebServer IAMPolicySSM: Type: AWS::IAM::Policy Properties: PolicyName: !Sub uacbt-${TagEnvironment}-policy-ssm PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - ssm:ListAssociations - ssm:ListInstanceAssociations - ssm:UpdateInstanceInformation Resource: "*" - Effect: Allow Action: - ec2:DescribeInstanceStatus - ec2messages:GetMessages - ec2messages:AcknowledgeMessage Resource: "*" Roles: - !Ref IAMRoleWebServer IAMPolicyCloudWatchLogs: Type: AWS::IAM::Policy Properties: PolicyName: !Sub uacbt-${TagEnvironment}-policy-cloudwatch-logs PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:DescribeLogGroups - logs:DescribeLogStreams - logs:PutLogEvents Resource: - arn:aws:logs:*:*:* Roles: - !Ref IAMRoleWebServer

Route53

Route53 Record Set Group

Route53RecordSetGroup: Type: AWS::Route53::RecordSetGroup Properties: HostedZoneName: !Sub ${HostedDNSZoneName}. Comment: !Sub uacbt (${TagEnvironment}) - aliases to elastic IP of web server RecordSets: - Name: !Sub uacbt-${TagEnvironment}.${HostedDNSZoneName}. Type: A AliasTarget: HostedZoneId: !GetAtt WebServerLoadBalancer.CanonicalHostedZoneID DNSName: !GetAtt WebServerLoadBalancer.DNSName

Outputs

Output values that can be viewed from the AWS CloudFormation console.

Outputs: WebServerFQDN: Description: FQDN of the web server Value: !Sub uacbt-${TagEnvironment}.${HostedDNSZoneName}. Environment: Description: Environment of the stack (dev, tst, prd, etc) Value: !Sub ${TagEnvironment}