無料のSSL証明書をWoSignからLet's Encryptに乗り換えた話

# SSL証明書を乗り換えるきっかけ

最近以下の記事が出ました。

中国最大の認証局「WoSign」が証明書発行日改竄などを行っていたとしてFirefoxがブロックの方針
http://gigazine.net/news/20160928-wosign-firefox-block/

WoSignは、無料で数年単位のSSL証明書を発行できるので、便利で使っていましたが、まさかの改竄騒ぎ勃発です、これは困りました。

昨年の初め頃に無料のSSL証明書を発行してくれる所を探した時に、WoSignくらいしか目ぼしい所が無くて選んだのですが、改めて調査してみると、Let's Encryptが今年の4月にベータから正式サービスに移行していました。

Leaving Beta, New Sponsors
https://letsencrypt.org/2016/04/12/leaving-beta-new-sponsors.html

グッドタイミングです（笑）

というわけで、改竄とか怪しさ満点のサービスとは見切りをつける決心をしました。

# Let's Encrypt導入方法

導入方法は、今までの常識を覆すような自動化がされていました。
今まで有料のSSL証明書も業務で取得したりして扱っていましたが、その時に当然の様にあった手続きが一切ありません、驚きです。

## 導入できる条件

- ドメインの権利を持っている事
- そのドメインでアクセスできるWEBサーバが動作していること

条件はこの２つだけなので、既に満たしていました。
というか、この条件持ってないのにSSL証明書欲しいという事はあまりなさそうです。

## 導入手順

証明書取得はcertbotというツールで実行します。
ツールはgithubに上がっているので、gitで引っ張ってきて使う感じです。

```
cd /usr/local
git clone https://github.com/certbot/certbot
cd certbot/
```

今回導入したサーバはCentOS6.2のVaultリポジトリ縛りにしていたので、このあとの手順では、baseとupdatesを一時的に有効にする必要がありました。

```
vi /etc/yum.repos.d/CentOS-Base.repo
```

そして以下のコマンドを実行します。

```
./certbot-auto
```

yumインストールが開始するので、「ｙ」を押して進めます。
しばらくして終わると、青い画面の対話式で証明書作成が始まりますが、選択肢に欲しいドメイン名が無かったので、キャンセルして終わらせました。

そして以下のコマンドで証明書を取得します。

```
./certbot-auto certonly --webroot \
-w /var/www/hogehoge -d www.example.com \
-m kirksencho@example.com \
--agree-tos
```
※www.example.com及びkirksencho@example.comは例示用ドメインです。

certonlyは、証明書貰うだけよというオプションです。
--webrootは、ドキュメントルートに認証用のファイルを自動で置くというオプションです。
-wの次は、当該ドメインで公開しているドキュメントルートのPATHです。
-dの次は、証明書を取得したいドメイン名です。
-mの次は、担当者のメールアドレスです。何かあった時の連絡受信用です。
--agree-tosは、利用規約に同意しますよという意思表示オプションです。

これで証明書は取得されましたが、実行中に以下のワーニングが表示されました。

```
/root/.local/share/letsencrypt/lib/python2.6/site-packages/cryptography/__init__.py:26: DeprecationWarning: Python 2.6 is no longer supported by the Python core team, please upgrade your Python. A future version of cryptography will drop support for Python 2.6
```

ググってみると、Pythonのバージョン問題にぶち当たってる方が多かったです。
スルーしてる方やSCLで対策してる方などいろいろでした。

~~試しに私もSCLで2.7を入れてみたのですが、解決には至りませんでした。~~
certbotインストール時に入る、以下のPATHの中を見てみると・・・

