sudo の設定に LDAP を使用すると、有利な点がいくつかある。
LDAP による設定と sudoers ファイルによる設定との、 もう一つの大きな違いは、LDAP では sudo 専用のエイリアスが サポートされていないことである。
たいていの場合、sudo 専用のエイリアスは実のところ必要がない。 User_Aliases や Runas_Aliases の代わりに、Unix のグループやユーザの ネットグループが使用できる。また、Host_Aliases の代わりには、ホストの ネットグループが使える。LDAP には Unix のグループやネットグループも 格納できるので、sudo 専用のエイリアスがどうしても必要というわけでは ないのだ。
Cmnd_Aliases もまったく必要がない。一つの sudoRole エントリに 複数のユーザを登録できるからだ。複数のユーザが参照する Cmnd_Alias を 定義する代わりに、複数のコマンドを含む sudoRole エントリを一つ作成して、 そこに複数のユーザを割り当てればよい。
dn: ou=SUDOers,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
ou: SUDOers
sudo はまず最初に SUDOers コンテナ配下に
cn=default
の
エントリを捜す。見つかった場合は、複数回指定可能な
sudoOption
属性が、/etc/sudoers のグローバルな
Defaults
行と同じやり方で解析される。
以下の例では、環境変数
SSH_AUTH_SOCK
が
すべてのユーザの環境に保存されることになる。
dn: cn=defaults,ou=SUDOers,dc=example,dc=com
objectClass: top
objectClass: sudoRole
cn: defaults
description: Default sudoOption's go here
sudoOption: env_keep+=SSH_AUTH_SOCK
LDAP において /etc/sudoers の個々の「ユーザ設定」に
相当するのは、
sudoRole
エントリである。
それは以下の構成要素からできている。
上記の各構成要素が含む値は一個であるべきだが、同じタイプの構成要素が
複数回現れてもよい。sudoRole エントリは
sudoUser
、
sudoHost
、
sudoCommand
を
少なくとも一個づつ含んでいなければならない。
以下の例では、wheel グループのユーザに sudo 経由でいかなるホストでも 任意のコマンドの実行を許可している。
dn: cn=%wheel,ou=SUDOers,dc=example,dc=com
objectClass: top
objectClass: sudoRole
cn: %wheel
sudoUser: %wheel
sudoHost: ALL
sudoCommand: ALL
例を挙げてみよう。
# /etc/sudoers の場合:
# shell 以外のすべてのコマンドを許可する
johnny ALL=(root) ALL,!/bin/sh
# 次の設定は、ALL が最後にマッチするので、常にすべてのコマンドを
# 許可することになる
puddles ALL=(root) !/bin/sh,ALL
# 上記の johnny に相当する LDAP のエントリ:
# shell 以外のすべてのコマンドを許可する
dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
objectClass: sudoRole
objectClass: top
cn: role1
sudoUser: johnny
sudoHost: ALL
sudoCommand: ALL
sudoCommand: !/bin/sh
# 上記の puddles に相当する LDAP のエントリ:
# ALL が最後に指定されているが、LDAP のコードはよりパラノイア的な
# 設定になっているため、これもまた role1 と同じように動作する
# ことに注意してほしい
dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
objectClass: sudoRole
objectClass: top
cn: role2
sudoUser: puddles
sudoHost: ALL
sudoCommand: !/bin/sh
sudoCommand: ALL
もう一つの相違は、Host、User、Runas についての否定は、現在のところ 無視されるということだ。たとえば、以下に挙げるような属性は期待どおりに 動作しない。
# joe 以外の全員とマッチしないどころか、
# 誰にもマッチしない
sudoUser: !joe
# joe 以外の全員とマッチしないどころか、
# joe を含む全員にマッチしてしまう
sudoUser: ALL
sudoUser: !joe
# web01 以外のすべてとマッチしないどころか、
# web01 を含むすべてのホストにマッチしてしまう
sudoHost: ALL
sudoHost: !web01
たぶん、sudo の配布物中に三種類のスキーマが入っていると思う。 すなわち OpenLDAP サーバ用 (schema.OpenLDAP)、 Netscape ディレクトリサーバの流れを汲むサーバ用 (schema.iPlanet)、 Microsoft Active Directory 用 (schema.ActiveDirectory) の スキーマである。
OpenLDAP 用の形式にした sudo のスキーマについては、 以下の「用例」セクションにも記載しておいた。
もうひとつ注意してほしいのは、OpenLDAP ライブラリを使っている システムでは、 /etc/openldap/ldap.conf やユーザの .ldaprc ファイルで指定しているデフォルト値が使用されないことである。
すなわち、/etc/ldap.conf に明示的に記載され、かつ sudo で サポートされているオプションのみが使用される。設定オプションを 以下に大文字で列挙するが、解析されるときは大文字小文字は区別されない。
OpenLDAP:
tls_cert /etc/ssl/client_cert.pem
Netscape 由来:
tls_cert /var/ldap/cert7.db
Netscape 由来のライブラリを使う場合は、このファイルに認証局の証明書も 入れることができる。
OpenLDAP:
tls_key /etc/ssl/client_key.pem
Netscape 由来:
tls_key /var/ldap/key3.db
「用例」セクションにある
ldap.conf
のくだりも
参照してほしい。
以下の参照元が有効である。
files /etc/sudoers から sudo の設定を読み込む
ldap LDAP から sudo の設定を読み込む
なお、
[NOTFOUND=return]
の記述があると、先行する参照元に
ユーザが見つからなかった場合、参照を中断することになる。
最初に LDAP を参照し、その後で (もし存在するならば) ローカルマシン上の sudoers ファイルを調べるには、次のように指定する。
sudoers: ldap files
ローカルマシン上の sudoers ファイルをまったく無視するには、 次のようにする。
sudoers: ldap
/etc/nsswitch.conf ファイルが存在しなかったり、存在しても sudoers の 行がなかったりした場合は、次のデフォルト設定が使用される。
sudoers: files
基盤となるオペーレーティング・システムが nsswitch.conf ファイルを 使用しない場合でも、sudo は /etc/nsswitch.conf を サポートしていることに注意してほしい。
最初に LDAP を参照し、その後で (もし存在するならば) ローカルマシン上の sudoers ファイルを調べるには、次のように指定する。
sudoers = ldap, files
ローカルマシン上の sudoers ファイルをまったく無視するには、 次のようにする。
sudoers = ldap
LDAP を正式の参照元と見なし、LDAP にユーザが 見つからなかったときのみ、ローカルの sudoers を使用する。
sudoers = ldap = auth, files
上記の例において、
auth
修飾子が影響を及ぼすのは、
ユーザを照合するときだけであることに注意してほしい。
Defaults
エントリについては、LDAP と
sudoers の両方が参照される。
/etc/netsvc.conf ファイルが存在しなかったり、存在しても sudoers の 行がなかったりした場合は、次のデフォルト設定が使用される。
sudoers = files
# URI か host:port の組み合わせを一つ以上指定する。 # どちらも指定されていない場合、sudo は localhost と 389 番 # ポートを使用する。 # #host ldapserver #host ldapserver1 ldapserver2:390 # # host がポートなしで指定されている場合のポート番号。 # デフォルトは 389 である。 #port 389 # # URI の指定は、host と port による指定に優先する。 uri ldap://ldapserver #uri ldaps://secureldapserver #uri ldaps://secureldapserver ldap://ldapserver # # LDAP サーバに接続しようとしているときの、秒単位の待ち時間。 bind_timelimit 30 # # LDAP の参照を行っているときの、秒単位の待ち時間。 timelimit 30 # # 必ず設定すること。さもないと、sudo は LDAP を無視することになる。 sudoers_base ou=SUDOers,dc=example,dc=com # # LDAP を参照したとき、sudo 設定のマッチングについて詳細情報を # 表示する。 #sudoers_debug 2 # # LDAP の操作を行う者の認証情報 (設定する、しないは任意)。 #binddn <who to search as> #bindpw <password> #rootbinddn <who to search as, uses /etc/ldap.secret for bindpw> # # LDAP プロトコルのバージョン。デフォルトは 3 である。 #ldap_version 3 # # LDAP 接続を暗号化したいなら、on にする。 # 通例、ポートを 636 (ldaps) にすることも必要。 #ssl on # # ポート 389 を使用し、バインド操作のために認証情報が # 送信される前に、暗号化セッションに切り替えたい場合に設定する。 # これをサポートしているのは、OpenLDAP のような start_tls 拡張に # 対応している LDAP サーバだけである。 #ssl start_tls # # 以下の TLS オプションを付けることで SSL/TLS 接続を微調整できる。 # #tls_checkpeer yes # サーバの SSL 証明書を確認する。 #tls_checkpeer no # サーバの SSL 証明書を確認しない。 # # tls_checkpeer を有効にするときは、 tls_cacertfile か # tls_cacertdir のどちらかを指定すること。tls_cacertfile や # tls_cacertdir は OpenLDAP 使用時のみ使える。 # #tls_cacertfile /etc/certs/trusted_signers.pem #tls_cacertdir /etc/certs # # /dev/random がないシステムでは、下記の設定を PRNGD、あるいは # EGD.pl と一緒に使用すれば、暗号セッション用の鍵を生成するための # 乱数プールの種を供給できる。このオプションが使えるのは、 # OpenLDAP を使用しているときだけである。 # #tls_randfile /etc/egd-pool # # 使用する暗号を限定することができる。どの暗号が使えるかに # ついては、SSL の文書を参照してほしい。このオプションが # 使えるのは、OpenLDAP を使用しているときだけである。 # #tls_ciphers <cipher-list> # # sudo は LDAP サーバと交信するときに、クライアントの証明書を # 提示することができる。 # 注意: # * 両方の行を同時に有効にすること。 # * キーファイルをパスワードでプロテクトしてはいけない。 # * キーファイルが読めるのは root だけにするのを忘れずに。 # # OpenLDAP の場合: #tls_cert /etc/certs/client_cert.pem #tls_key /etc/certs/client_key.pem # # SunONE や iPlanet LDAP の場合: # こちらの場合は、tls_cert や tls_key で指定するのは、 # ディレクトリでもよく、cert や key ファイルそのもののパスでもよい。 # 前者の場合、ディレクトリ中のファイルは、既定の名前 (たとえば、 # cert8.db と key4.db) でなければならない。もっとも、ファイルの # パスを指定した場合は、バージョン 5.0 の LDAP SDK にはバグが # あるので、ファイル名によってはうまく動作しないことがある。 # この理由から、tls_cert や tls_key には、ファイル名ではなく、 # ディレクトリを指定する方をお薦めする。 # # tls_cert で指定した証明書のデータベースには、認証局の証明書と # クライアントの証明書が、どちらか一方だけ入っていてもよく、 # 両方入っていてもよい。クライアントの証明書が入っている場合は、 # tls_key も指定するべきである。 # 後方互換のため、tls_cert のかわりに sslpath を使うこともできる。 #tls_cert /var/ldap #tls_key /var/ldap # # LDAP に SASL 認証を使用する場合 (OpenSSL) # use_sasl yes # sasl_auth_id <SASL username> # rootuse_sasl yes # rootsasl_auth_id <SASL username for root access> # sasl_secprops none # krb5_ccname /etc/.ldapcache
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 )
attributetype ( 1.3.6.1.4.1.15953.9.1.6
NAME 'sudoRunAsUser'
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.7
NAME 'sudoRunAsGroup'
DESC 'Group(s) impersonated 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 $ sudoRunAsUser $
sudoRunAsGroup $ sudoOption $ description )
)