Chefのdata_bagでsecret_keyの管理

たとえばtwitterのconsumer_keyなど，外部サービスを利用するためのkeyとかtokenとかpassword等々
こういう第三者には秘密にしておきたい，githubの公開リポジトリに置いておきたくない類のものを管理する方法
ここでは，Chef（knife-solo）のData Bagという仕組みを試してみることにします．

### Data Bagとは

[入門Chef Solo](http://www.amazon.co.jp/dp/B00BSPH158)には，グローバルなドメインモデル的なデータを扱うためにつかうといいもの，といったようなことが書いてあります．
複数台のノードを扱う場合に，それらのノード全てに複数のユーザを追加したいといったケースでは，それらのユーザのデータがData Bagが扱う対象とすべきデータ，だそうです．

あまり深く考えずに，とりあえず手を動かしてみることにします．

### knife-solo インストール

一応インストールから．
knife-soloの他に，knife-solo_data_bagが要ります．

```
$ gem install knife-solo
$ gem install knife-solo_data_bag
$ knife solo init chef-repo
$ cd chef-repo
```

### 鍵の作成
鍵を作って，レシピのカレントディレクトリ下に配置します．
（.gitignoreしておくことをオススメします）

```
$ openssl rand -base64 512 > data_bag_key
```

### knife.rbの編集
.chef/knife.rbのencrypted_data_bag_secretでdata_bag_keyのパスを指定します．
今回は，L6でコメントアウトしてあるものをそのまま使えばOKです．

```rb:.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"
```

### data_bagの作成

ここでようやくデータの設定作業です．
hogeという外部サービスが発行したapi_keyとapi_secretを扱いたいという設定で作ってみます．

```
$ export EDITOR=vim
$ knife solo data bag create app hoge
```

data_bags下にapp/hoge.jsonというファイルができます．
環境変数EDITORに設定したエディタで立ち上がるので編集します．

```json:data_bags/app/hoge.json
{
  "id": "hoge",
  "api_key": "xxxxxx",
  "api_secret": "zzzzzz"
}
```

再度編集したくなった場合

```
$ knife solo data bag edit app hoge
```

knife solo data bag editを使わずに，直接hoge.jsonを覗いてみると，api_key & api_secretが暗号化されているのがわかるかと思います．
暗号＆複号には先ほど作った鍵が使われています．

```json:data_bags/app/hoge.json
{
  "id": "hoge",
  "api_key": {
    "encrypted_data": "WAxqaxShdfnww36d4sLFW+35VIbxi4zHNfs56VTrse0=\n",
    "iv": "imayJwTu00tSccCWfDVPUQ==\n",
    "version": 1,
    "cipher": "aes-256-cbc"
  },
  "api_secret": {
    "encrypted_data": "yoYzF9FHmh/jHXYqA80ZVeYvWE92EGPvI3MtAhetJ5Y=\n",
    "iv": "dfnlC0Ub5tky5tuvSrzjgQ==\n",
    "version": 1,
    "cipher": "aes-256-cbc"
  }
}
```

### レシピの記述

data_bagで設定した値は，レシピ内でChef::EncryptedDataBagItemによって読むことができます．
ここまで来たら，あとは煮るなり焼くなりお好きなようにって感じですが，今回は環境変数に設定してみることにします．

レシピの作成

```
$ knife cookbook create sample -o site-cookbooks
```

templateを使って.profileを配置します．
variablesを使うことで，テンプレートに値を指定できます．
（user名などは適当に読み替えてください）

```rb:site-cookbooks/sample/recipes/default.rb
app = Chef::EncryptedDataBagItem.load("app", 'hoge')

template "/home/vagrant/.profile" do
    source "profile.erb"
    user "vagrant"
    mode 0644
    variables({
        :api_key => app["api_key"],
        :api_secret => app["api_secret"],
    })
end
```

テンプレートの中身

```bash:site-cookbooks/sample/templates/default/profile.erb
# <関係ない所は省略>

export API_KEY=<%= @api_key %>
export API_SECRET=<%= @api_secret %>
```

### アプリケーション
アプリケーション側では，先ほど設定した環境変数から値を読み込むようにします．

### おわり

data_bagで，api_keyを暗号化した状態で管理することができるようになった．
data_bagの勉強にはなったが，ただ単にapi_keyを安全に管理したいだけならば，少々大げさな気がする，やること多いし．多分普通にprivateリポジトリとか使った方がいい．
既にChefを使ってるのであれば使えると思う．

#### 参考資料
アルパカchef日記３日目　data bagについて / またはユーザ管理クックブックなど - アルパカDiary
http://d.hatena.ne.jp/toritori0318/20130516/1368722444

chefに関してはこの本が詳しいです．
今回，Chefの説明多々すっ飛ばしてますが，その辺はこれを読んでおけば多分補間できるはず
入門Chef Solo - Infrastructure as Code
http://www.amazon.co.jp/dp/B00BSPH158