AnsibleでAWS操作シリーズ
- aws-cliインストール編
- EC2インスタンス編
- S3バケット編
- CloudFrontディストリビューション編
- Simple Email Service編
- Certificate Manager編
- Lambda編
関連記事
やりたかったこと
-
ACM
にて独自ドメインへのSSL
証明書を発行 -
SSL
証明書をCloudFront
に設定 GUIを使わずに黒い画面でコマンドを「ッターーン!」してかっこつけたい
やったこと
前提
- CIサーバー(
ansible
実行サーバー)構築済み - CLIサーバー(
aws-cli
実行サーバー)構築済み -
Ansible
インストール済み -
aws-cli
インストール済み - 各サーバーへのSSH接続設定済み
- 独自ドメイン取得済み
- SESの設定済み
- CFとS3の設定済み
※ ${~}
は各環境に合わせて値を設定してください。
作業フロー
1. SSL証明書発行リクエストの作成
command
ansible-playbook -i inventory/production create-aws-acm-request.yml
戻り値の値を控えます。
2. SESに保存された認証確認メールから認証用URLを取得し、ブラウザからapproveする
command
ansible-playbook -i inventory/production view-aws-acm-notice-mail-url.yml
戻り値のURLにブラウザからアクセスする必要あり
3. CloudFrontの設定を更新して、httpsでアクセス出来るようにする
command
ansible-playbook -i inventory/production update-aws-cf.yml
## ディレクトリ構成
```text
├── ansible.cfg
├── create-aws-acm-request.yml
├── templates
│ └── production
│ └── cf
│ └── update.j2
├── inventory
│ └── production
│ └── inventory
├── roles
│ ├── create-aws-acm-request
│ │ └── tasks
│ │ └── main.yml
│ ├── update-aws-cf
│ │ └── tasks
│ │ └── main.yml
│ └── view-aws-acm-notice-mail-url
│ └── tasks
│ └── main.yml
├── update-aws-cf.yml
├── view-aws-acm-notice-mail-url.yml
└── vars
└── all.yml
Ansible構成ファイル
inventory
inventory/production/inventory
[ciservers]
${CIサーバーホスト}
[cliservers]
${CLIサーバーホスト}
[all:vars]
ENV=production
vars
vars/all.yml
AWS:
ACM:
ARN: ${ACMリクエストのARN}
REGION: us-west-2
VERIFICATION_MAIL_OBJECT: ${認証メールオブジェクト名}
CF:
DISTRIBUTION:
ID: ${ディストリビューションID}
ORIGIN_ID: ${オリジンID}
E_TAG: ${Eタグ}
S3:
BUCKET:
NAME: ${バケット名}
END_POINT: ${S3バケットの静的ホスティングエンドポイント}
DOMAIN:
MAIN:
NAME: ${ドメイン名}
SUB:
NAME: ${サブドメイン名}
templates
production/cf/update.j2
{
"DistributionConfig": {
"Comment": "Https Bucket.",
"CacheBehaviors": {
"Quantity": 0
},
"IsIPV6Enabled": true,
"Logging": {
"Bucket": "",
"Prefix": "",
"Enabled": false,
"IncludeCookies": false
},
"WebACLId": "",
"Origins": {
"Items": [
{
"OriginPath": "",
"CustomOriginConfig": {
"OriginSslProtocols": {
"Items": [
"TLSv1",
"TLSv1.1",
"TLSv1.2"
],
"Quantity": 3
},
"OriginProtocolPolicy": "http-only",
"OriginReadTimeout": 30,
"HTTPPort": 80,
"HTTPSPort": 443,
"OriginKeepaliveTimeout": 5
},
"CustomHeaders": {
"Quantity": 0
},
"Id": "{{ AWS.CF.ID }}",
"DomainName": "{{ AWS.S3.END_POINT }}"
}
],
"Quantity": 1
},
"DefaultRootObject": "index.html",
"PriceClass": "PriceClass_All",
"Enabled": true,
"DefaultCacheBehavior": {
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"LambdaFunctionAssociations": {
"Quantity": 0
},
"TargetOriginId": "{{ AWS.CF.ID }}",
"ViewerProtocolPolicy": "redirect-to-https",
"ForwardedValues": {
"Headers": {
"Quantity": 0
},
"Cookies": {
"Forward": "all"
},
"QueryStringCacheKeys": {
"Quantity": 0
},
"QueryString": true
},
"MaxTTL": 604800,
"SmoothStreaming": false,
"DefaultTTL": 604800,
"AllowedMethods": {
"Items": [
"HEAD",
"GET"
],
"CachedMethods": {
"Items": [
"HEAD",
"GET"
],
"Quantity": 2
},
"Quantity": 2
},
"MinTTL": 604800,
"Compress": false
},
"CallerReference": "2017-07-29_06-25-01",
"ViewerCertificate": {
"SSLSupportMethod": "sni-only",
"ACMCertificateArn": "{{ AWS.ACM.ARN }}",
"MinimumProtocolVersion": "TLSv1",
"Certificate": "{{ AWS.ACM.ARN }}",
"CertificateSource": "acm"
},
"CustomErrorResponses": {
"Quantity": 0
},
"HttpVersion": "http2",
"Restrictions": {
"GeoRestriction": {
"RestrictionType": "none",
"Quantity": 0
}
},
"Aliases": {
"Items": [
"{{ DOMAIN.MAIN.NAME }}"
],
"Quantity": 1
}
},
"Id": "{{ AWS.CF.DISTRIBUTION.ID }}",
"IfMatch": "{{ AWS.CF.DISTRIBUTION.E_TAG }}"
}
playbook
create-aws-acm-request.yml
- hosts: cliservers
roles:
- create-aws-acm-request
vars_files:
- vars/all.yml
update-aws-cf.yml
- hosts: cliservers
roles:
- update-aws-cf
vars_files:
- vars/all.yml
view-aws-acm-notice-mail-url.yml
- hosts: cliservers
roles:
- view-aws-acm-notice-mail-url
vars_files:
- vars/all.yml
tasks
role/create-aws-acm-request/tasks/main.yml
- name: "Create Certificate"
shell: |
aws acm request-certificate \
--domain-name {{ DOMAIN.MAIN.NAME }} \
--subject-alternative-names {{ DOMAIN.SUB.NAME }} \
--domain-validation-options DomainName={{ DOMAIN.SUB.NAME }},ValidationDomain={{ DOMAIN.MAIN.NAME }} \
--region={{ AWS.ACM.REGION }}
register: result
changed_when: False
- debug: var=result.stdout_lines
when: result | success
tags:
- always
role/view-aws-acm-notice-mail-url/tasks/main.yml
- name: Download Verification Mail Object
shell: |
aws s3 cp \
s3://${AWS.S3.BUCKET.NAME}/{{ AWS.ACM.VERIFICATION_MAIL_OBJECT }} \
{{ TEMP.DIRECTORY }}.{{ AWS.ACM.VERIFICATION_MAIL_OBJECT }}
register: result
changed_when: False
- debug: var=result.stdout_lines
when: result | success
tags:
- always
- name: View URL
shell: |
grep https {{ TEMP.DIRECTORY }}.{{ AWS.ACM.VERIFICATION_MAIL_OBJECT }} | grep context
register: result
changed_when: False
- debug: var=result.stdout_lines
when: result | success
tags:
- always
role/update-aws-cf/tasks/main.yml
- name: Create Json
template:
src={{ ENV }}/cf/update.j2
dest={{ TEMP.DIRECTORY }}/update.json
tags:
- always
- name: Update Distribution
shell: |
aws cloudfront update-distribution \
--cli-input-json {{ TEMP.DIRECTORY }}/update.json
register: result
changed_when: False
- debug: var=result.stdout_lines
when: result | success
tags:
- always
終わりに
これで今までhttp
でアクセスしてたS3
バケット(CloudFront
経由)にアクセスすると、https
にリダイレクトされた上で正常に表示されると思います。
AWS
+CloudFrount
+ACM
+S3
を使えばほぼ無料でSSL
証明証の発行や紐付けが出来、自動更新の設定や複数ドメインのSSL
証明書をまとめて管理することが出来ます。
自分は以下のようなWordpressプラグインとAWSサービスで静的サイトを運用していますが、今のところ問題なく運用出来ています。
Wordpress
+staticpress
+staticpresss3
+S3
+CloudFront
+ACM
Wordpress
を静的サイト化することで一部機能が制限されてしまいますが、セキュリティ観点がかなり向上します。
また、制限される部分も特に不要な機能だと思いますし、JavaScript
等である程度保管することも可能なので動的サイトを切り捨てて静的サイトにするメリットは十分あると思いますので、興味のある方は是非お試し下さい♪
じゃあの。