puppet 今試すなら バージョン 0.22.1 を使え、そして gem で入れるな

Posted by Gosuke Miyashita Sat, 24 Mar 2007 05:49:40 GMT

追記
これに関連した続きエントリ書きました

gem がだめなわけは、puppetrun が入らないから。(0.22.1, 0.22.2 で確認。)puppetrun 使わないなら gem で構わないけど。metadata 覗いたら、executables の中に puppetrun がない。こんな感じ。

executables:
- puppet
- puppetd
- puppetmasterd
- puppetdoc
- puppetca  

とりあえずチケットに入れておいた

あと、最新のバージョン 0.22.2 だと、以下のエラーが出る。

$ sudo puppetd --listen --no-client -v
/usr/lib/ruby/site_ruby/1.8/puppet/util/config.rb:29:in `[]': Undefined configuration parameter 'authconfig' (ArgumentError)
        from /usr/lib/ruby/site_ruby/1.8/puppet.rb:83:in `[]'
        from /usr/bin/puppetd:360

--listen オプション使うときには、/etc/puppet/namespaceauth.conf が必要で、authconfig にはこのパスがセットされるはずなんだけど、セットされていないためのエラーっぽい。これは trunk では直ってる。

もうひとつ、puppetrun 実行時のエラー。

$ sudo puppetrun --host kenny.southpark
Failed to load ruby LDAP library. LDAP functionality will not be available
/usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/core_ext/module/introspection.rb:5:in `parent': private method `split' called for :Client:Symbol (NoMethodError)
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:463:in `const_missing'
        from /usr/local/bin/puppetrun:343
        from /usr/local/bin/puppetrun:335:in `fork'
        from /usr/local/bin/puppetrun:335
kenny.southpark finished with exit code 1 

これは puppetrun に以下の一行を追加すれば直る。

require 'puppet/network/client/runner'

trunk でも直ってないようなので、こちらもチケットに入れた fix された。自分の修正内容と違うけど。

puppet の実行ファイル

Posted by Gosuke Miyashita Tue, 20 Mar 2007 15:34:33 GMT

Puppet Executables より。またもや超意訳、というかメモ。

puppet

スタンドアロンなインタプリタ。manifest ファイルを直接読んで、自ホストに適用する。あまり使うことはないと思う。

puppetca

SSLv3 証明書ハンドリングのためのコマンド。この辺参照

puppetd

puppet クライアント側で実行するデーモン。デフォルトでは、puppet サーバに対して定期的に問い合わせに行くけれど、

$ puppetd --listen --no-client

と実行することで、puppet サーバからキックされるのを待ち受ける状態になる。(サーバは後述の puppetrun を実行してキックする。)

puppetdoc

puppet ソースからドキュメントを抽出するためのツール。これもあまり使わないと思う。

puppetmasterd

puppet サーバ側で起動するデーモン。

puppetrun

puppet クライアントをサーバ側からキックする時に使うコマンド。

$ puppetrun --host hostA --host hostB

という感じで特定のクライアントのみキックできるし、

$ puppetrun --all --parallel 5

とかですべてのクライアントをキックする(ただし同時にキックするのは 5 クライアント)といったことができる。

$ puppetrun --class web

とかで web クラスのクライアントのみキックとかもできる。ただし、--all や --class は、クライアントホストを LDAP で管理している場合のみ。

うちではこれをメインに使うことになりそう。サーバの数が数百台とかあるから、クライアントから定期的にポーリングされる負荷も馬鹿にならないし、いっぺんにファイルとりにこられたりすると、とんでもないことになるので。

puppet の通信の仕組みにちょっと立ち入ってみる

Posted by Gosuke Miyashita Tue, 20 Mar 2007 15:08:03 GMT

puppet のクライアント/サーバ間通信は https + XMLRPC で、認証は SSLv3 の証明書認証が利用されています。

通常、SSLv3 で証明書認証とかいうと、CA とか、自己署名証明書とか、色々めんどくさかったりしますが、puppet はこの辺りはほとんど自動で処理してくれるので、とても楽です。

