APIの認証について
pemっていうファイルで認証しているのはなんとなくわかる。
このなんとなくを解消したいと思う。
本エントリはWikiの誤訳だと思ってほしいです。
API Clients
nodeデータはChef serverからの認証リクエストによって別々に管理されており、それはすなわちAPI Clientごとに管理されているということです。どのAPI Clientも公開/非公開キーを所持しています。
公開キーはChef server側で所持され、非公開キーはAPI Clientのほうで所持しています。nodeを実行したとき、非公開キーが自動的に/etc/chef/client.pem上に生成されます。knifeコマンドを利用するのが管理者の場合~/.chef/USERNAME.pemに非公開キーは生成されます。
全てのChef serverへのリクエストはHTTP headerに認証情報が入っています。署名はClient側のリクエストにClientの非公開キーを用いて暗号化したものを利用します。
The Validation Client
Chef Clientの初回アクセスはAPI Clientのキーをまだ生成できておらずChef serverへ認証リクエストを作る事ができません。
そこでデフォルトで"validation-client"という特殊なClientを使います。Chef clientが実行されて、最初にキーがなかったときChef serverに自分自身を登録するためvalidation-clientを一時的に借りるようにします。それをするために、validation clientの非公開キーをChef clientホストの/etc/chef/validation.pemにおくようにしてください。
一度Chef server側に登録できればこの特殊なClientは必要なくなります。一度validation clientを利用してChef serverに登録したらそのホストにおいてあるキーを削除する事をおすすめします。
Signed Header Authentication
APIの認証は基本的にリクエストごとに実施します。そしてそのリクエスト自体はClientがキーを利用して作成しています。つまるところ、結局HTTP headerに毎回ユニークな認証キーを作成しているだけです。リクエストは以下の項目を所持しています。
- The HTTP Method (GET/PUT/POST/DELETE)
- The Request Body in Base64
- A Timestamp
- Your Client ID
リクエストはClient側の非公開キーによって暗号化され、HTTP headerにセットされ、Chef server側でそれを解釈します。さらに受け取ったリクエストが本当にChef client側から送られてきたものなのかどうかをbodyがかわっていないかHTTP methodに変わりはないか必要な回数以内のリクエストなのかということから判断します。
全てのリクエストはHTTPS経由で行う事をお勧めします。
Chef Clientにはclient keyが発行されることになります。
Under the hood
新しいAPI Clientが作成されたとき、Chefは新しい公開/非公開キーを作成します。公開キーはChef serverで保持され、非公開キーはAPI Client側で保持されます。リクエストがきたときChef server側では以下のように検証を行います。(公開キーを利用します)
この検証は以下のメリットをもっています。
- 全てのリクエストで認証が必要
- Sessionを持たなくてよい
- リクエストを改ざんされても問題ありません
- end-to-endの認証なのでいかなるトランスポート層を通る事ができます
Chef Clientの認証の仕組みは以下の通りです。
- 最初にChef clientがclient keyを持っているか確認します
- もし持っていたら認証リクエストの発行を開始します
- もし持っていなかった場合validation keyをもっているか確認します
- もし持っていたらAPIを利用するためのリクエストを作成します
- もし持っていなかったら、失敗です。。。
- もしClient keyを作成できた場合、それを使って再度リクエストを作成します
The Web UI key
Chef web UIはChef APIのようなものです。違いはインストール時にキーが発行されることです。(同時にvalidation keyも発行されます)
Creating new API Client Keys with Knife
もしChef-server上にデフォルトのユーザでリクエストを送りたくなければ絶対に自分自身のキーを作った方がいいですよ。
API clientを生成する際は、まず以下のknifeコマンドを発行しましょう。
$ knife client create monkey INFO: Created (or updated) client[monkey]
これから利用する非公開キーが発行されます。さらに以下のコマンドを発行しましょう。
knife client create monkey -f /tmp/monkey.pem
この例でいえば/tmp/monkey.pemに非公開キーができるはずです。
まとめ
- Chef-serverは公開キー持ってればいい
- Chef-Clientは非公開キーが必要
- 上記のAPI Clientの作り方だと失敗したよ(僕の環境)
- でもChef-webuiから発行できるよ
- 発行したものをChef-clientサーバのpemファイルに保存すれば問題なく動きます
追記
API Clientの作り方失敗しませんでした
- Client上に/etc/chefディレクトリ作成
- /etc/chef/client.rbに最低限以下のものを設定したファイルをおく
- client_key
- chef_server_url
- /etc/chef/validation.pemに非公開キーをおく
- chef-clientを実行
- chef-validatorが新しいclient_keyを作成してくれる
- ~/.chef/knife.rbにclient.rbにnode_nameあたりを追加したものをコピー
- knife node listで出力確認
なんかApacheインストールするためだけのレシピ
%w(#{node[:apache][:work_dir]} #{node[:apache][:install_dir]}).each do |dir| directory dir do owner "root" group "root" mode 0644 action :create recirsive true end end cookbook_file File.join(node[:apache][:work_dir], "httpd.tar.gz") do source "httpd-2.2.17.tar.gz" action :create owner "root" group "root" mode 0644 end script "install apache" do interpreter 'bash' user 'root' cwd node[:apache][:work_dir] code <<-EOC tar -zxvf httpd.tar.gz cd httpd-2.2.17 ./configure #{node[:apahe][:install_options]} make make install EOC end