techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

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 利用規約に同意するための自動化オプション。指定しない場合はインストール過程でユーザが明示的に同意する。
--email メールアドレス

※参考:コマンド解説 - 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コマンドもできるだけ自動化していますが、全ては自動化できてません)
方法がわかればまた共有したいと思います。

というわけで今回はこの辺で。