さくらVPSの初期設定をChef Soloでやってみた〜サードパーティcookbookの使い方〜

さくらVPSの初期設定をChef Soloでやってみた〜サードパーティcookbookの使い方〜

Chef Soloの正しい始め方 | tsuchikazu blogがどういうわけかgoogleさんに好かれているので、続編を書きました。入門Chef Soloと正しい始め方を読んで、じゃあ実際に色々やってみようかな。とはいえ、チュートリアル的なことでなく、もうちょっと実践的なことをして理解を深めたい。このような人を対象に、さくらVPSの初期設定を題材に、Chef Soloを説明していきます。

この記事でやることは以下のとおりです

  • 一般ユーザの作成
  • 鍵認証の設定
  • sudo有効化
  • sshの設定
  • iptablesの設定

さくらVPSでよく行われる初期設定で、これを実施すればrootが乗っ取られてヤバイことになった。とかそういう事態は防げるはずです。AWSのEC2ですと、デフォルトで設定される内容になっていますので、さくらVPSをEC2レベルまでセキュリティ向上させるのを目標にします。

前提

自分のローカルの環境は以下のとおりです。

$ ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin11.4.0]
$ gem list | grep chef
chef (11.6.0)
$ gem list | grep knife
knife-solo (0.3.0)
$ gem list | grep berks
berkshelf (2.0.9)

今回、設定するさくらVPSのサーバ環境はCentOS 6.4で進めました。おそらくVagrantで作ったVM等でも問題なく動作するはずです。

セットアップ

早速、Chef Soloを実行するためのベースとなるリポジトリを、knife solo initコマンドを使って作成します。

$  knife solo init vps-start-chef-cookbooks
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...
Setting up Berkshelf...

$ cd vps-start-chef-cookbooks/

今回、サードパーティのcookbookの管理にはberksを使用します。berksのコマンドを使って、berksに必要なファイルを作成します。

$ berks init
      create  Berksfile
      create  Thorfile
    conflict  .gitignore
       force  .gitignore
    conflict  Gemfile
       force  Gemfile
      create  Vagrantfile
Successfully initialized

ローカルの準備は整ったので、次にサーバ側の設定を行います。さくらVPSの初期状態ですと、Chefがインストールされておらず、Chef Soloが実行できる状態ではありません。knife solo prepareコマンドを使用してChefをサーバにインストールします。
(VPSのIPが133.242.191.168という設定で進めます。自分の環境に合わせてIPを変更してください)

$ knife solo prepare root@133.242.191.168
Bootstrapping Chef...
Enter the password for root@133.242.191.168:
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
101  6790  101  6790    0     0   7495      0 --:--:-- --:--:-- --:--:-- 20764
Downloading Chef 11.6.0 for el...
Installing Chef 11.6.0
warning: /tmp/tmp.Wjdkgw9l/chef-11.6.0.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
Preparing...                ########################################### [100%]
   1:chef                   ########################################### [100%]
Thank you for installing Chef!
Generating node config 'nodes/133.242.191.168.json'...

これで準備は完了です。

一般ユーザ作成&鍵認証&sudo有効化

初期状態ではrootユーザーしか存在しないため、通常作業用に一般ユーザーを作成します。

今回はサードパーティで用意されているcookbookを利用しながらChefの仕組みを理解していくために、積極的に採用していきます。やりたいこと + cookbook でググったり、Opscode Communityで検索すると、やりたいことが出来るcookbookが見つかるかと思います。
今回ユーザの追加用のcookbookとして、fnichol/chef-user · GitHubを利用します。まずサードパーティのcookbookを使うには、cookbookをダウンロードしてくる必要があります。そのためにはBerksfileファイルにダウンロードするcookbookを追加し、berks installコマンドを実行します。サードパーティのcookbookはcookbooksディレクトリに置いておく慣習があるため--pathオプションでcookbooksを指定しておきましょう。

$ vim Berksfile
site :opscode
# この一行を追加 
cookbook 'user'

$ berks install --path cookbooks
Using user