例えば、puppet サーバ側では、puppetmasterd をはじめて起動した時に、CA 関連ファイルや自己署名証明書などを、/etc/puppet/ssl 以下に勝手に作ってくれます。

$ ls -R /etc/puppet/ssl
/etc/puppet/ssl:
ca/  certs/  csr_kenny.southpark.pem  private/  private_keys/  public_keys/

/etc/puppet/ssl/ca:
ca_crl.pem  ca_key.pem  inventory.txt  requests/  signed/
ca_crt.pem  ca_pub.pem  private/       serial

/etc/puppet/ssl/ca/private:
ca.pass

/etc/puppet/ssl/ca/requests:

/etc/puppet/ssl/ca/signed:
kenny.southpark.pem

/etc/puppet/ssl/certs:
ca.pem  kenny.southpark.pem

/etc/puppet/ssl/private:

/etc/puppet/ssl/private_keys:
kenny.southpark.pem

/etc/puppet/ssl/public_keys:
kenny.southpark.pem 

あれ、CA 証明書っぽいものが二つある、と思ったら、ca/ca_crt.pem と certs/ca.pem はまったく同じものでした。

また、CA 証明書とは別に、kenny.southpark.pem というものができていますが、これはおそらく、自身が puppet クライアントになる時に利用するものと思われます。

CA 証明書の中身を覗いてみるとこんな感じ。

$ sudo openssl x509 -text -in /etc/puppet/ssl/ca/ca_crt.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 0 (0x0)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: CN=kenny.southpark
        Validity
            Not Before: Mar 20 14:29:16 2007 GMT
            Not After : Mar 18 14:29:16 2012 GMT
        Subject: CN=kenny.southpark
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:ea:83:02:5a:83:08:02:c8:bc:cd:d0:26:07:e7:
                    44:f7:a0:0e:0f:26:23:82:ba:e4:ed:d7:c8:88:c6:
                    43:b7:0a:5d:16:39:a2:6a:48:f9:8f:a5:9d:35:2f:
                    24:1e:ec:38:6b:73:0f:23:17:84:70:7e:08:08:96:
                    bd:e6:51:53:f2:fe:1d:ec:2f:d0:9a:5b:3d:ea:92:
                    8a:39:f5:ff:02:ff:6b:e4:d2:ef:9f:d2:c3:d6:35:
                    d8:5c:51:42:d9:16:59:62:c5:da:9a:9d:cd:f7:91:
                    a7:06:0b:28:8e:7f:4a:52:bc:5f:c3:5c:cb:b3:e3:
                    81:d0:1b:ca:b6:7f:73:b2:3f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Netscape Comment:
            Puppet Ruby/OpenSSL Generated Certificate
            X509v3 Basic Constraints: critical
            CA:TRUE
            X509v3 Subject Key Identifier:
            82:0D:36:AD:29:30:30:2D:CC:2D:EB:EA:F9:32:07:44:80:11:D3:E6
            X509v3 Key Usage:
            Certificate Sign, CRL Sign
    Signature Algorithm: sha1WithRSAEncryption
        e0:0b:a7:28:39:8e:09:cc:91:85:ce:13:19:c1:9b:ba:21:c3:
        d8:09:c2:ee:93:ac:8d:76:91:18:7a:31:01:fc:55:8b:84:e6:
        69:3f:f5:a3:62:ce:cc:af:87:21:42:d4:0d:ab:02:62:26:4f:
        c2:f4:a2:22:4f:52:a5:06:bd:88:4c:65:89:9e:98:4c:cb:82:
        ce:09:50:e0:4b:67:59:1e:d7:26:75:2f:6f:3d:d3:d4:92:55:
        79:06:5e:56:39:2b:15:b0:67:d9:00:79:09:37:86:1a:a1:30:
        e0:ce:e8:2b:0a:16:92:73:a3:b8:1f:16:c8:60:f7:7d:c5:24:
        09:66
