Locked

CentOS_TIPS_005

Let's Encrypt の SSL/TLS 証明書を取得/設定

Let's Encrypt の「SSL/TLSサーバ証明書」(無料!)を取得し、CentOS/apacheに設定します。

  • 総合ポータルサイト(日本語)

https://letsencrypt.jp/

本家ツールが「letsencrypt-auto」から「certbot-auto」になっています。
クライアントツールも、多種多様な実装が出てきているので、得意なジャンルのツールを選択すると良いでしょう。

https://letsencrypt.org/docs/client-options/

https://certbot.eff.org/

以前「letsencrypt.sh」として公開されていたbashによる実装(非公式)の方もプロジェクト名が「dehydrated」になっています。

https://github.com/lukas2511/dehydrated

2016.9.17時点では、何れもベータ扱いのようですが、一旦、ドキュメントの再整理をしました。
引き続き、各ツールは更新が見込まれるものと思われますので、最新の情報を確認してください。

バージョン情報

サーバ側の情報は以下の通り。

$ cat /etc/redhat-release
CentOS release 6.8 (Final)

$ httpd -v
Server version: Apache/2.2.15 (Unix)
Server built:   Jul 18 2016 15:24:00

certbot-auto

SCLとepelを使用出来るように用意し、python27をインストールします。

# yum install python27-python python27-python-virtualenv python27-python-pip python27-python-tools
...
依存性を解決しました

================================================================================
 パッケージ                  アーキテクチャ
                                     バージョン           リポジトリー     容量
================================================================================
インストールしています:
 python27-python             x86_64  2.7.8-16.el6         centos-sclo-rh   82 k
 python27-python-pip         noarch  7.1.0-2.el6          centos-sclo-rh  1.5 M
 python27-python-virtualenv  noarch  13.1.0-1.el6         centos-sclo-rh  1.7 M
 python27-python-tools       x86_64  2.7.8-16.el6         centos-sclo-rh  879 k
依存性関連でのインストールをします。:
 python27-python-devel       x86_64  2.7.8-16.el6         centos-sclo-rh  387 k
 python27-python-libs        x86_64  2.7.8-16.el6         centos-sclo-rh  5.7 M
 python27-python-setuptools  noarch  0.9.8-3.el6          centos-sclo-rh  423 k
 python27-runtime            x86_64  1.1-25.el6           centos-sclo-rh  1.0 M
 python27-tkinter            x86_64  2.7.8-16.el6         centos-sclo-rh  388 k
 scl-utils-build             x86_64  20120927-27.el6_6    base             17 k

トランザクションの要約
================================================================================
インストール        10 パッケージ

ツールをダウンロードします。

# wget -o /usr/local/sbin/certbot-auto https://dl.eff.org/certbot-auto

初めてインストール/使用する場合

ツールの実行前に、apacheの設定を変える必要があるか確認します。
SSL/TLS証明書の取得/更新時に、以下のディレクトリが作成され、簡易的な認証に使用されます。
このディレクトリが外部からアクセス可能であるかの確認(必要に応じて設定)が必要になります。
ツール実行時にapacheを停止しておき、「--webroot -w」の代わりに「--standalone」を指定して(一時的に簡易ウェブサーバが起動して)認証処理を行うことも可能ですが、証明書更新の都度対応が必要となります。

{サイトのドキュメントルート}/.well-known/acme-challenge/

