Let's Encryptを使ってEC2にSSL証明書の発行から自動更新まで行う


## はじめに

AWSでSSLを簡単に実現するにはAWS Certificate Manager(以下ACM)を使えばすぐ出来るけど、Elastic Load Barancer(以下ELB)を挟まなければいけなかった。特にELBのリスナーをいじっていなければELBを挟むと以下のような形でアクセスされる。

`ユーザー → (http or https) → ELB → (http) → EC2`

上記でアクセスされるというのはELBのリスナーが以下のようになっているから。
![スクリーンショット 2017-11-02 19.23.20.png](https://qiita-image-store.s3.amazonaws.com/0/19716/8765fd98-4c23-1ae9-ee3b-27a15e8a8062.png)



ACMはELBでしか使えないので、結局EC2にアクセスする際はhttpでアクセスすることになる。

この時、サーバーサイドの言語を使ってhttpかhttpsを判別している時にhttpsでアクセスしてきてもELBからhttpで呼ばれるためmixed contentになったり不具合があったので、結局EC2にもSSLを適用させることにした。

色々調べてみたら、[Let's Encrypt](https://letsencrypt.org/)というのが便利そうだった。
なおLet's Encryptを簡単に導入できる[Certbot](https://certbot.eff.org/)というクライアントがあったので、その方法で進めていきます

なおAmazon Linuxではまだ実験段階とのことで、途中以下のようにメッセージが出た。

```
FATAL: 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!
Alternatively, you can install OS dependencies yourself and run this script
again with --no-bootstrap.
```

## 環境

* Amazon Linux
* Apache 2.4.7

前提として、EC2インスタンスの作成は出来ている状態で進めていきます。

以下で行う作業は全てssh後にrootユーザーとなっていることが前提で進めていきます。


## 1. certbotのインストール

```
// rootユーザーになる
$ sudo -i

// curlでインストール
$ curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto

// 700権限を付与
$ chmod 700 /usr/bin/certbot-auto

```

　
## 2. SSL証明書を作成する

```
// 生成するコマンド
$ certbot-auto certonly --webroot -w /var/www/html -d hoge.com --email hoge@hoge.com -n --agree-tos --debug
```


お使いの環境で上記コマンドの変更が必要な部分は以下です。
以下のオプションの後に値を半角スペースで入力する

オプション | 概要 | 値
---------| ----|----
-w | ドキュメントルートの指定 | /var/www/html
-d | 対象ドメイン | hoge.com
--email | 登録用メールアドレス | hoge@hoge.com
-n | 対話の入力をスキップ | 
--agree-tos | 利用規約に同意する | 
--debug | AWSではこれがないとエラーになる |

`-w`で指定している`/var/www/html`はApacheのデフォルトのドキュメントルートです。`httpd -S`とかで確認して設定してください。

最後についてる`--debug`はAmazon Linuxはまだ実験段階であるためこのオプションをつけなければエラーとなってしまうので、つける必要があります。

上記コマンドを入力して成功すると、以下のようなメッセージが出力される

```
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/hoge.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/hoge.com/privkey.pem
   Your cert will expire on 2018-01-31. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
```

いつまで有効化というのも教えてくれるし、親切仕様...

## 3. 設定ファイルに証明書のパスを指定

`mod_ssl`をインストールします。

```
// mod_sslをインストール
$ yum install mod24_ssl

// 作成されたssl.confをviで開く
vi /etc/httpd/conf.d/ssl.conf
```

#### ssl.conf

`/etc/httpd/conf.d/ssl.conf`ファイルの以下の部分を書き換えていきます。

* SSLCertificateFile
* SSLCertificateKeyFile
* SSLCertificateChainFile

自分の環境下では102行目に`SSLCertificateFile`に関する記述がありました。

```
// 102行目にcert.pemファイルまでのパスを記述
102 SSLCertificateFile /etc/letsencrypt/live/hoge.com/cert.pem

// 110行目にprivkey.pemまでのパスを記述
110 SSLCertificateKeyFile /etc/letsencrypt/live/hoge.com/privkey.pem

// 119行目のコメントアウトを外しchain.pemまでのパスを記述
119 SSLCertificateChainFile /etc/letsencrypt/live/hoge.com/chain.pem
```

変更したら`esc`→`:wp`で保存して終了し、`service httpd restart`でApacheを再起動します。

## 4. SSL証明書をcronを使って自動更新する

Let's Encryptで発行した証明書は3ヶ月しか有効期限がないので、自動で更新するようにしておく必要があるかと思います。

`/usr/bin/certbot-auto renew --post-hook "sudo service httpd restart"`のコマンドを実行し、証明書の更新が出来るのか確認する。

証明書を発行した際に、`renew`コマンドで更新が出来ると書いてあったので、`renew`コマンドで更新を行う。`--post-hook`オプションで更新が行われた際に実行するコマンドを指定出来る。

cronに登録する前にcronが使用出来るか確認。
`/etc/rc.d/init.d/crond status`で`crond (pid  2641) is running...`となっていれば大丈夫。


#### cronファイルを作成

`vi /etc/cron.d/letsencrypt`でファイルを作成して、ファイルに以下を記述する。

```
00 01 * * * root /usr/bin/certbot-auto renew --post-hook "service httpd restart"
```

以上で毎日1時にcronが実行されSSL証明書の確認・更新が行われるようになります。

以上で設定は終わりなので、設定したドメインにhttpsをつけてアクセスしてみてください。

## httpsでアクセス出来なかったら

もしhttps://設定したドメイン　で見れない場合は、「EC2」→ 「セキュリティーグループ」でインスタンスに適用しているグループの「インバウンド」の編集から以下を追加してあげればOKです。

![スクリーンショット 2017-11-02 18.54.39.png](https://qiita-image-store.s3.amazonaws.com/0/19716/77ba7a9b-7685-5750-2611-17eaac3c5364.png "スクリーンショット 2017-11-02 18.54.39.png")