SSL/TLS証明書を無償で取得し設定する

# 背景
世界的にWebサービスのセキュリティ向上の為、従来の平文HTTPから暗号化HTTPSへの移行「常時SSL/TLS」が進められています。
これはHTTPSしていないWebサイトでは、かなりの数のハッキングがされており、悪用されている恐れがある事が背景にあります。
Googleの検索サービスでもHTTPSされたサイトの検索順位を上位にランクする方針で、SEO対策的にもメリットがあります。
また一般の利用者にもHTTPSを標準で利用する様にWebブラウザにて対応が進行しています。
特にGoogleのWebブラウザChromeは2017年から警告表示を開始しています。

[グーグル、「Chrome 56」でHTTP接続への警告表示を開始](https://japan.zdnet.com/article/35095743/)

[グーグル、HTTPページへの警告表示を強化へ--10月リリース予定の「Chrome 62」から](https://japan.cnet.com/article/35100589/)

テキストボックスにてフォーム入力する際にはHTTPSしていないとユーザーに警告される事になります。
金融やショピングなどのWebサイト以外でも今後全てのWebサービスは「常時SSL/TLS」が求められて来る事でしょう。

# 無償のSSL/TLS証明書
従来は認証局に費用を払って購入していたSSL/TLS証明書ですが、DVに関しては無償で取得できる認証局があります。

[Let’s Encrypt](https://letsencrypt.org/)

2016年4月に正式サービスが開始されて商用利用も可能です。
必要なのは申請する管理ドメインと連絡先メールアドレスだけです。

# 事前準備
SSL/TLS証明書を取得するにあたって準備が必要になります。

- 管理する独自ドメインのDNSのゾーンテーブルにAレコードを設定する。
- ファイヤーウォールの設定でHTTP(tcp/80),HTTPS(tcp/443)を開ける事。
- root権限のあるサーバー
- 連絡先メールアドレス

必ずしもApacheなどのWebサービスを事前に起動している必要はありませんが、Let’s Encryptと疎通出来る環境が必要になります。

# certbotインストール
Let’s EncryptではSSL/TLS証明書を取得するツールとしてcertbotを推奨しています。

[certbot](https://certbot.eff.org/)

各プラットホーム毎にインストール方法が解説されています。
今回は、CentOS7でApacheの環境にて行ってみます。

[Apache on CentOS/RHEL 7](https://certbot.eff.org/#centosrhel7-apache)

CentOS 7の場合は、EPELリポジトリにパッケージがあります。

CentOS 7 + Apacheプラグインの場合
````
$ sudo yum install --enablerepo=epel python-certbot-apache
````

CentOS 7 + Apacheプラグインを使わない場合
````
$ sudo yum install --enablerepo=epel certbot
````

# SSL/TLS証明書の取得方法
certbotのコマンドだけでSSL/TLS証明書が取得できますが、自動設定よりオプション指定による取得を推奨しておきます。以下のサイトにてオプションのガイドが日本語で解説されています。

[Let's Encrypt 総合ポータル](https://letsencrypt.jp/)

webサービスが既に起動しているかいないかでオプションを選択します。

webサービスが既に起動中の場合	→　--webroot　オプション
````
$ sudo certbot certonly --webroot -d www.example.jp
````
webサービスが起動していない場合	→　--standalone　オプション
````
$ sudo certbot certonly --standalone -d www.example.jp
````

今回はApacheが既に起動してインターネットから疎通確認出来ている環境とします。

````
$ sudo certbot certonly --webroot -w /var/www/html -d www.example.jp
````
wオプションはwebサイトコンテンツのドキュメントルートを指定します。
dオプションは申請する独自ドメインのFQDNになります。事前にDNSのゾーンテーブルにAレコードを登録して疎通が確認出来ている必要があります。
certbotコマンドを実行すると連絡先メールアドレスの入力を求められます。

````
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):メールアドレスを入力
````

次にライセンス承諾を求められます。

````
-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel:Agree
````

連絡先のメールアドレス宛にLet’s Encryptの認証確認メールが届きます。
メール文中のリンクをクリックしてLet’s Encryptのサイトに行くと無事に承認されます。
これでSSL/TLS証明書の発行準備が出来ましたので実行します。

````
-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: Yes
Starting new HTTPS connection (1): supporters.eff.org
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for www.example.jp
Using the webroot path /var/www/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/www.example.jp/fullchain.pem. Your cert
   will expire on 2017-07-30. 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"
````

申請したドメイン名とドキュメントルート、有効期限が表示されて無事にSSL/TLS証明書が取得出来ました。
取得したSSL/TLS証明書は以下の場所にあります。

サーバ証明書と中間証明書が結合されたファイル
`/etc/letsencrypt/live/www.example.jp/fullchain.pem`
※Apache 2.4.8 未満は使用しません。

秘密鍵
`/etc/letsencrypt/live/www.example.jp/privkey.pem`

# Apacheの設定と再起動
取得したSSL/TLS証明書を設定ファイルに編集します。

```conf:/etc/httpd/conf.d/ssl.conf
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/letsencrypt/live/www.example.jp/fullchain.pem

#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.jp/privkey.pem
````

有効にする為にサービスを再起動します。

````
$ sudo systemctl restart httpd
````

WebサービスにHTTPSにて接続を確認してみましょう。
また、鍵アイコンから証明書が正しいモノかも確認しておきましょう。

「常時SSL/TLS」する為に、HTTP接続した場合にHTTPSにリダイレクトする様に設定をします。

```conf:/etc/httpd/conf.d/rewrite.conf
  <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
  </IfModule>
````

有効にする為にサービスを再起動します。

````
$ sudo systemctl restart httpd
````

WebサービスにHTTPにて接続を確認してみましょう。
HTTPSにリダイレクトされたら晴れて「常時SSL/TLS」する事が出来ました。

# SSL/TLS証明書の更新
Let’s Encryptで取得したSSL/TLS証明書の有効期限は3ヶ月と短期間です。
更新コマンドをその都度行うのは面倒ですので、cronで定期実行する事で更新します。
また更新間際でないと実際には更新が実行されない為、cronの定期実行は毎週行うことで更新漏れを防ぎます。

````
$ sudo crontab -e
30 2 * * 0 /bin/certbot renew --pre-hook "systemctl restart httpd"
````
毎週日曜日AM2:30に実行し、更新後はApacheを再起動する。