さて、どうやってこれを利用していくかですが、サードパーティのcookbookには大きく3つあるようです。(この分類は自分が勝手に呼んでいるだけで、非公式です)

  • LWRP型・・・recipeで何もせずに、LWRPを提供するもの(例:fnichol/chef-user · GitHub
  • Attribute型・・・recipeが提供され、Attributeが柔軟に定義されているもの(例:opscode-cookbooks/mysql · GitHub
  • ハイブリッド型・・・LWRP型とAttribute型の両方が提供されているもの

まずはLWRP型ですが、これはrecipeには何も書かれておらずLWRP(Lightweight Resources and Providers)だけが書かれているcookbookです。そもそもLWRPというのは、独自のResourceを定義する機能です。LWRPの細かい説明は省略しますが、要は標準で提供されているResourceより、便利になった独自Resourceが使えるようになるcookbook。それが、LWRP型です。fnichol/chef-user · GitHubはLWRP型のcookbookですので、実際に使用してみましょう。(Attribute型は後述します)

READMEを読むと、user_accountというLWRPが使うことが出来ることがわかります。標準のuserResourceとの違いは、SSHの公開鍵をauthorized_keysに置けるところです。それではuser_accountを呼び出すためのcookbookを作って、recipeを編集していきます。

$  knife cookbook create site_user -o site-cookbooks/ 
** Creating cookbook site_user
** Creating README for cookbook: site_user
** Creating CHANGELOG for cookbook: site_user
** Creating metadata for cookbook: site_user

recipeを編集しましょう。tsuchikazuとユーザを作成してみます。ssh_keysにはあらかじめ作成しておいた公開鍵を指定します。

$ vim site-cookbooks/site_user/recipes/default.rb
# LWRPの呼び出し
user_account 'tsuchikazu' do            # tsuchikazuというユーザを
  action :create                        # 作成するよ
  ssh_keys  ['ssh-rsa AAAAB3NzaC....']  # authorized_keysはこれで
end

今、追加したrecipeを適用するために、knife solo prepareを実行した時に作成されているJSON ファイル nodes/ipaddress.jsonrun_list にrecipeを追加しましょう。この時に、サードパーティのrecipeを先に書いておくことで、その後に指定したrecipeでサードパーティが提供しているLWRPを使用することが出来るようになります。

$ vim nodes/133.242.191.168.json
{
  "run_list":[
    "recipe[user]",  
    "recipe[site_user]"
  ]
}

これで、userを追加する準備が整いました。さらに今追加しようとしているuserでsudoコマンドを使えるようにします。普通にやるとするとvisudoコマンドでsudoresファイルを編集するでしょうか。それをChefでやるために、サードパーティのcookbookであるopscode-cookbooks/sudo · GitHubを使うことにします。先ほどのfnichol/chef-user · GitHubと同様にberksopscode-cookbooks/sudo · GitHubをダウンロードします

$ vim Berksfile
# この1行を追加
cookbook 'sudo'

$ berks install --path cookbooks
Using user (0.3.0)
Using sudo (2.0.4)

さて、このサードパーティcookbookを利用してsudoの設定を行いたいのですが、opscode-cookbooks/sudo · GitHubは、まだ説明していないAttribute型に分類されます。Attribute型というのはrecipeが記述されていますが、重要部分がAttributeが使用されており、そのAttributeの値を上書きすることで、思い通りにrecipeを実行するというものです。opscode-cookbooks/sudoでいうと、sudo/recipes/default.rb at master · opscode-cookbooks/sudo · GitHubのrecipeをみると、Attributeが使用されているのがわかるかと思います。LWRP型のrecipe、chef-user/recipes/default.rb at master · fnichol/chef-user · GitHubと見比べると一目瞭然です。

では、実際にJSONファイルでAttributeを指定しましょう。指定するAttributeはREADMEを見て、調べましょう。ここでは、tsuchikazuユーザをパスワード無しでsudo出来るような設定にしてあります。

$ vim nodes/133.242.191.168.json
{
  "run_list":[
    "recipe[user]",  
    "recipe[site_user]",  
    "recipe[sudo]"
  ],   
  "authorization": {
    "sudo": {
      "users": ["tsuchikazu"],   
      "passwordless": "true"
    }
  }
}

これでユーザ作成の準備完了です。実際にChef Soloを実行してみましょう。passwordを何度も聞かれますが、めげずに入力してください。

$ knife solo cook root@133.242.191.168

実際に作成されたか、試してみてください。PWなしでログイン出来るはずです。

$ ssh tsuchikazu@133.242.191.168

SSHの設定、iptablesの設定

先ほどのユーザ作成でサードパーティの使い方は説明したので、復習のために設定を進めます。
まずはSSHの設定ということで、以下の設定をします。

  • rootログインの禁止
  • パスワードログインの禁止

この設定をopscode-cookbooks/openssh · GitHubのcookbookを使ってやってみます。このcookbookはAttribute型なため、JSONファイルでAttributeを指定します。

$ vim Berksfile
# この1行を追加
cookbook 'openssh'

$ berks install --path cookbooks
Using user (0.3.0)
Using sudo (2.0.4)
Using openssh (1.1.4)

$ vim nodes/133.242.191.168.json
{
  "run_list":[
    ....(省略)
    "recipe[openssh]"
  ],   
  ....(省略)
  "openssh": {
    "server": {
      "permit_root_login":"no", 
      "password_authentication":"no"
    }
  }
}

これでSSHの設定は完了です。
次にiptablesの設定ということで、以下の設定をします。

  • SSH 22番とHTTP 80番とHTTPS 443番のポートを開ける

次にiptablesの設定をdcrosta/cookbook-simple-iptables · GitHubのcookbookを利用して、行います。dcrosta/cookbook-simple-iptables · GitHubはLWRP型のcookbookなので、cookbookを作成してrecipeからLWRP呼び出します。

$ vim Berksfile
# gitからもinstall出来ます
cookbook 'simple_iptables', git:"git://github.com/dcrosta/cookbook-simple-iptables.git"

$ berks install --path cookbooks

$ knife cookbook create site_simple_iptables -o site-cookbooks/

$ vim site-cookbooks/site_simple_iptables/recipes/default.rb
---- default.rb
# Exampleをコピりました
# Reject packets other than those explicitly allowed
simple_iptables_policy "INPUT" do
  policy "DROP"
end

# The following rules define a "system" chain; chains
# are used as a convenient way of grouping rules together,
# for logical organization.

# Allow all traffic on the loopback device
simple_iptables_rule "system" do
  rule "--in-interface lo"
  jump "ACCEPT"
end

# Allow any established connections to continue, even
# if they would be in violation of other rules.
simple_iptables_rule "system" do
  rule "-m conntrack --ctstate ESTABLISHED,RELATED"
  jump "ACCEPT"
end

# Allow SSH
simple_iptables_rule "system" do
  rule "--proto tcp --dport 22"
  jump "ACCEPT"
end

# Allow HTTP, HTTPS
simple_iptables_rule "http" do
  rule [ "--proto tcp --dport 80",
         "--proto tcp --dport 443" ]
  jump "ACCEPT"
end
---- default.rb

$ vim nodes/133.242.191.168.json
{
  "run_list":[
    ....(省略)
    "recipe[simple_iptables]", 
    "recipe[site_simple_iptables]" 
  ],   
  ....(省略)

最後にChef Soloを実行してみましょう。ユーザには先ほど作成したユーザを指定してみてください。無事設定が反映されているでしょうか。

$ knife solo cook tsuchikazu@133.242.191.168

まとめ

これで簡単なサードパーティのcookbookを利用できるようになったはずです。サードパーティのcookbookを利用する際のコツは、とにかくREADMEを読んでやってみて、エラーになったらcookbookを読む。しかないかなと。READMEもcookbookによっては、適当で不親切なものがありますので、直接ソースを読むかサードパーティを使わないという手を取るのもいいかと思います。ちなみに、自分はこうやって使っているというだけですので、間違い等あれば指摘していただきたいです。

今回、サードパーティのcookbookを使って初期設定を進めました。なぜサードパーティを使ったかというと、naoyaさんの入門書を皮切りにChef入門記事が量産されました。Chef Soloの正しい始め方 | tsuchikazu blogこれもその1つです。が、それらを読んでも、サンプルを実行するぐらいで私は自前でrecipeなどを書ける気に全くなりませんでした。そこで、次にやったのが今回紹介したサードパーティcookbookを使いまくる。ということです。今回紹介したものに加え、nginxやmysqlなど色々なcookbookを読みながら使いまくりました。すると自然とLWRPやAttribute、Recipeの書き方が少しずつわかってきた(気がした)のです。
ということで、入門の次のステップとしてサードパーティのcookbookの使い方を書きました。今回作成したChefリポジトリはtsuchikazu/vps-start-chef-cookbooksで公開していますので、参考になれば幸いです。