data_bagsの用途について
こんにちは。小宮です。
data_bagsについて内部的に解説する必要が生じたのでこちらにも書いておきます。
最近のdata_bagsの活用方法は以下のとおり
1.LDAPで管理していないシステム用途のOSユーザ情報をロードしてレシピで追加
2.SSL証明書の格納とレシピからロードしてtemplateで設定
3.ntpサーバの情報のロードとtemplateで設定
4.awsのクレデンシャル情報を管理して各種スクリプトへ埋め込み
5.mysqlやldapなどのパスワードなどアカウント情報の管理
6.roleとenvironmentに収まりきらないnginxやapacheのvhostやupstream等の情報の管理
7.gangliaのhead_nodeやcluster_nameの情報の管理
0.下準備的な解説
※前提条件としてchef-soloの場合”knife-solo_data_bag”というgemが必要なので入れる。
(gem listでなければgem installかbundlerで入れてください)
格納方法と確認方法
暗号化しない場合、viなど任意のエディタで編集OK
chef-repository/data_bags/任意のディレクトリ名/任意のファイル名.json
をつくる。
中身はjsonの規則にのっとっている必要があるので、シンタックスをjson_verifyでCHK。
cat data_bags/dirname/filename.json |json_verify
で、JSON is valid と出るのを確認する
暗号化する場合、
まずEDITORの環境変数を~/.bashrcなりに設定しておく必要があるのと暗号化用の鍵を作って設定しておく必要がある。
(※鍵は案件ごとに異なるイメージで、.gitignoreに書いとく必要があります。
流出厳禁かつ無くすとデータが見えなくなります。)
1 2 3 4 5 6 |
export EDITOR=vi vi .chef/knife.rb ------コメントを外す--------------------- encrypted_data_bag_secret "data_bag_key" ----------------------------------------- |
※コメント外すと鍵指定しなくてもknifeコマンドでcreateした場合常に暗号化される
ゆえに暗号化せず扱いたいデータファイルはviで作るかコメントインしてから作る必要有
鍵が必要なら作る
(※.chef/knife.rbの相対パスはchefリポジトリ直下を意味します)
1 2 3 4 5 6 7 |
openssl rand -base64 512 > data_bag_key knife solo data bag create dirname filename # 作成(※既存は上書きされる) knife solo data bag edit dirname filename # ファイルをエディタで編集 knife solo data bag show dirname filename # jsonの中身を表示 knife solo data bag list # ディレクトリ一覧表示 |
・注意するべきこと
→bashやexecuteリソースは極力使うべきではない。templateリソースつかってください。
bashでsedるとdata_bagsから変数に入れた特殊文字が展開されて意図しない値が入ったりします
もうひとつ、sedると毎度毎度同じsedをする必要が生じるなど冪等にならないです。
1.LDAPで管理していないシステム用途のOSユーザ情報をロードしてレシピで追加
これは大したことしてないのでポインタで失礼します
Chefで既存手順のレシピを書く2(ユーザ作成) | DEVLAB
暗号化はしていないパターン。(パスワードはあらかじめ暗号化した文字列を入れる)
個人ユーザはLDAP管理でchefでは扱うのはldapのclient設定ファイル配布等です
2.SSL証明書の格納とレシピからロードしてtemplateで設定
apacheとnginxでやっておりますがnginxの場合についてを記載します。
ssl証明書の格納方法についてですが、改行コードを以下のように文字列に変換したものを貼ります。
証明書と鍵なのでもちろん暗号化で入れてロードしております。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
cat cert.pem|perl -pe 's/n/n/g' knife solo data bag create ssl jenkins knife solo data bag edit ssl jenkins knife solo data bag show ssl jenkins { "id": "jenkins", "crt": "-----BEGIN CERTIFICATE-----nMIIDd~略~", "key": "~略~", "passkey": "~略~", "passphrase": "hogehoge" } |
レシピ側でロードする方法について(一部抜粋)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# cat site-cookbooks/nginx/recipes/nginx_ssl_client.rb --- # data_type(≒role)名と環境名を変数に入れてdataファイルの名前にしてます #role = ("#{node.roles}"[/[w_-]+/]) environment = ("#{node.environment}"[/w+/]) data_type = node['nginx']['data_type'] sslclientconf_type = node['nginx']['sslclientconf_type'] datafile = "#{data_type}_#{environment}" # 鍵の名前などを変数に定義(これはrole等のアトリビュートからロードされます sslkeyfile = node['nginx']['sslkey1'] sslcrtfile = node['nginx']['sslcrt1'] clientcrtfile = node['nginx']['clientcrt'] clientcrlfile = node['nginx']['clientcrl'] sslkeydir = '/etc/nginx' # data_bagsの暗号化されたデータをロードして変数に定義してます ssl = Chef::EncryptedDataBagItem.load("ssl", "#{datafile}") sslcrtdata = ssl["crt"] sslkeydata = ssl["key"] clientcrtdata = ssl["clientcrt"] #clientcrldata = ssl["clientcrl"] # data_typeでif分岐してるレシピです if "#{data_type}" == "" #~略~ else # templateリソースを使うことで冪等性を保つことができます template "#{sslkeydir}/#{sslcrtfile}" do notifies :restart, 'service[nginx]' source "sslcrtfile.erb" variables({ :sslcrtdata => sslcrtdata }) end template "#{sslkeydir}/#{sslkeyfile}" do notifies :restart, 'service[nginx]' source "sslkeyfile.erb" variables({ :sslkeydata => sslkeydata }) end template "#{sslkeydir}/#{clientcrtfile}" do notifies :restart, 'service[nginx]' source "clientcrtfile.erb" variables({ :clientcrtdata => clientcrtdata }) end --- templateファイルがどうなっているかといいますと # cat site-cookbooks/nginx/templates/default/sslcrtfile.erb <%= @sslcrtdata %> # cat site-cookbooks/nginx/templates/default/sslkeyfile.erb <%= @sslkeydata %> # cat site-cookbooks/nginx/templates/default/clientcrtfile.erb <%= @clientcrtdata %> |
variablesで@になってる箇所にdata_bagsからロードして変数に入ってる値をセットできます。
3.ntpサーバの情報のロードとtemplateで設定
5.mysqlやldapなどのパスワードなどアカウント情報の管理
これもポインタで失礼をば。
chef-soloのレシピのカスタマイズの記録 | DEVLAB
ご参考まで。
4.awsのクレデンシャル情報を管理して各種スクリプトへ埋め込み
もちろん暗号化して入れます。
ssl証明書の場合とロード方法も埋め込む方法もあまり変わらないので省略します。
作成・編集・確認は以下のように。
1 2 3 4 5 6 7 8 9 10 11 |
# knife solo data bag create awskeys deploy # knife solo data bag edit awskeys deploy # knife solo data bag show awskeys deploy { "id": "deploy", "aws_access_key_id": "Axxxxxxxxxxxxxxxxxx", "aws_secret_access_key": "oxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "region": "us-xxxx-2" } |
こんなかんじでいれて、ロードする方法はたとえば以下のようにしています。(設置せずにスクリプトに変数渡してます)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
cookbook_file "/usr/local/sbin/renamehost" do source "renamehost" owner 'root' group 'root' mode 0750 end ohai "reload" do plugin "hostname" end # 環境から対応するAWSアカウントを取得する env_rank = data_bag_item("master_data", "env_rank") rank_awsaccount = data_bag_item("master_data", "rank_awsaccount") environment = node.chef_environment rank = env_rank[environment] awsaccount = rank_awsaccount[rank] # アカウントに対応する認証情報を取得する awscredential = Chef::EncryptedDataBagItem.load("awskeys", "deploy_#{awsaccount}") aws_access_key_id = awscredential["aws_access_key_id"] aws_secret_access_key = awscredential["aws_secret_access_key"] aws_region = awscredential["region"] role = ("#{node.roles}"[/[\w_-]+/]) bash "exec-renamehost" do not_if { node[:hostname] =~ /^#{role}/ } notifies :reload, "ohai[reload]", :immediately notifies :restart, "service[rsyslog]", :immediately code <<-EOC /usr/local/sbin/renamehost `echo #{aws_access_key_id} #{aws_secret_access_key} #{aws_region}` EOC end include_recipe "base_setting::hosts" |
6.roleとenvironmentに収まりきらないnginxやapacheのvhostやupstream等の情報の管理
レシピ的には以下のとおりです
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
ngxdata = data_bag_item('nginx',"#{datafile}") servername = ngxdata['servername1'] upstream = ngxdata['upstream1'] upstreamport = ngxdata['upstreamport'] template "/etc/nginx/conf.d/ssl.conf" do source "#{role}/ssl.conf.erb" path '/etc/nginx/conf.d/ssl.conf' backup 5 owner 'root' group 'root' mode '0644' action :create notifies :restart, 'service[nginx]' variables({ :servername1 => servername, :upstream1 => upstream, :upstreamport => upstreamport }) end |
jsonファイルは特に暗号化していません(gitで確認しづらいですし)
1 2 3 4 5 6 7 8 9 10 |
# cat data_bags/nginx/nginx-hoge_test1.json ---- { "id": "nginx-hoge_test1", "servername1": "exsample.hoge.net", "upstream1": "internal-ELB-int-hoge-test1-xxxxxxx.us-xxxx-2.elb.amazonaws.com", "upstreamport": "80" } ---- |
roleもenvironmentも多数あって、どっちかに収まりきらないという時にはdata_bagsに入れるしかなさげです。
7.gangliaのhead_nodeやcluster_nameの情報の管理
これは6とあんまり変わらないので省略します
参考:
databags を使ってみた一部始終(1) – ようへいの日々精進
[chef] data bag活用法 | ITインフラ雑記帳
Chefで公開したくないJSONデータを暗号化するためにDataBagsを利用してみた記録 – さよならインターネット
ご参考まで。読んでいただいてありがとうございました。