-----BEGIN CERTIFICATE-----
MIICIzCCAYygAwIBAgIBADANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDDA9rZW5u
eS5zb3V0aHBhcmswHhcNMDcwMzIwMTQyOTE2WhcNMTIwMzE4MTQyOTE2WjAaMRgw
FgYDVQQDDA9rZW5ueS5zb3V0aHBhcmswgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
AoGBAOqDAlqDCALIvM3QJgfnRPegDg8mI4K65O3XyIjGQ7cKXRY5ompI+Y+lnTUv
JB7sOGtzDyMXhHB+CAiWveZRU/L+Hewv0JpbPeqSijn1/wL/a+TS75/Sw9Y12FxR
QtkWWWLF2pqdzfeRpwYLKI5/SlK8X8Ncy7PjgdAbyrZ/c7I/AgMBAAGjeTB3MDgG
CWCGSAGG+EIBDQQrFilQdXBwZXQgUnVieS9PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0
aWZpY2F0ZTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSCDTatKTAwLcwt6+r5
MgdEgBHT5jALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEFBQADgYEA4AunKDmOCcyR
hc4TGcGbuiHD2AnC7pOsjXaRGHoxAfxVi4TmaT/1o2LOzK+HIULUDasCYiZPwvSi
Ik9SpQa9iExliZ6YTMuCzglQ4EtnWR7XJnUvbz3T1JJVeQZeVjkrFbBn2QB5CTeG
GqEw4M7oKwoWknOjuB8WyGD3fcUkCWY=
-----END CERTIFICATE-----    

次にクライアント側ですが、こちらもはじめて puppetd(クライアント側で起動するデーモン)を実行した時に、秘密鍵、公開鍵、CSR を自動的に作成し、サーバに対して CSR への署名を求めることが、起動時のメッセージから読み取れます。

$ sudo /usr/sbin/puppetd --server mizzy.org --test
err: No certificate; running with reduced functionality.
info: Creating a new SSL key at /var/lib/puppet/ssl/private_keys/cartman.southpark.pem
info: Creating a new certificate request for cartman.southpark
info: Requesting certificate
warning: peer certificate won't be verified in this SSL session
notice: Did not receive certificate

サーバ側では、証明書リクエストが来ていることを、次のようなコマンドで確認できます。

$ sudo puppetca --list
cartman.southpark

これに署名するには、

$ sudo puppetca --sign cartman.southpark

と実行するだけです。これで puppet クライアント/サーバ間で無事通信できるようになります。

セキュアな通信が割りと簡単に実現できていい感じ。

puppet でファイルが変更されたら指定したコマンドを実行するレシピ

Posted by Gosuke Miyashita Mon, 19 Mar 2007 12:02:10 GMT

puppet で ファイルの配布 ができたので、次はファイルが変更されたら特定のコマンドを実行、にチャレンジ。これは FAQ にやり方書いてました。

puppet サーバで管理している /etc/httpd/conf.d/ 以下のファイルが変更されたら、puppet クライアント上のファイルを更新して httpd を再起動するレシピはこんな感じ。

class web {
  define httpd {
    $path = '/etc/httpd/conf.d'
    file { $path:
      source  => 'puppet://mizzy.org/files/etc/httpd/conf.d',
      recurse => 'true',
    }
    exec { 'httpd restart':
      command     => '/etc/init.d/httpd restart',
      subscribe   => File[$path],
      refreshonly => true
    }
  }

  httpd { 'httpd settings': }
}

node 'www.mizzy.org' {
  include web
}

/etc/httpd/cond.d/perl.conf を変更して puppet クライアント上で puppetd --test を実行するとこんな感じに。

$ sudo /usr/sbin/puppetd --server mizzy.org --test
info: Caching configuration at /var/lib/puppet/localconfig.yaml
notice: Starting configuration run
info: //www.mizzy.org/web/httpd[httpd settings]/file=/etc/httpd/conf.d/perl.conf: Removing old backup of type file
notice: //www.mizzy.org/web/httpd[httpd settings]/file=/etc/httpd/conf.d/perl.conf/source: source changed '{md5}b78c3e53dd7fef842c99f105e9e4204f' to '{md5}a28770c2cdfc4c23faa2ea41b2e67397'
info: //www.mizzy.org/web/httpd[httpd settings]/file=/etc/httpd/conf.d/perl.conf: Scheduling refresh of exec[httpd restart]
notice: //www.mizzy.org/web/httpd[httpd settings]/exec=/etc/init.d/httpd restart: Triggering 'refresh' from 1 dependencies
notice: Finished configuration run in 7.42 seconds    

