この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どーもsutoです。AWSのサービスを駆使してWebサーバ(EC2)のSSL設定を自動化するテンプレートを作成しました。
要件
前提
- 対象のEC2は既に作成済
- Route53でドメイン取得、ホストゾーン作成が完了済
テンプレートで自動化する項目
- ALB、ターゲットグループ、リスナーを新規作成
- Route53の既存ホストゾーン下にサブドメインを新規作成、エイリアスにALBをアタッチ
- ALBに紐づけるSGの新規作成
- AWS Certificate Manager(ACM)で証明書を発行、対象のサブドメインに設定
試してみた
以下のテンプレートにテストパラメータを入力して実行結果を見てみます。
AWSTemplateFormatVersion: '2010-09-09'
Description: Create new ALB, ACM, SG, https
Parameters:
ServerName:
Description: Server Name
Type: String
Default: 'test'
VPCID:
Description: VPC ID
Type: String
Default: 'vpc-xxx'
PrimarySubnet:
Description: PrimarySubnet ID
Type: String
Default: 'subnet-xxx'
SecondarySubnet:
Description: SecondarySubnet ID
Type: String
Default: 'subnet-xxxx'
AllowIP:
Description: IP Address for SG
Type: String
Default: ''
AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
ConstraintDescription: "Must be a valid IP range of the form x.x.x.x/x"
EC2Web1:
Description: EC2 Instance ID
Type: String
Default: 'i-xxx'
HostZoneId:
Description: FQDN of the hosted zone
Type: String
Default: 'Z0xxx'
DomainName:
Description: FQDN of the HostZone
Type: String
Default: 'example.com'
SubDomain:
Description: FQDN of the certificate
Type: String
Default: 'test.example.com'
Resources:
SGloadbalancer:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupName: !Sub ${ServerName}-alb-sg
GroupDescription: !Sub ${ServerName}-alb-sg
VpcId: !Ref VPCID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '443'
ToPort: '443'
CidrIp: !Ref AllowIP
Tags:
- Key: Name
Value: !Sub ${ServerName}-alb-sg
TargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
VpcId: !Ref VPCID
Name: !Sub ${ServerName}-tg
Protocol: HTTP
Port: 80
HealthCheckProtocol: HTTP
HealthCheckPath: "/"
HealthCheckPort: "traffic-port"
HealthyThresholdCount: 5
UnhealthyThresholdCount: 2
HealthCheckTimeoutSeconds: 5
HealthCheckIntervalSeconds: 30
Matcher:
HttpCode: 200
Targets:
- Id: !Ref EC2Web1
Port: 80
InternetALB:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Name: !Sub ${ServerName}-alb
Scheme: "internet-facing"
LoadBalancerAttributes:
- Key: "deletion_protection.enabled"
Value: false
- Key: "idle_timeout.timeout_seconds"
Value: 4000
SecurityGroups:
- !Ref SGloadbalancer
Subnets:
- !Ref PrimarySubnet
- !Ref SecondarySubnet
ALBListenerHTTP:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
Port: 80
Protocol: HTTP
DefaultActions:
- Type: redirect
RedirectConfig:
Host: '#{host}'
Path: '/#{path}'
Port: 443
Protocol: HTTPS
Query: '#{query}'
StatusCode: HTTP_301
LoadBalancerArn: !Ref InternetALB
ALBListenerHTTPS:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
Port: 443
Protocol: HTTPS
Certificates:
- CertificateArn: !Ref ACM
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
LoadBalancerArn: !Ref InternetALB
DnsRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Sub '${HostZoneId}'
Comment: "DNS for ALB"
Name: !Sub '${SubDomain}'
Type: A
AliasTarget:
HostedZoneId: !GetAtt 'InternetALB.CanonicalHostedZoneID'
DNSName: !GetAtt 'InternetALB.DNSName'
ACM:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Sub '${SubDomain}'
DomainValidationOptions:
- DomainName: !Sub '${SubDomain}'
HostedZoneId: !Sub '${HostZoneId}'
ValidationMethod: DNS
約15分程度でスタック処理が完了。無事リソースが出来ていました。
2020年6月17日のアップデートによりACMのDNS検証が自動化されたため、間に手作業をまったく入れずスタックの完了を待つだけで設定できるのはホントに素晴らしい!
時間に余裕があるときにParametersの記述を整理したいなと思います。
作成経緯における個人的な注意点
- 当初”RecordSet”のホストゾーンの指定を”HostedZoneName”にしていたが、値を「example.com.」(←最後にドットが必要)にしなければならず紛らわしかったので”HostedZoneId”の指定に変えた
- このスタックを削除しても、DNS検証で自動作成されたRoute53のCNAMEは削除されず残ってしまうため、不必要なら手動で削除すること
以上となります。