LoginSignup
0
5

More than 5 years have passed since last update.

AnsibleでAWS操作 Certificate Manager編

Last updated at Posted at 2017-08-23

AnsibleでAWS操作シリーズ

  1. aws-cliインストール編
  2. EC2インスタンス編
  3. S3バケット編
  4. CloudFrontディストリビューション編
  5. Simple Email Service編
  6. Certificate Manager編
  7. Lambda編

関連記事

aws-cli コマンド一覧(随時追記)

やりたかったこと

  • 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等である程度保管することも可能なので動的サイトを切り捨てて静的サイトにするメリットは十分あると思いますので、興味のある方は是非お試し下さい♪

じゃあの。

0
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
5