AWS

無料でSSL/TLC証明書を手に入れる EC2/ElasticBeanstalk編

投稿日:

Certbotを使って Conoha+Kusanagi(nginx/centos7) に無料でSSL/TLC証明書をインストール・自動更新する方法は過去に書いた。"無料でSSL/TLC証明書を手に入れる"

CertbotサイトにOSとWebサーバの組み合わせを入力すると対応するインストール手順が表示される。メジャーな組み合わせであれば証明書の取得から自動更新まで全自動でやってくれる。

2016年7月現在、AWS(EC2)は未対応のため、Certbotツールを使って試行錯誤する必要がある。Certbotの一次情報をもとに何とかやってみたので記録を残しておく。

  • AWS(EC2)にCertbotでSSL/TLC証明書をインストールする
  • ElasticBeanstalkのロードバランサに取得した証明書を登録しhttpsでアクセスできるようにする
  • 自動更新のセットアップを行う

AWS(EC2)にCertbotを使ってSSL/TLC証明書をインストールする

いくつか前提がある。

  • ドメインは取得済みであること。
  • ドメインがElasticBeanstalkのIPアドレスを指すようにRoute53を設定済みであること。
  • EC2インスタンスにSSHでログインできるようにしておく。
  • Certbot利用時、外部からEC2インスタンスにhttpでアクセスを受ける。ElasticBeanstalkにRoutingを変更するようなアプリがデプロイされているとアクセスが失敗するのでDocumentRootにindex.phpがあるだけという状態にしておく。
  • SSL/TLC証明書をインストールするだけなら443番を開けておく必要はない。ロードバランサはデフォルトの80番だけ開けていれば良い
  • EC2インスタンスのrootパスワードが設定済みであること
  • AWS CLIがインストール済みであること。
  • IAMで証明書登録ポリシーを付与済みであること。

さっそくEC2インスタンスにログイン。基本的にec2-userで作業する。
一応下記を実行。

$ sudo yum install epel-release
Loaded plugins: priorities, update-motd, upgrade-helper
Package epel-release-6-8.9.amzn1.noarch already installed and latest version
Nothing to do

Certbotをダウンロードする。

$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto

Certbotを実行してみる。その際、--debugオプションを付けないと怒られる。would like to work on improving it と言っておきながら --debug がmust。きっと実行内容がCertbotに送られるのだろう。

$ ./certbot-auto
WARNING: Amazon Linux support is very experimental at present...
if you would like to work on improving it, please ensure you have backups
and then run this script again with the --debug flag!

指示通り、--debugオプションを付けて実行してみる。

$ ./certbot-auto --debug
...
Installed:
  augeas-libs.x86_64 0:1.0.0-5.7.amzn1
  dialog.x86_64 0:1.1-9.20080819.1.5.amzn1
  libffi-devel.x86_64 0:3.0.13-11.4.amzn1
  python27-tools.x86_64 0:2.7.10-4.120.amzn1
  system-rpm-config.noarch 0:9.0.3-42.27.amzn1

Complete!
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Requesting root privileges to run certbot...
  /home/ec2-user/.local/share/letsencrypt/bin/letsencrypt --debug
Version: 1.1-20080819
Version: 1.1-20080819
No installers are available on your OS yet; try running "letsencrypt-auto certonly" to get a cert you can install manually

いろいろインストールされる。/home/ec2-user/.local/share/letsencrypt/ 以下にPython27 が入る。今回の試行錯誤では自力でPythonを上げなかった。たぶん、自力でPythonのバージョンを上げなくてもコレが使われるんじゃないか。

肝心のインストーラはインストールされず、"letsencrypt-auto certonly"というコマンドを実行せよ、と出る。が、これはtypo。

No installers are available on your OS yet; try running "letsencrypt-auto certonly" to get a cert you can install manually

ディレクトリを移動する。

$ cd /home/ec2-user/.local/share/letsencrypt/bin

ここにある certbot コマンドを叩く。ドメイン名、メールアドレスを指定する。

sudo ./certbot certonly -d hoge.com --agree-tos -m hoge@hoge.com --debug

