Let's Encrypt(無料SSL証明書)についてまとめ

## 背景
- SSL証明書はこれまで有料かつ高価だったため、そのせいで証明書を使わずセキュリティの低い状態のサイトが多かった
- これを問題視した[ISRG](https://letsencrypt.org/isrg/)が2015年夏ごろ、無料SSL証明サイトの配信サイト[Let's Encrypt]()を立ち上げ

## 特徴
- 無料で取得 / 運用できる

- 取得したいサーバ上でスクリプトを実行して申請する
    - その際、ドメインを所有していることの確認手続きが必要になる

- 証明書の有効期間は90日と短い
    - バッチ処理で自動更新させることは可能

- 取得できるのはDV証明書のみ。OVやEVは不可
    - TLS 1.0 ~ 1.3に対応
    - RSA, DHE, ECDHEに対応

## 参考
- [J-Stream CDN情報サイト - 無料SSL証明書](https://tech.jstream.jp/blog/ssl/free/)
- [Let'sEncrypt 総合ポータル - Let's Encrypt の使い方](https://letsencrypt.jp/usage/)
- [あぱーブログ - Let's Encrypt サーバー証明書の取得と自動更新設定メモ](https://blog.apar.jp/linux/3619/)


## 導入方法

### DNSの設定
証明書の取得に先立って、対象のドメインが実際に運用するサーバのIPに向いている必要があるので設定する。

- DNSのAレコードに対象ドメインとIPを登録
- サーバが実際にそのドメインでhttp/httpsアクセスできるよう、ファイアウォール等を設定

### Certbotの導入
Certbotというスクリプトを対象のサーバ上で実行することで、証明書を取得する。

```bash
$ git clone https://github.com/certbot/certbot
$ cd certbot
$ ./certbot-auto

# スクリプト中でyumが実行されるので、承認して諸々をインストール
# ↓が表示されるので、NOを選択

> No names were found in your configuration files.
> You should specify ServerNames in your config files in order to allow for accurate installation of your certificate.
> If you do use the default vhost, you may specify the name manually.
> Would you like to continue?
```

### 証明書の取得
Certbotを使って証明書を申請/取得する。
~~certbot-autoの実行中はこのスクリプトが80/443ポートをリスンするので、Webサーバ(今回の場合Apache)をいったん停止する必要があった。~~

```bash:webサーバを停止させる方法
# service httpd stop
# ./certbot-auto certonly --standalone -d <DOMAIN>


## メールアドレスを聞かれるので入力する
## 利用規約への同意を求められるので同意する
## 証明書が欲しいドメイン名を聞かれるので入力する

>  - Congratulations! Your certificate and chain have been saved at
> /etc/letsencrypt/live/<DOMAIN>/fullchain.pem.
> Your cert will expire on 2016-11-30. 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"
```

***
###### 2016/09/07追記
[Webサーバを停止させずに証明書を取得する方法があった。](https://letsencrypt.jp/faq/#WithoutBringingDownHTTPD)

停止させたくない場合は、`--webroot`オプションを使って、取得したい証明書のドメインのドキュメントルートを指定する。

この方法の場合、指定したドキュメントルートに`.well-known`ディレクトリが作成される。
Let's Encryptのサーバがこのフォルダ内のファイルにhttp/sアクセスすることで、ドメインの所有権を認証する様子。


```bash:webサーバを停止させない方法
$ ./certbot-auto certonly --webroot -w /path/to/document/root/ -d <DOMAIN>
```
***


証明書一式は`/etc/letsencrypt/archive/<DOMAIN>/`以下のパスに作成される:

ファイル | 内容
--- | ---
cert1.pem         | 証明書(公開鍵)
chain1.pem        | 中間証明書
fullchain1.pem    | 証明書＋中間証明書
privkey1.pem      | 秘密鍵


### 証明書の設定
Webサーバごと任意に証明書、秘密鍵、中間証明書を設定する。
Apacheの場合はssl.confに以下のように設定した。

```/etc/httpd/conf.d/ssl.conf
SSLCertificateFile /etc/letsencrypt/archive/<DOMAIN>/cert1.pem<
SSLCertificateKeyFile /etc/letsencrypt/archive/<DOMAIN>/privkey1.pem<
SSLCertificateChainFile /etc/letsencrypt/archive/<DOMAIN>/chain1.pem
```

***
###### 2016/09/08追記
証明書と秘密鍵の参照パスが妥当でなかった。

証明書は自動更新されるごとに`/etc/letsencrypt/archive/<DOMAIN>/`以下に、cert1.pem, cert2.pem,...と蓄積されていく。cert1.pemを設定ファイルで参照していると、自動更新しても一番古い証明書が使われづつけることになる。

正しくは、`/etc/letsencrypt/live/<DOMAIN>`内にあるpemファイルを参照する。
live/内のpemファイルはarchive/内の最新の証明書のリンクなので、こうしておくことで証明書の自動更新に対応できる。

```bash
# archive/にリンクされているのが確認できる
$ ls -alF /etc/letsencrypt/live/<DOMAIN>/
> total 8.0K
> drwxr-xr-x 2 root 4.0K Sep  8 05:00 ./
> drwx------ 7 root 4.0K Sep  7 14:04 ../
> lrwxrwxrwx 1 root   40 Sep  8 05:00 cert.pem -> > ../../archive/<DOMAIN>/cert3.pem
> lrwxrwxrwx 1 root   41 Sep  8 05:00 chain.pem -> ../../archive/<DOMAIN>/chain3.pem
> lrwxrwxrwx 1 root   45 Sep  8 05:00 fullchain.pem -> ../../archive/<DOMAIN>/fullchain3.pem
> lrwxrwxrwx 1 root   43 Sep  8 05:00 privkey.pem -> ../../archive/<DOMAIN>/privkey3.pem
```

```/etc/httpd/conf.d/ssl.conf
# live/ を参照するよう変更
SSLCertificateFile /etc/letsencrypt/live/<DOMAIN>/cert1.pem<
SSLCertificateKeyFile /etc/letsencrypt/live/<DOMAIN>/privkey1.pem<
SSLCertificateChainFile /etc/letsencrypt/live/<DOMAIN>/chain1.pem
```


***

httpsアクセスしてブラウザに正当な証明書である旨が表示されればOK。

### 自動更新の設定
このままだと90日で証明書の期限が切れてしまうので、自動的に更新されるよう設定する。`certbot-auto`コマンドを呼ぶと、証明書の期限を確認した上で、自動的に更新してくれる。

```bash
$ ./certbot-auto renew

# --force-renewを付けると、期限に余裕があっても更新する
$ ./certbot-auto renew --force-renew

# --dry-runを付けると動作のみを確認できる
$ ./certbot-auto renew --dry-run
```

証明書が更新された場合、Webサーバは証明書を再読み込みする必要がある。
まとめると、crontabに以下のように書けばいい


```shell:crontab
0 0 1 * * /path/to/certbot/certbot-auto renew && service httpd reload
```


## 直接更新できない場合
参考: [Let's Encrypt 証明書の自動発行とELB自動登録を行ったログ](http://qiita.com/hidekuro/items/482520f220a305dc147b)

Amazon ELB/EC2で Webサーバを冗長構成する場合はロードバランサに証明書を設定するが、ELB自身はスクリプトを実行できない。この場合はいずれかのEC2サーバで証明書を取得/管理し、AWS CLIを使ってELBの証明書を更新する方法をとる。