ツールを実行し、証明書を取得します。
「-d」でドメインのFQDN(SSL/TLS証明書における「CN」)を、「-m」で連絡用メールアドレス(対Let's Encrypt用)、「--agree-tos」でLet's Encryptの利用規約に同意の表明を示します。
オプション「-n」を付けることで、追加インストールが必要なパッケージ類を自動的に(応答無しで)インストールします。

# scl enable python27 /bin/bash
# python --version
Python 2.7.8
# certbot-auto certonly -n --webroot -w {サイトのドキュメントルート} -d example.jp -m info@example.jp --agree-tos

最終的には自動更新処理もroot権限で実行するしかないため、ここではrootになって作業を進めています。
ユーザ権限での実行も可能ですが、ツールの実行にはroot権限が必要なためsudoパスワードの入力を求められます。
また、sudoされた時点でsclによる環境切替もリセットされてしまうため、python27環境での実行には別の対応が必要となります。

以下のメッセージが表示されると、SSL/TLSサーバ証明書の取得が成功/完了です。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.jp/fullchain.pem. Your cert will expire
   on 2016-03-13. To obtain a new version of the certificate in the
   future, simply run Let's Encrypt again.
 - If like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

取得した証明書関連のファイルは/etc/letsencrypt/live下に格納されます。

apacheの設定ファイルに適用します。
以下の例ではプライベート証明書で構築/設定されていたものを修正しています。

-  SSLCertificateFile /etc/pki/tls/certs/example.jp.crt
-  SSLCertificateKeyFile /etc/pki/tls/certs/example.jp.key
-
+  SSLCertificateFile /etc/letsencrypt/live/example.jp/cert.pem
+  SSLCertificateKeyFile /etc/letsencrypt/live/example.jp/privkey.pem
+  SSLCertificateChainFile /etc/letsencrypt/live/example.jp/chain.pem

letsencrypt-autoからcertbot-autoへの切替

古いツールが/root/.local/share/letsencrypt下で動作しているはずなので、そちらを使用しないようにします。
以下の例では、一応、別名で残していますが、消してしまっても構わないでしょう。

# mv /root/.local/share/letsencrypt /root/.local/share/_letsencrypt

ツールにより更新処理を実行します。
python27を使用していますが、python26のパッケージをインストールしようとしますので、そのまま適用してください。

# scl enable python27 /bin/bash
# python --version
Python 2.7.8

# certbot-auto renew
Bootstrapping dependencies for RedHat-based OSes...
yum is /usr/bin/yum
...
依存性を解決しました

================================================================================
 パッケージ          アーキテクチャ
                                   バージョン              リポジトリー    容量
================================================================================
インストールしています:
 python-tools        x86_64        2.6.6-66.el6_8          updates        871 k
依存性関連でのインストールをします。:
 tix                 x86_64        1:8.4.3-5.el6           base           252 k
 tkinter             x86_64        2.6.6-66.el6_8          updates        258 k

トランザクションの要約
================================================================================
インストール         3 パッケージ
...
インストール:
  python-tools.x86_64 0:2.6.6-66.el6_8

依存性関連をインストールしました:
  tix.x86_64 1:8.4.3-5.el6            tkinter.x86_64 0:2.6.6-66.el6_8

完了しました!
Creating virtual environment...
Installing Python packages...
Installation succeeded.

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/example.jp.conf
-------------------------------------------------------------------------------

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/example.jp/fullchain.pem (skipped)
No renewals were attempted.

証明書自動更新

証明書の有効期限は取得後90日です。
コマンド内で有効期限切れのチェックが行われるようになりましたので、cronでの実行をdaily/weeklyにしても良さそうです。

(scl enable python27 'certbot-auto renew --post-hook "/sbin/service httpd graceful"') >>{ログファイル} 2>&1

ルート証明書

以下のURLから取得できます。

https://letsencrypt.org/certificates/

dehydrated

非公式ですがbashによる実装「dehydrated」の使用例を記述します。
これによりpythonのバージョンに依存せず、例えばCentOS5等でも証明書を取得できるようになります。

https://github.com/lukas2511/dehydrated

処理にroot権限が不要になる点もよいです。

2016.9.17時点のスクリプトを使用してCentOS5で取得してみました。

$ cat /etc/redhat-release
CentOS release 5.11 (Final)

ファイル格納用のディレクトリを用意します。

# mkdir /usr/local/etc/dehydrated /var/www/dehydrated /var/www/html/.well-known
# chown {YOUR ACCOUNT}:{YOUR GROUP} /usr/local/etc/dehydrated /var/www/dehydrated /var/www/html/.well-known

GitHubからスクリプト群を取得/初期設定を行います。

$ git clone https://github.com/lukas2511/dehydrated
$ cp dehydrated/docs/examples/config /usr/local/etc/dehydrated/config
$ echo 'example.jp' > /usr/local/etc/dehydrated/domains.txt
$ ln -s /var/www/dehydrated /var/www/html/.well-known/acme-challenge

旧バージョン/letsencrypt.shを使用していた場合、ファイル格納用ディレクトリ名を変更します。
また、必要に応じて{WELLKNOWN}で設定していたディレクトリ/参照先を変更します。

# mv /usr/local/etc/letsencrypt.sh /usr/local/etc/dehydrated

# rm /var/www/html/.well-known/acme-challenge
# ln -s /var/www/dehydrated /var/www/html/.well-known/acme-challenge

複数のドメインを対象とする場合は空白文字を挟んで列記します。

$ echo 'example.jp example.net' > /usr/local/etc/dehydrated/domains.txt

2016.9.17現在、旧バージョンからの移行のための警告が表示(10秒sleep)されます。

$ ./letsencrypt.sh -c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! letsencrypt.sh has been renamed to dehydrated !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Due to trademark violation letsencrypt.sh had to be renamed and is know called dehydrated.

To make a clean cut dehydrated doesn't use the old config locations /etc/letsencrypt.sh and
/usr/local/etc/letsencrypt.sh anymore, also the script file has been renamed.

If you were using the default WELLKNOWN location please also update your webserver to use /var/www/dehydrated.

You are currently running (or reading) a temporary wrapper which handles the old config locations,
you should update your setup to use /etc/dehydrated and the 'dehydrated' script file as soon as possible.

Script execution will continue in 10 seconds.
...

手動実行に成功したら、これらのメッセージ表示部+sleep処理部はコメントアウトしても良さそうです。
(将来的には、上述のメッセージは表示されなくなるものと思われます。)

手動実行/証明書取得。

$ ./letsencrypt.sh -c
# INFO: Using main config file /usr/local/etc/dehydrated/config
Processing example.jp
 + Signing domains...
 + Generating private key...
 + Generating signing request...
 + Requesting challenge for example.jp...
 + Responding to challenge for example.jp...
 + Challenge is valid!
 + Requesting certificate...
 + Checking certificate...
 + Done!
 + Creating fullchain.pem...
 + Done!

$ ls /usr/local/etc/dehydrated/certs/example.jp/{cert,chain,fullchain,privkey}.pem
/usr/local/etc/dehydrated/certs/example.jp/cert.pem
/usr/local/etc/dehydrated/certs/example.jp/chain.pem
/usr/local/etc/dehydrated/certs/example.jp/fullchain.pem
/usr/local/etc/dehydrated/certs/example.jp/privkey.pem

更新も、同じコマンドで処理可能です。
デフォルトでは期限切れまで30日を下回ると更新が掛かります。

$ ./letsencrypt.sh -c
# INFO: Using main config file /usr/local/etc/dehydrated/config
Processing example.jp
 + Checking domain name(s) of existing cert... unchanged.
 + Checking expire date of existing cert...
 + Valid till Jul 25 05:07:00 2016 GMT (Longer than 30 days). Skipping renew!

daily/weeklyでcronに仕掛けておくくらいで良さそうです。