[chef] chef solo + knife solo で、encrypted data bag を使うための 5ステップ [password]

こんなタイトルの記事はいくらでもあるので、今更感満載だけれども、あえて書きます。
なぜかというと「私のため」だから。

さて、chef を使っていて、パスワードを埋め込んだり変更したりと言うことはよくあるざます。
その時に、`node` ファイルや `attributes` へ直接書き込んだまま、Github に上げてしまうと、パスワードバレバレの事態になります。さすがに初心者でも気がつく当たり前の事象です。

とは言え、data bagってなんかめんどくさいし、password は`環境変数` でもいっか、とか手の抜きどころを沢山考えたのですが、折角与えられた機能だから使ってみよう。使っておこう。
そういうことにして、本日はそのステップのみを記載して終わりにします。

夜遅いし、まだ仕事終わってないし。

# 1. 鍵を作る

君のマシンに `openssl` コマンドはあるか?
よし、次のコマンドを打て

```bash:鍵
openssl rand -base64 512 > data_bag_key
```

名前も場所も好きなところで良いけれども、`~/chef_repo` 配下だと何も考えずに `git add` して `git commit` して `git push` して泣くことになるかも知れないので、別のトコへ配置するのが推奨かも。 `.gitignore` にわざわざ書いてもいい。

オレは `Emacs` で `magit-status` でいちいち staging する内容確認してるから、どこでも問題なし。さすが、`Emacs` (関係ない)

# 2. .chef/knife.rb 書き換え

書き換えといっても大したことじゃないです。
最小限の作業としては、1行アンコメントするだけです。

```ruby:.chef/knife.rb
cookbook_path    ["cookbooks", "site-cookbooks"]
node_path        "nodes"
role_path        "roles"
environment_path "environments"
data_bag_path    "data_bags"
encrypted_data_bag_secret "data_bag_key"

knife[:berkshelf_path] = "cookbooks"
```

`encrypted_data_bag_secret "data_bag_key"` をアンコメントして、指定したファイルとするだけです。`/etc/chef/data_bag_key` へ配置したなら
`encrypted_data_bag_secret "/etc/chef/data_bag_key"` となることでしょう。
簡単。

# 3. knife solo 用の data bag ツールを準備する

たいそうなこと言ってますが、`gem install knife-solo_data_bag` してくださいってだけです。`sudo` する派もしない派もどちらでもいいですし、`bundle`派も自分の環境どおりに好きにしてください。私は `sudo`派です。ゴメンなさい。

```bash:gem
$ sudo gem install knife-solo_data_bag
Password:
Fetching: knife-solo_data_bag-1.1.0.gem (100%)
Successfully installed knife-solo_data_bag-1.1.0
Parsing documentation for knife-solo_data_bag-1.1.0
Installing ri documentation for knife-solo_data_bag-1.1.0
1 gem installed
```

# 4. 鍵を使って暗号化 json を作成する

事前に `EDITOR` 環境変数を指定しておきましょう。よく分からない人は次のようにして、vi でも使ってください。vi の使い方知らない人が、chef 使うことはあり得ないでしょう。

```bash:EDITOR
$ export EDITOR=vi
```

そして、次のコマンドです。

```bash:create_data_bag
$ knife solo data bag create password mysql --secret-file ./data_bag_key 
```

`knife solo data bag create` まで固定です。
次に指定している `password` `mysql` は、ディレクトリで示すと次のようになります

```bash:mysql
~/chef_repo/data_bags/password/mysql.json
```

分かりやすい。`password` というグループに、`mysql` 用の定義を準備したと理解するといいですね。はい、私はそんな風に理解しました。

`--secret-file` の後は、お分かりのように、1. で作成した鍵ファイルを指定します。

すると、きっと次のような画面が出てくるはずです。

```bash:default
{
  "id": "mysql"
}
```

ここで必要な定義を追加して、そっと閉じましょう。

```bash:default
{
  "id": "mysql",
  "password": "p@ssw0rd"
}
```

実際はこんな単純なパスワードは使ってませんが、例えばです。 なお、`"id": "mysql"` は、おまじないの中でも必須な条項です。書き換えるのはやめておきましょう。

試しに中を覗いてみるとこんな感じです。

```bash:mysql.json
$ cat data_bags/password/mysql.json 
{
  "id": "mysql",
  "password": {
    "encrypted_data": "6u167KJgpqz0MxwHW+SZ3/kxXkehCeCYZfuSqoJqYRg=\n",
    "iv": "raa292+i9HCAED4DC9eEFg==\n",
    "version": 1,
    "cipher": "aes-256-cbc"
  }
}
```

見事、暗号化されていますね。良かった。

# 5. recipe で読み出す

後は、実際にchef のレシピで呼び出すだけです。

こう。

```ruby:load
data_bag = Chef::EncryptedDataBagItem.load('password','mysql')
mysql_password = data_bag['password']
```

これで、`mysql_password` 変数に一時的に復元されたパスワードが保持されました。

`template` resource 内で使う場合は、`variables` で飛ばして上げる必要があります。

```ruby:template
template "foo" do
  variables ({
               :password => mysql_password
             })
end 
```

で、`foo` という tepmlate ファイル内では、こう

```ruby:foo
PASSWORD = '<%= @password %>'
```

で定義されます。良かったネヽ(´ー｀)ノ