ファイルが更新されてない場合はこうなる。

$ sudo /usr/sbin/puppetd --server mizzy.org --test
info: Caching configuration at /var/lib/puppet/localconfig.yaml
notice: Starting configuration run
notice: Finished configuration run in 6.80 second

puppet file server 1

Posted by Gosuke Miyashita Mon, 19 Mar 2007 10:22:17 GMT

puppet サーバ上のファイルをクライアントに配布するには、file server 機能を利用するらしい。というわけで、ドキュメント File Serving Configuration から要点を抜き出してみる。

/etc/puppet/fileserver.conf の設定

[module]
    path /path/to/files
    allow *.domain.com
    deny *.wireless.domain.com

こう設定すると、

/path/to/files/sudoers

というファイルを

puppet://server/module/sudoers

で取得できるようになる。

manifest の設定

"the Puppet language" が記述される設定ファイルを manifest と呼ぶらしい。要は puppet クライアントをどう管理するか、が記述された設定ファイルですね。(上の /etc/puppet/fileserver.conf は manifest ではない。)

puppet file server 上のファイルを配布するには、以下の様な設定を manifest に記述。

# copy a remote file to /etc/sudoers
file { "/etc/sudoers":
    mode   => 440,
    owner  => root,
    group  => root,
    source => "puppet://server/module/sudoers"
}

source がポイント。

詳細は File Serving Configuration を参照。

puppet の言語構造

Posted by Gosuke Miyashita Mon, 19 Mar 2007 04:34:13 GMT

Installation Guide を読めば、とりあえず puppet を動かすことはできるけど、やりたいことをやろうと思ってもすぐにできるわけでもない。というわけで、ドキュメントをちゃんと読んでみることにした。

まずは puppet の設定ファイルで使われている内部言語の理解から、ということで、Language Structures を超意訳してみる。

Types

puppet 設定の基本構成単位。管理されるコンピュータ上のオブジェクト(ファイルとかパッケージとか)を表すもので、あらかじめ用意されたビルトインタイプ以外にも、自ら定義することも可能。

file { "/etc/passwd": owner => root, mode => 644 } 
package { apache: install => true }

詳しくは Type Reference を参照。

Assignment

変数が利用できる。

$variable = value
$x = foo
$y = bar
$z = "$x$y"

Bringing Config files together

設定ファイルに、別の設定ファイルをインポートできる。

import "filename"

正規表現も利用可能。

import "classes/*"
import "packages/[a-z]*"

Scope

{ } によってスコープが形成される。

変数は一度割り当てられると、同一スコープ内では変更できないが、サブスコープ内では同一名の変数を割り当てることができる。

$var = value

# override $var
define testing {
    $var = othervalue
}

Components

ここでいう Components とは、自分で定義する Type のことっぽい。Components の定義と利用は以下の様な感じ。

define svnserve($source, $path, $user = false, $password = false) {
    file { $path:
        create => directory,
        owner => root,
        group => root
    }
    $svncmd = $user ? {
        false => "/usr/bin/svn co --non-interactive $source/$name .",
        default => "/usr/bin/svn co --non-interactive --username $user --password '$password' $source/$name ."
    }   
    exec { $svncmd: 
        cwd => $path,
        require => file[$path],
        creates => "$path/.svn"
    }   
}

svnserve { dist:
    source => "https://reductivelabs.com/svn",
    path => "/dist",
    user => "puppet",
    password => "password"
}

svnserve { "dist/config/apps/puppet":
    source => "https://reductivelabs.com/svn",
    path => "/etc/puppet",
    user => "puppet",
    password => "password"
}

利用する時はビルトインタイプと構文上の違いはない。

Server Classes

Class を定義してインクルードすることができる。

class  [inherits ] { ... }

継承も可能。

