Chefを使ってみる - 実践編(1) ユーザを作成する

* Chef/knife-soloを利用する
* cookbook名は「add_user」とする
* 作成するユーザの情報はdatabagへ格納する
* 鍵認証ssh接続に備え、authorized_keyを配置する


# data bagツールをインストールし、ユーザ情報を格納する
## data bag インストール
まずはdata bagツールをインストールし、利用できるようにする。
<pre>
\# gem install knife-solo_data_bag
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
Done installing documentation for knife-solo_data_bag after 0 seconds
1 gem installed
</pre>

## data bag を作成する
作成するユーザ情報をしまうための箱を準備する
コマンドを実行するとdata_bagsディレクトリの下に「users」ディレクトリが作成される
<pre>
$ knife solo data bag create users
$ ls data_bags/
users
</pre>

## 作成するユーザの情報を作成し、保存する
ユーザ情報をjsonに記載して、data_bags/users配下へ保存する
コマンドを実行するとそのまま編集モードになるので、編集実施
<pre>
$ export DISPLAY=vi
$ knife solo data bag create users hogehoge
</pre>

```json:hogehoge.json
{
  "id": "hogehoge",
  "groups": [
    {
      "name": "hogehoge",
      "gid": 2001
    }
  ],
  "users": [
    {
      "name": "hogehoge",
      "home": "/home/hogehoge",
      "shell": "/bin/nologin",
      "uid": 2001,
      "gid": 2001
    }
  ]
}
```
作成するユーザ分同様にjsonを作成する

# Cookbookを作成し、Recipeなどを編集していく
## cookbookを作成する
<pre>
$ knife cookbook create add_user -o site-cookbooks
DL is deprecated, please use Fiddle
ffi-yajl/json_gem is deprecated, these monkeypatches will be dropped shortly
** Creating cookbook add_user
** Creating README for cookbook: add_user
** Creating CHANGELOG for cookbook: add_user
** Creating metadata for cookbook: add_user
</pre>

## Recipeを編集する
* ユーザのホームディレクトリは/home<br />
ただし、/homeは/var/homeへのシンボリックリンク<br />
なので、/var/homeを作成し、/homeのシンボリックリンクを作成する
* knife-solo実行ユーザは、予め「/opt/home」をホームディレクトリとして作成済み

```rb:site-cookbooks/add_user/recipes/default.rb
# /var/homeディレクトリ作成
# /var/homeの存在確認をnot_ifにて実施
directory "/var/home" do
  owner "root"
  group "root"
  mode  "0777"
  action :create
  not_if { File.exists? "/var/home" }
end

# /home削除
# /homeの存在確認をnot_ifにて実施
directory "/home" do
  action :delete
  not_if "test -L /home"
end

# シンボリックリンクを作成
# /homeの存在確認をnot_ifにて実施
link "/home" do
  to "/var/home"
  not_if "test -L /home"
end


# ユーザ作成
# data_bag/users配下にあるjsonすべてを読みに行く
data_ids = data_bag('users')

data_ids.each do |id|
  item = data_bag_item('users',id)

 item['groups'].each do |g|
    group g['name'] do
      gid g['gid']
      action :create
    end
  end

  item['users'].each do |u|
    user u['name'] do
      home  u['home']
      shell u['shell']
      password u['password']
      uid   u['uid']
      gid   u['gid']
      supports :manage_home => true
      action :create
    end
    directory "/#{u['home']}/.ssh" do
      owner u['uid']
      group u['gid']
      mode  '0700'
      action :create
    end
    # ssh_authorized_keys を配置
    # site-cookbooks/add_user/files/default/に鍵を配置しておく
    cookbook_file "/#{u['home']}/.ssh/authorized_keys" do
      source "#{u['name']}_authorized_keys"
      action :create
      owner  u['uid']
      group  u['gid']
      mode   '0600'
    end
  end
end

# wheelグループへのユーザ追加
# attributeへ対象ユーザを記載する
group 'wheel' do
  group_name 'wheel'
  members node['add_user']['wheel']
  action :modify
end
```

## authorized_keyの配置
authrize_keyを利用しないユーザの場合でも、空ファイルを配置しておく
<pre>
$ ls site-cookbooks/add_user/files/default/
hogehoge_authorized_keys  fugafuga_authorized_keys
</pre>

## Attributeへ変数定義
wheelグループへ追加するユーザを外出し変数として設定する

```rb:site-cookbooks/add_user/recipes/default.rb
default['add_user']['wheel'] = ['root','hogehoge','fugafuga']
```

# nodeオブジェクトを編集し、実際に試してみる
## nodeオブジェクト編集

```json:nodes/Test-hogehoge.json
{
    "run_list": [
      "recipe[add_user]"
    ]
}
```

# 実行してみる
<pre>
$ knife solo cook -i ~/.ssh/usr-fugafuga.pem usr-fugafuga@remote-hogehoge
</pre>
usr-fugafugaがプロビジョニング用のユーザ
クライアント側ではユーザの作成とsudo設定が完了している