すると、中途半端にグラフィカルな画面が表示される。簡易Webサーバを起動するか、現在のWebサーバのDocumentRootを教えるか、2択となる。簡易Webサーバだとどうしても上手くいかなかった。Webサーバを上げたまま(ElasticBeanstalkのヘルスチェックがOKの状態)、DocumentRootを指定すると上手くいった。

うまくいくと、以下のようなメッセージが表示される。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/arst.me/fullchain.pem. Your cert will expire
   on 2016-09-29. To obtain a new or tweaked version of this
   certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

/etc/letsencrypt/live に証明書が作られている。なお、live には ec2-user でアクセスできない。ここでrootに昇格。

$ su - 
# cd /etc/letsencrypt/live
# ls
hoge.com
# cd hoge.com
# ls
cert.pem  chain.pem  fullchain.pem  privkey.pem

ElasticBeanstalkのロードバランサに証明書を登録する

AWS CLI経由で証明書を登録する。その際、IAMにてポリシーを追加しておく必要がある。過去エントリを参照のこと。成功するとJSONで登録情報が返る。ここでは、HogeCertification という名前で登録を行っている。

$ aws iam upload-server-certificate --server-certificate-name HogeCertification
   --certificate-body file://cert.pem --private-key file://privkey.pem
{
    "ServerCertificateMetadata": {
        "ServerCertificateId": "ASCAI***********A6F5GI",
        "ServerCertificateName": "HogeCertification",
        "Expiration": "2016-09-29T01:57:00Z",
        "Path": "/",
        "Arn": "arn:aws:iam::281631559249:server-certificate/HogeCertification",
        "UploadDate": "2016-07-01T03:10:18.440Z"
    }
}

ElasticBeanstalkのロードバランサの設定で、証明書欄から HogeCertification を選べるようになる。選んで 443/HTTPS を通すようにすれば、晴れて https://独自ドメイン/ で ElasticBeanstalk の URL が開く。

証明書の自動更新

更新自体はcertbot renewコマンドで行う。certbot renewコマンドは/var/www/html/.well-known/以下にファイルを置いて外部から開きにくる。困ったことに、CakePHPやLaravelアプリをデプロイしているとフレームワークのルーティング機能により上手くいかない。
以下の戦略で対応する。

  1. certbot renew 時だけ、DocumentRoot を アプリ用からcertbot用に切り替える
  2. Laravel等のように DocumentRoot がサブディレクトリにオフセットされている場合に対応する

ElasticBeanstalkで自動生成される環境を見ると、/var/www/html が /var/app/current へのシンボリックリンクとなっている。Certbot renew を叩くときだけ、シンボリックリンクを差し替える。

$ cd /var/app
$ sudo mkdir -p certbot/project/public
$ sudo chown -R webapp:webapp certbot
$ cd /var/www
$ sudo ln -s -f /var/app/certbot html

また、certbot用の.well-knownディレクトリが /var/www/html 直下に作られる仕様になっている。DocumentRootはさらに project/public にオフセットされているため、/var/www/html/project/public/.well-known が /var/www/html/.well-known を指すようにシンボリックリンクを作成する。

$ cd /var/app/certbot/project/public
$ sudo ln -s ../../.well-known

この状態で certbot renew --dry-run を叩くと無事成功する。

$ pwd
/home/ec2-user/.local/share/letsencrypt/bin
$ sudo certbot renew --dry-run
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/ikuty.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)

シンボリックリンクの作成は一度だけで良いが、アプリ用とCertbot用のシンボリックリンク張替は都度必要となる。

以下のシェルスクリプトをcronで叩けば良い。

#!/bin/bash

cd /var/www
sudo unlink html
sudo ln -s -f /var/app/certbot html
cd ~
pwd
sudo ./.local/share/letsencrypt/bin/certbot renew --debug
cd /var/www
sudo unlink /var/www/html
sudo ln -s -f /var/app/current html

不要な更新は実行されないため、1日2回の頻度で実行してよい旨、ドキュメントに記述がある。

Note: if you’re setting up a cron or systemd job, we recommend running it twice per day (it won’t do anything until your certificates are due for renewal or revoked, but running it regularly would give your site a chance of staying online in case a Let’s Encrypt-initiated revocation happened for some reason). Please select a random minute within the hour for your renewal tasks.

-AWS

Copyright© ikuty.com , 2018 AllRights Reserved Powered by AFFINGER4.