# really simple example
class solaris {
    file {
        "/etc/passwd": owner => root, group => root, mode => 644;
        "/etc/shadow": owner => root, group => root, mode => 440
    }
}

class solworkstation inherits solaris {
    file {
        "/etc/sudoers": owner => root, group => root, mode => 440;
        "/bin/sudo": owner => root, group => root, mode => 4111
    }
}

include solworkstation

以下の例だと、$operatingsystem の値と同名の Class と、$hostname に応じた Class がインクルードされる。

include $operatingsystem, $hostname ? {
    myhost => classA, default => classB
}

$operatingsystem とか $hostname とかは、Facterというライブラリを使ってプリセットされているみたい。

Classes vs. Components

Classes と Components の違いは以下の通り。

  • Classes はシングルトンなので、ホスト上でひとつしかないものを定義するのに利用する(OSの種類とか、特定のパッケージとかサービスとか。)
  • Components はホスト上で複数あるオブジェクト(バーチャルホストなど)を定義するのに利用する。

あと、Classes は引数を受け取れない、という違いもある。

Subclssing

Class は継承ができる。

class unix {
    file { "/etc/sudoers":
        owner => root,
        group => root,
        mode => 440
    }
}

class bsd inherits unix {
    File["/etc/sudoers"] {
        group => wheel
    }
}

Using Classes Outside of Puppet

puppet サーバで設定された Class 名が、puppet クライアントの /etc/puppet/classes.txt に保存されるので、それを外部プログラムなどから読み込んで利用したりできるよ、とうことらしい。

FC4 で yum insall した puppet の場合は、/var/lib/puppet/classes.txt に保存されていた。

Nodes

node  { ... }

特定のホストに適用する設定を割り当てる。

以下の例だと、file type はすべてのホストに割り当てられるけど、webserver class と dbserver class の中に書かれた設定は、それぞれ特定のホストにのみ割り当てられる。

class webserver { ... }
class dbserver { ... }

file { "/etc/sudoers": mode => 440 } # apply to everyone

node host1, host2 {
    include webserver
}
node host3, host4 {
    include dbserver
}

node は継承することも可能。

node base {
    include $operatingsystem
}

node kirby inherits base {
    include webserver
}

FQDN で指定する時は、シングルクォートで囲む。

node 'host.domain.com' {
    ...
}

Conditionals

条件指定が可能。

以下の例は $os が何かによって、 $owner に入る値が変わる。

define testing(os) {
    $owner = $os ? {
        sunos => adm,
        redhat => bin,
        default => root
    }
    file { "/some/file": owner => $owner }
}

以下の例は $operatingsystem が何かによって、適用する class が変わる。

case $operatingsystem {
    sunos:      { solaris {} } # apply the solaris class
    redhat:     { redhat  {} } # apply the redhat class
    default:    { generic {} } # apply the generic class
}

Reserved words

true, define, inherits, class は予約語。

Comments

sh スタイルのコメントが利用可。

puppet の node 設定ではまる

Posted by Gosuke Miyashita Sun, 18 Mar 2007 13:10:23 GMT

といったあたりを読みながら puppet を試していたのですが、node の設定ではまったのでメモ。

pueppt では、

node nag.example.com {
  include yum-rawhide
  include horde-db-pg
  include horde-nag
}

といった設定でターゲットとなるホストと、そのホストでどのようなタスクを実行するかを定義できるのですが、これで puppetmasterd を実行すると、

Syntax error at '.' at /etc/puppet/manifests/site.pp:5 

と怒られます。そこで、

node 'nag.example.com' {
  include yum-rawhide
  include horde-db-pg
  include horde-nag
}

とクォートしてあげると OK でした。最初に挙げた URL にあるチュートリアルの例ではクォートされておらず、そのままやるとはまりますのでご注意を。

追記
Language Structures を読んだら、「You can specify fully-qualified node names, but you have to single-quote the names:」ってちゃんと書いてあった。

cfengine よりも puppet がよさげ

Posted by Gosuke Miyashita Sun, 18 Mar 2007 12:33:00 GMT