```
ll /root/.local/share/letsencrypt/lib/python2.6/
合計 344
lrwxrwxrwx  1 root root    32  9月 29 13:53 2016 UserDict.py -> /usr/lib64/python2.6/UserDict.py
-rw-r--r--  1 root root 10062  9月 29 13:53 2016 UserDict.pyc
lrwxrwxrwx  1 root root    31  9月 29 13:53 2016 _abcoll.py -> /usr/lib64/python2.6/_abcoll.py
-rw-r--r--  1 root root 24165  9月 29 13:53 2016 _abcoll.pyc
lrwxrwxrwx  1 root root    27  9月 29 13:53 2016 abc.py -> /usr/lib64/python2.6/abc.py
-rw-r--r--  1 root root  6357  9月 29 13:53 2016 abc.pyc
lrwxrwxrwx  1 root root    30  9月 29 13:53 2016 codecs.py -> /usr/lib64/python2.6/codecs.py
-rw-r--r--  1 root root 39165  9月 29 13:53 2016 codecs.pyc
lrwxrwxrwx  1 root root    27  9月 29 13:53 2016 config -> /usr/lib64/python2.6/config
lrwxrwxrwx  1 root root    32  9月 29 13:53 2016 copy_reg.py -> /usr/lib64/python2.6/copy_reg.py
以下略
```

こんな感じで直接Python2.6にシンボリックリンクが貼られていました。
~~なので、いくら2.7を使えるようなbashを起動しても、2.7は使ってもらえずに強制的に2.6のPythonが使われてしまって警告が出るようです。~~

~~証明書の作成自体はできたので、イマイマはこのままで行こうと思いますが、いつかは完全に動かなくなるかもしれません。~~

※2016/11/15追記
Python2.6のバージョン問題ですが、いただいた[コメント](http://qiita.com/kirksencho/items/797c60b79845f1984c40#comment-f114ee7cf15747cf319a)を元に検証したところ以下の手順で解決しました。

- /root/.local/share/letsencrypt/のフォルダはキャッシュなので削除。
- scl enable python27 bashを再度実行
- certbot-autoコマンドを実行

以上で2.6の警告が表示されず2.7が使用されました。
この状態で以下に2.7のキャッシュが作成されていました。
/root/.local/share/letsencrypt/lib/python2.7

ただ、その後scl enable python27 bashしていない状態でcertbot-autoコマンドを実行してしまうと、再び2.6のキャッシュに置き換わってしまうので注意が必要です。

※2017/02/17追記
Python2.6のバージョン問題ですが、iusリポジトリを利用したもっと簡単な解決方法を見つけました。
以下、CentOS6の場合の手順です。

```
rm -rf /root/.local/share/letsencrypt
wget https://centos6.iuscommunity.org/ius-release.rpm
rpm -ivh ius-release.rpm
yum -y install python27 python27-devel python27-pip python27-setuptools python27-virtualenv
```

上記のインストール完了後に、コンソールに再ログオンしてからcertbot-autoを実行するとpython2.7を見つけてくれて勝手に使ってくれました。
キャッシュにもpython2.7が保存されます。
この方法だと、scl enableをうっかり忘れて2.6のキャッシュが出来て警告出ちゃったというミスも起きないので嬉しいですね。

## apacheの設定変更

apacheのconfファイルの該当するサーバの設定に以下を書いておきます。

```
SSLCertificateFile /etc/letsencrypt/live/www.example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/www.example.com/chain.pem
```

そしてapacheをリロードすれば完了です。

```
service httpd reload
```

## 自動更新の方法

Let's Encryptは有効期限が90日しかありません。
なので、そのたびに人間が処理を行うのは面倒ですし、忘れそうです。

なので、コマンド一発で更新できるようにcrontabに設定を入れます。

※2016/11/15追記
コマンドの先頭に「source /opt/rh/python27/enable;」を追加

※2017/02/17追記
iusリポジトリを利用したpython2.7導入方法の場合は「source /opt/rh/python27/enable;」の追加は不要です。

```
crontab -u root -e
00 03 01 * * source /opt/rh/python27/enable;/usr/local/certbot/certbot-auto renew --force-renew && /sbin/service httpd reload
```

上記は毎月1日の午前3時に強制的に証明書を更新するコマンドです。
crontabで90日おきという表現ができないので、毎月やっちゃいます。
Let's Encryptは更新頻度に上限がありますが、月に一回であれば問題無さそうです。

# おわりに

今回、まさかの認証局側の不祥事でSSL証明書を他の組織に変更しなければならない緊急事態に直面して実施した対策をまとめてみました。
~~Pythonのバージョン問題が残ってるのが、ちょっと心残りではありますが、ひとまず解決できて良かったです。~~
他にLet's Encryptの様なサービスが見当たらないので、オンリーワンなのがちょっと不安ではありますが、サービスがずっと継続してくれる事を願うばかりです。