ChefでLet's Encryptを利用するためのDefinitionを定義してみた
Chefのレシピを記述する際は、リソースを使用することで簡単にパッケージのインストールやサービスの起動、フォルダの作成などを行うことができます。
Chefから提供されているリソースには便利なものがたくさんありますが、Definitionを使えば自分で作成するもできます。
今回はGitからLet's Encryptをダウンロードし、証明書の取得を行ってみます。
【環境】
ゲストOS : Cent OS 6.8
ホストOS : Mac OS X
HTTPサーバ : Apache
※Let's Encryptを利用するにはドメイン名が必要です。また、予めsshでログインできる状態にしておきます。
Defintionの定義
Let's Encryptを利用するためのクライアントCertbotをGithubからダウンロードし、証明書の取得までを自動で行ってみます。
クライアントCertbotで証明書をインストールする方法は前回を参考にしてください。今回も同じ環境を使用しています。
Chefについてはこの辺りを参考にしてください。
まずはLet's Encrypt用のcookbookを用意します。cookbookの名称はなんでも構いません。(ホストPCでの作業)
$ mkdir test_letsencrypt_chef $ cd test_letsencrypt_chef $ knife solo init . $ knife cookbook create certbot -o site-cookbooks
cookbookができたらDefinitionを定義し、新しいリソースを作成します。
Definitionは、<test_letsencrypt_chef>/site-cookbooks/certbot/definitions ディレクトリに任意の名称のRubyファイルを作成してその中に定義します。
今回は以下のようにしました。
[certbot_auto.rb]
define :certbot_auto, :email => "sample@gmail.com", :domain => "sample.com" do git "/root/certbot" do # /rootディレクトリの下にcertbotディレクトリが作成され、その中にGitから取得するファイル類がダウンロードされる repository "git://github.com/certbot/certbot.git" #Githubのリポジトリを指定 revision "master" # masterブランチから取得 action :checkout # チェックアウト user "root" # rootユーザで実行 group "root" # rootグループで実行 notifies :run, "execute[install certbot]", :immediately # 後述 end execute "install certbot" do action :run user "root" group "root" cwd "/root/certbot" # カレントワーキングディレクトリの指定 environment "HOME" => '/root/certbot' # 証明書取得のコマンドを定義 command "./certbot-auto certonly --webroot -w /var/www/html -d #{params[:domain]} --non-interactive --test-cert --keep --agree-tos --email #{params[:email]}" end end
1行目はリソースの名称とパラメータを定義します。今回は「certbot_auto」という名前のリソース名にしました。
パラメータとしてはドメイン名とメールアドレスを指定できるようにします。渡されてきたパラメータは、コード上でparams[:domain]
のような形で参照できます。
今回作成するcertbot_autoリソースでは、まずは2行目〜9行目で、gitリソースを使用してGithubからLet's Encryptを利用するためのCertbotクライアントを取得します。
gitリソース内で使用しているオプションは特に難しいものはないと思いますが、notifiesオプションは他のリソース(ここではexecuteリソース)を呼び出すことができます。今回はGithubからCertbotクライアントを取得したらexecuteリソースを呼んでいます。
そのexecuteリソースは、11行目以降で定義しています。executeリソースを利用すれば、任意のコマンドを実行できます。今回は、証明書を取得するためのcertbot-autoコマンドを実行します。
今回実行しているコマンドのオプションはそれぞれ以下の通りです。詳細は参考を見てみてください。
オプション/サブコマンド | 概要説明 |
---|---|
certonly | 証明書の取得だけを行うサブコマンド |
--webroot | プラグインの指定。ウェブサーバの DocumentRoot以下に認証用のファイルを設置する |
-w | ウェブサーバの DocumentRootを指定 |
-d | ドメイン名の指定 |
--test-cert | テスト用証明書を取得。本番用証明書は1ドメインあたり取得できる数に制限あり |
--non-interactive | ユーザ入力を回避する |
--keep | 「既存の証明書を上書きしない」を指定するための自動化オプション。指定しない場合はインストール過程でユーザが明示的に選択する |
--agree-tos | ACME 利用規約に同意するための自動化オプション。指定しない場合はインストール過程でユーザが明示的に同意する。 |
メールアドレス |
※参考:コマンド解説 - Let's Encrypt 総合ポータル
certbot-auto
コマンドは、実行中にユーザに対してドメインやらメールアドレスやらの入力を求めてきます。
しかしChefでインストールするためにはこの辺りの入力は邪魔になるので、全て自動化するためにオプションであらかじめ必要となる情報を定義しておきます。
さて、これでDefinition定義は出来上がりです。
レシピの作成
Definitionを定義したら、レシピで定義したリソースを使用します。 今回はシンプルに以下のようにします。
certbot_auto "certbot_auto" do domain "<ドメイン名>" email "<メールアドレス>" end
一行目で、今回定義したリソースcertbot_autoの利用を宣言します。後に続く"certbot_auto"は、Definition定義ファイル内でparams[:name]
で取得できますが、今回は特に使用していないのでなんでもオッケーです。ドメイン名とかを指定できるようにしておくといいかもしれません。
あとはDefinitionの方でパラメータとして定義したdomainとemailに値を指定しておきます。
apacheのcookbookの用意とnodeオブジェクトファイルの記述
今回はApache2をHTTPサーバとして利用するので、ついでにChefでインストールできるようにしておきます。(今回必須ではないので飛ばしてもオッケーです) cookbookの作成とレシピファイルの記述はこちらを参考にしてください。
最後に忘れずにnodeオブジェクトファイルを以下の通り定義します。
{ "run_list": [ "recipe[apache]", "recipe[certbot]" ], "automatic": { "ipaddress": "<ドメイン名>" } }
実行と確認
というわけで、cookbookをサーバに適用します。ホストOS上で以下のコマンドを実行します。
$ knife solo bootstrap root@<サーバのドメイン名>
これでサーバ(おそらく以下のディレクトリ)に証明書などが配置され、ssl.confファイルが配置されているかと思います。
また、Apacheもインストールされているはずなので、http://<ドメイン名>
でApacheのトップページが見えるはずです。
/etc/letsencrypt/live/<ドメイン名>/.pem
/etc/letsencrypt/live/<ドメイン名>/.cert
/etc/letsencrypt/live/<ドメイン名>/*.chain
ただし、今回はあくまで証明書の取得のみ行っており、HTTPSでアクセスするためにはさらに以下のコマンドをサーバ側で実行し、証明書のインストールを行う必要があります。
/root/certbot/certbot-auto install --keep --cert-path /etc/letsencrypt/live/<ドメイン名>/cert.pem --key-path /etc/letsencrypt/live/<ドメイン名>/privkey.pem -d <ドメイン名> --chain-path /etc/letsencrypt/live/<ドメイン名>/chain.pem --no-redirect
コマンドを実行すると、ssl.confに設定が自動で書き込まれます。
本当はインストールまでChefで行いたかったのですが、./certbot-auto run
に--non-interactiveオプションを指定するとコマンドラインフラグが足りないと言われてしまい自動化することができず、、、今回は証明書の取得までとしました。(上記install
コマンドもできるだけ自動化していますが、全ては自動化できてません)
方法がわかればまた共有したいと思います。
というわけで今回はこの辺で。