I, newbie » Links Roundup 経由で puppet というシステム管理ツールを知って以来ずっと気になっていたのですが、このエントリの著者さんが OSC2007 の発表資料(PDF)で「Puppet is so sexy.」と書かれているのを見て、本気で触ってみることにしました。

puppet がどんなものかは、上記資料とか だ!日記さんのエントリ にも書かれているのですが、本家の Cfengine vs. Puppet というエントリから cfengine との違いを一部適当に意訳してみると、こんな感じです。

  • next-generation version of cfengine ということで、cfengine をベースとしながらも、より良いものを目指している。
  • リソース抽象化レイヤーにより、OS やディストリビューションの違いを意識しなくても良い。
  • タスクの実行順序を制御できる。(cfengine ではできないor難しいらしい。)
  • 設定ファイルで記述する内部言語が強力になっている。
  • type の拡張が簡単。
  • Ruby でできている。

というわけで、cfengine の導入を検討して、こんなエントリ を書いたりしてたのですが、cfengine は捨てて puppet でいこうかな、と思ってます。

emacs 用のヘルパーモード なんかも提供されているのがさらに好印象です。vim 用もあるし

それから、まだ Experimental ですが、puppetshow という Rails でできたウェブインターフェースもあるようです。

/etc/sudoers を LDAP で管理する

Posted by Gosuke Miyashita Sat, 30 Dec 2006 16:12:47 GMT

/etc/sudoers を LDAP で一元管理とかできないのかなぁ、と思っていたら、ちゃんと対応してた

利用方法はわりと簡単で、上記リンクの README.LDAP (ソースに同じものが同梱されてる)を見ればすぐわかるけど、一応ここにやったことをメモ。ほとんど README からの抜粋です。

手元の Slackware に元から入っている sudo は LDAP 対応していないので、ここからダウンロード して以下の手順でインストール。

$ ./configure --with-ldap
$ make
$ sudo make install

でもって /etc/ldap.conf に以下の記述を追加。(元々 LDAP は利用していて、基本的な設定はできているので、追加は一行だけ。)

sudoers_base   ou=SUDOers,o=southpark

