知識整理　Let’s Encryptで証明書取得

# 概要
なんだか思いがけず色々と苦労したので、Let’s Encryptで証明書を得るのに必要な手続き/知識を整理しておこうと思います。

## Let’s Encryptの仕組み
以下の３サイトを参考にさせていただき理解いたしました。

【15秒でわかるLet's Encryptのしくみ～無料で複数ドメイン有効な証明書作成～】
　https://qiita.com/S-T/items/7ede1ccfae6fc7f08393
【Let's Encrypt 総合ポータル (非公式解説サイト)】
　https://free-ssl.jp/technology/
【ACMEプロトコルの仕組み】
　https://http2.try-and-test.net/letsencrypt.html

【まとめ】
   [１]秘密鍵とCSRを用意、秘密鍵をローカルに保存
   [２]Let’s EncryptのエージェントがLet'sEncryptのACMEサーバに接続しCSRを送付
  [３]ACMEサーバは、認証情報をエージェントに返す
  [４]エージェントは、認証情報からファイルを生成し、
     ローカルのhtdocs配下の特定ディレクトリにファイルを配置する
  [５]準備が整ったところで、エージェントは、ACMEサーバに認証チャレンジを要求
  [６]ACMEサーバは、指定のドメインに認証用のファイルが設置されているか、Webサーバ(HTTPD)に確認
  [７]ACMEサーバが、期待した通りの認証用ファイルをダウンロードできれば、サーバ証明書を発行
  [８]発行された証明書をエージェントに送付

上記、まとめの通り、Let’s Encryptという無償の証明書発行機関が用意したサーバに対して、エージェントソフトを利用（githubにある）し、自分の用意しているWebサーバとLet’s Encryptが用意している証明書発行用のサーバとが通信することで公的証明書が発行される仕組みということです。
秘密鍵とCSRについてはOpenSSLを利用して自分で用意しても大丈夫です。
なぜかというとLet’s Encryptは証明書の証明/発行がメインのお仕事ですので、証明される元を自分が用意しても構わないということです。
ちなみにLet’s Encryptが発行する証明書の有効期間は3ヶ月です、期間を過ぎた場合、コマンドで更新していく必要があります。

ここでさらに用語を整理すると以下になります。
　・エージェント　
　　certbot,certbot-autoコマンド（Let’s Encryptが用意したサーバと通信できるCLIツール）
　・認証用のファイル
　　デフォルトではhtdocs配下に保存されるが、certbot-autoのオプションで--webrootで出力するパスを指定すると${webroot-path}/.well-known/acme-challengeの形でLet’s Encryptの認証ファイル出力先を変更することができる

## 前提条件
 [1]この記事ではApacheをSSL化する前提で記載します。
 [2]Webサーバは存在していることを前提で記載します。
 [3]以下のパッケージはダウンロード済みであることを前提で記載します。
　　(1)git
　　(2)certbot
　　(3)python2-certbot-apache

## 実施した環境
【マシン】
　AWS EC2 t2.micro
【OS】
　CentOS 7.6.1810 (Core)

## 通信要件
以下、全てインバウンドのみに適用することを前提とする。

HTTP 80 0.0.0.0/0(::/0)
HTTPS 443 0.0.0.0/0(::/0)
※mod_sslでhttps化している場合、mod_rewriteを利用して、httpでアクセスがきたら、httpsへリダイレクトする設定を追加しておく考慮が必要です。

## やること

以下、どちらかのパターンで実装することが可能です。

[1]git経由で導入する
以下のコマンドでリポジトリをダウンロードできます

```bash:コマンド
git clone https://github.com/letsencrypt/letsencrypt.git
```
以下のコマンドで証明書の導入を行うことが可能です。

```bash:コマンド
cd ./letsencrypt/
./letsencrypt-auto certonly --webroot --webroot-path <認証用の一時ファイルを作成するパス> -d <Webサーバドメイン> -n
```

[2]certbotコマンドで導入する
以下のコマンドで証明書の導入を行うことが可能です。

```bash:コマンド
certbot certonly --standalone -d <Webサーバドメイン> --register-unsafely-without-email --webroot --webroot-path <認証用の一時ファイルを作成するパス> -n
```

一見、certbotコマンドが１コマンドで導入できて便利そうな印象なのですが、gitのリポジトリで使えるコマンドのほうがオプションが充実していて、Webサーバ上の証明書まで一気通貫で更新できるものあるようです。
※certonlyのオプションを別のオプションに変更すれば良いようです。

両パターンに共通して言える注意点として、上記のコマンドを実行する際に以下の条件を満たしている必要があります。
そうでないとエラーが発生して、証明書を取得できない場合があります。
最低限、以下の条件を満たしておく必要があります。

【注意点】
　(1)コマンド実行前にポート80番と443番が使われていないことを確認する
　　　※httpd、nginx、rails、phoenixとかのwebサーバは停止しておいてください。
　(2)名前解決できるようDNSレコードを登録しておく
　　　→上記に記載した通り、Let’s EncryptサーバがWebサーバにアクセスしてくるため、
　　　 外部から名前解決できるようにAレコードを登録しておいてください。
　　　 IPv6のAAAAレコードはなくても証明書は取得できます。

上記、紹介したコマンドではWebサーバで指定している証明書の情報は更新されないため、Webサーバの設定にて証明書の指定を変更しておく必要があります。

```bash:
102,103c102
< # SSLCertificateFile /etc/pki/tls/certs/localhost.crt
< SSLCertificateFile  /etc/letsencrypt/live/<Webサーバドメイン名>/cert.pem
---
> SSLCertificateFile /etc/pki/tls/certs/localhost.crt
110,111c109
< # SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
< SSLCertificateKeyFile /etc/letsencrypt/live/<webサーバドメイン名>/privkey.pem
---
> SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
```

IPv6用のAAAAレコードを登録しておくとLet’s EncryptサーバからIPv6でアクセスしてくるので、Webサーバ上ででもIPv6でのアクセス処理ができるように工夫しておく必要があります。

具体的にはhttpd.confファイルのListen設定などを変更しておく必要があります。

<参考：Apache HttpdのIPv6の設定と確認>
https://http2.try-and-test.net/ipv6httpd.html