ようへいの日々精進XP

よかろうもん

Community Cookbooks 探訪(1)- users

要件

  • Community Cookbooks の中から一つの cookbook を選んでどんな事が書いてあるか読み解く
  • 先人たちの叡智を吸収して、cookbook 作成スキルをアップしたい

注意点

  • まずは usage を個人的な意訳メモですので、記載内容につきましては責任を負いかねますのでご了承下さい!

今日のメニュー

概要

  • "Creates users from a databag search." とあるので databag を使った node 上のユーザー管理 cookbook だと思われる
  • LWRP として任意の cookbook から利用する
  • Opscode がメンテナンスする LWRP(Light Weight Resource Providor)
    • LWRP については別途記事にしてみたい

git より clone

$ git clone git://github.com/opscode-cookbooks/users.git

cookbook の構造

$ tree users/
users/
├── CHANGELOG.md
├── CONTRIBUTING
├── LICENSE
├── README.md
├── metadata.rb
├── providers
│   └── manage.rb
├── recipes
│   ├── default.rb
│   └── sysadmins.rb
├── resources
│   └── manage.rb
└── templates
    └── default
        ├── authorized_keys.erb
        ├── private_key.erb
        └── public_key.pub.erb

5 directories, 12 files

使い方

LWRP として他の cookbook から下記のように記載して利用する
include_recipe "users"

もしくは、以下のように記載しても利用することが出来る

include_recipe "users::sysadmins"
databag に ユーザーデータを JSON データとして作成する
knife data bag create users

上記のコマンドを実行して ${chef-repo}/data_bags/users/${user_name} を作成する。以下、実際の data bag の中身。README.md から抜粋。

{
  "id": "bofh",
  "ssh_keys": "ssh-rsa AAAAB3Nz...yhCw== bofh",
}

{
  "id": "bofh",
  "password": "$1$d...HgH0",
  "ssh_keys": [
    "ssh-rsa AAA123...xyz== foo",
    "ssh-rsa AAA456...uvw== bar"
  ],
  "groups": [ "sysadmin", "dba", "devops" ],
  "uid": 2001,
  "shell": "\/bin\/bash",
  "comment": "BOFH",
  "nagios": {
    "pager": "8005551212@txt.att.net",
    "email": "bofh@example.com"
  },
  "openid": "bofh.myopenid.com"
}
制限事項

users/providers/manage.rb に以下のような記述があることから chef-solo-search がインストールされていないと chef-solo からだと利用出来ないようだ。

   if Chef::Config[:solo] and not chef_solo_search_installed?
     Chef::Log.warn("This recipe uses search. Chef Solo does not support search unless you install the chef-solo-search cookbook.")
   else

ぢゃあ、いったい何をやっているのか?

レシピ、コードを読んでみる

users/providers/manage.rb

まずは chef-solo の whyrun をサポートさせる為の記述。

 21 def whyrun_supported?
 22   true
 23 end

`action :remove` とあることからおそらくユーザー削除を定義している部分。41 行目で data_bags/users/ 以下から対象となるユーザーを id をキーとして検索し、ユーザーを削除する機能を提供している。

 37 action :remove do
 38   if Chef::Config[:solo] and not chef_solo_search_installed?
 39     Chef::Log.warn("This recipe uses search. Chef Solo does not support search unless you install the chef-solo-search cookbook.")
 40   else
 41     search(new_resource.data_bag, "groups:#{new_resource.search_group} AND action:remove") do |rm_user|
 42       user rm_user['username'] ||= rm_user['id'] do
 43         action :remove
 44       end
 45     end
 46     new_resource.updated_by_last_action(true)
 47   end
 48 endしている

`action :create`とあることからユーザーの追加を定義している部分。上記の remove 同様に data_bags/users/ 以下を検索した上で該当する id をキーとしてユーザー名を取得し、ユーザー作成の為に必要な各種設定($HOME の作成等)の機能を提供している。

 50 action :create do
 51   security_group = Array.new
 52 
- 略 -
 56     search(new_resource.data_bag, "groups:#{new_resource.search_group} AND NOT action:remove") do |u|
 57       u['username'] ||= u['id']
 58       security_group << u['username']
- 略 -
 83       # Create user object.
 84       # Do NOT try to manage null home directories.
 85       user u['username'] do
 86         uid u['uid']
 87         if u['gid']
 88           gid u['gid']
 89         end
 90         shell u['shell']
 91         comment u['comment']
 92         password u['password'] if u['password']
- 略 -
108         if u['ssh_keys']
- 略 -
119         if u['ssh_private_key']
- 略 -
131         if u['ssh_public_key']

password や ssh の authorized_keys や公開鍵等も data bag に登録されていれば、それらを元にファイルを作成しユーザーを作成してくれる機能を提供する。パスワードは暗号化する必要があるが、ドキュメントによると openssl コマンドを利用して作るようにと書かれている。

openssl passwd -1 "plaintextpassword"
users/resources/manage.rb

提供する action を定義しているようで、:create と :remove だけを提供。

 21 actions :create, :remove

それぞれの attribute の種類やデフォルトの値等が指定されている。

 28 attribute :data_bag, :kind_of => String, :default => "users"
 29 attribute :search_group, :kind_of => String, :name_attribute => true
 30 attribute :group_name, :kind_of => String, :name_attribute => true
 31 attribute :group_id, :kind_of => Integer, :required => true
 32 attribute :cookbook, :kind_of => String, :default => "users"
 33 
 34 def initialize(*args)
 35   super
 36   @action = :create
 37 end

まとめ

この cookbook に関して

感想
  • 最近、個人的話題の data bag を使った cookbook だけに少し時間を掛けて読んでみた
  • data bag の取り扱いについて理解に苦しんでいたが、この cookbook を読むことで、「こんな風に使うんだなー」ってのを改めて実感出来た
疑問
  • data bag のキーに openid が定義されているけど、いったいこれは何者?

LWRP について

LWRP 自体はちゃんと紐解いて理解したいと思うが、今回取り上げた users 以外にも幾つか存在する LWRP はレシピの中で書く resource(以下の例だと hoge の部分と action に続く :bar)を定義しているものなんだろうなーというフワッとした理解。(このあたり、来週月曜日の勉強会で聞けたら嬉しいなあ)

hoge 'foo' do
    action :bar
end