LDAP 側の設定はまずスキーマの追加。

  #
  #  schema file for sudo
  #

  attributetype ( 1.3.6.1.4.1.15953.9.1.1
        NAME 'sudoUser'
        DESC 'User(s) who may  run sudo'
        EQUALITY caseExactIA5Match
        SUBSTR caseExactIA5SubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

  attributetype ( 1.3.6.1.4.1.15953.9.1.2
        NAME 'sudoHost'
        DESC 'Host(s) who may run sudo'
        EQUALITY caseExactIA5Match
        SUBSTR caseExactIA5SubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

  attributetype ( 1.3.6.1.4.1.15953.9.1.3
        NAME 'sudoCommand'
        DESC 'Command(s) to be executed by sudo'
        EQUALITY caseExactIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

  attributetype ( 1.3.6.1.4.1.15953.9.1.4
        NAME 'sudoRunAs'
        DESC 'User(s) impersonated by sudo'
        EQUALITY caseExactIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

  attributetype ( 1.3.6.1.4.1.15953.9.1.5
        NAME 'sudoOption'
        DESC 'Options(s) followed by sudo'
        EQUALITY caseExactIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

  objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
        DESC 'Sudoer Entries'
        MUST ( cn )
        MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoOption $
              description )
        )

次に sudoers 用のコンテナ ou=SUDOers, o=southpark と、デフォルト設定用の cn=defaults, ou=SUDOers, o=southpark を LDAP エントリに追加。

dn: ou=SUDOers,o=southpark
objectclass: organizationalunit
ou: SUDOers

dn: cn=defaults,ou=SUDOers,o=southpark
objectclass: top
objectclass: sudorole
cn: defaults
sudoOption: ignore_local_sudoers

sudoOption: ignore_local_sudoers があると、/etc/sudoers ファイルを見なくなる。

最後に sudo 用 role エントリを追加して準備 OK。

dn: cn=role1,ou=SUDOers,o=southpark
changetype: add
objectclass: top
objectclass: sudorole
cn: role1
sudouser: miya
sudohost: ALL
sudocommand: ALL

sudouser, sudohost, sudocommand は複数設定可。! で否定になる。なので、特定のユーザだけ許可しない、という場合には、

sudouser: ALL
sudouser: !miya

なんて書き方もできる。同様に特定のホストだけ許可しない、という場合には、

sudohost: ALL
sudohost: !kenny

とかできるし、特定のコマンドだけ許可しない、という場合には、

sudocommand: ALL
sudocommand: !/sbin/reboot

とかできる。もちろんこれらの組み合わせも OK。

あと、ユーザではなくグループで指定したい場合には

sudouser: %group

とする。(これは README.LDAP には明記されてない。/etc/sudoers の書き方から類推すればわかるけど。)

OpenSSH の公開鍵を LDAP で管理

Posted by Gosuke Miyashita Thu, 28 Dec 2006 15:49:08 GMT

OpenSSH LDAP Public key patch を試してみたのでメモ。(略して lpk patch とか言うらしい。)

SSH で公開鍵認証を行う場合、通常はホームディレクトリの .ssh/authorized_keys を参照しますが、このパッチを適用すると、authrized_keys の代わりに LDAP データベース内のユーザエントリが持つ sshPublicKey 属性を参照して、アクセスを許可するかどうかを判断する、という動作になります。

以下、試した手順です。

インストール

OpenSSH ダウンロードサイト から OpenSSH 本体を入手し、lpk サイト から lpk patch を入手しておきます。

4.3p1-0.3.7 patch が最新のようなので、本体は 4.3p1 をダウンロードしておきます。

入手したら、以下のような感じでインストールします。

$ cd openssh-4.3p1
$ patch < ../openssh-lpk-4.3p1-0.3.7.patch
$ ./configure --with-ldap
$ make
$ sudo make install

sshd の設定

/usr/loca/etc/sshd_config に以下のような設定をして、sshd を再起動します。

UseLPK yes
LpkServers ldap://myhost.mydomain.com
LpkUserDN  ou=People,dc=mydomain,dc=com

LDAP スキーマの設定

lpk patch をあてると、 ソースディレクトリに以下のような内容の openssh-lpk.schema がつくられます。

#
# $Id: openssh-lpk-4.3p1-0.3.7.patch,v 1.3 2006/04/18 15:29:09 eau Exp $
#
# LDAP Public Key Patch schema for use with openssh-ldappubkey
# Author: Eric AUGE 
# 
# Based on the proposal of : Mark Ruijter
#


# octetString SYNTAX
attributetype ( 1.3.6.1.4.1.22054.500.1.1.1.13 NAME 'sshPublicKey' 
	DESC 'MANDATORY: OpenSSH Public key' 
	EQUALITY octetStringMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )

# printableString SYNTAX yes|no
objectclass ( 1.3.6.1.4.1.22054.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
	DESC 'MANDATORY: OpenSSH LPK objectclass'
	MUST ( sshPublicKey $ uid ) 
	)

OpenLDAP であればこいつを /etc/openldap/schema の下にでも置いて、slapd.conf で include してやれば OK でしょう。

Sun のやつであれば config/schema/99user.ldif あたりに以下の記述を追加すれば OK。

objectclasses: ( 1.3.6.1.4.1.22054.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MUST ( sshPublicKey $ uid ) )
attributetypes: ( 1.3.6.1.4.1.22054.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )

LDAP ユーザエントリへの公開鍵追加

最後に LDAP のユーザエントリへ公開鍵を登録します。以下のような LDIF をつくって ldapmodify で反映させてやれば OK。

dn: uid=xxx, ou=people, o=southpark
changetype: modify
add: objectclass
objectclass: ldapPublicKey
-
add: sshPublicKey
sshPublicKey: ssh-rsa
 AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KS
 qIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z8XwSsuAoR1t86t+5dlI
 7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key

これで公開鍵認証ができるようになります。

lpk patch をあてるとソースディレクトリに以下のドキュメントがつくられますので、詳細はこれらを読むと良いんではないでしょうか。

  • README.lpk
  • lpk-user-example.txt

Older posts: 1 2 3 4