基本的には、 OpenLDAP documentation の The Proxy Cache Engine で説明されている設定に加えて、anonymous proxyとなるように設定するだけです。
# moduleload back_ldap moduleload pcache include /etc/openldap/schema/core.schema include /etc/openldap/schema/cosine.schema include /etc/openldap/schema/inetorgperson.schema include /etc/openldap/schema/nis.schema # schema for MS ActiveDirectory # include /etc/openldap/schema/ad.schema conn_max_pending 1000 #logfile /var/log/openldap/slapd.log pidfile /var/run/openldap/slapd.pid argsfile /var/run/openldap/slapd.args # # loglevel stats sizelimit unlimited limits * size.pr=0 size.prtotal=none # anonymous readonly access readonly on access to * by * read # # LDAP proxy # database ldap conn-ttl 3600 idle-timeout 600 suffix "dc=work,dc=hanabusa,dc=net" rootdn "dc=work,dc=hanabusa,dc=net" uri "ldap://ldap1.work.hanabusa.net ldap://ldap2.work.hanabusa.net" # use MS Active Directory global catalog # uri "ldap://ldap1.work.hanabusa.net:3268 ldap://ldap2.work.hanabusa.net:3268" # auth with Kerberos idassert-authzFrom dn.regex:.* idassert-bind bindmethod=SASL saslmech=GSSAPI mode=none # cache config overlay pcache pcache hdb 100000 1 1000 300 pcacheAttrset 0 c cn displayName mail member objectClass telephonenumber #pcacheAttrset 0 c cn displayName mail member objectClass sAMAccountName sAMAccountType telephonenumber pcacheTemplate (cn=) 0 3600 #pcacheTemplate (sAMAccountName=) 0 3600 #pcacheTemplate (&(cn=)(sAMAccountName=)) 0 3600 # hdb config dbnosync cachesize 1000 index objectClass eq index cn,sn,mail pres,eq,sub #index sAMAccountName eq #directory /var/lib/ldap/cache
上記のslapd.confの設定は、domain controllerに対してLDAP接続する際に Kerberos認証を行うようにしています。 LDAP専用のuserを用意しても構いませんが、 Kerberosを使ったsingle sign on を行っていれば既にcomputer accountが発行されています。 このcomputer accountを使ってLDAPの認証を行ってみます。
まず、klistで/etc/krb5.keytabの中身を確認して、 computer accountが存在することを確認しましょう。 以下のようにklist -kを走らせると、[email protected] が存在することがわかります。 この hostname + $ のものがcomputer accountです。 (使っている暗号種類の数だけ同じ名前の行が出てきます)
# klist -k 2 host/[email protected] ... 2 host/[email protected] ... 2 [email protected] ... 2 HTTP/[email protected] ... #
試しに、kinitを使ってcomputer accountに対する Kerberos TGT (Ticket Granting Ticket, 電子的な身分証明書みたいなもの) を取得してみます。 通常、kinitはpasswordを聞いてきますが、"-k" をつけると keytabに保存されている暗号鍵からTGTを生成するため、passwordは聞かれません。
# kinit -k -t /etc/krb5.keytab '[email protected]' #
klistで確かにTGTを取得できていることがわかります。 また、この状態でldapsearchを走らせると、passwordを聞かれずにdomain controllerの LDAP serverへ接続できることも確認できます。
# klist Ticket cache: FILE:/var/lib/ldap/krb5cc_0 Default principal: [email protected] Valid starting Expires Service principal 12/31/13 11:22:33 12/31/13 21:22:33 krbtgt/[email protected] renew until 12/31/13 21:22:33 ... # ldapsearch -h ldap1.work.hanabusa.net '(uid=myuid)' ... #
以上のように /etc/krb5.keytab からTGTを作ってやれば、slapdは domain controllerのLDAP serverへ接続できるようになります。 ただしTGTは有効期限があるためcronなどで定期的に更新してやる必要があります。 例えばActive Directoryの標準は10時間ですので、それより短い間隔で更新します。 たいていの Linux distribution では /etc/cron.hourly に script file を置くと勝手に1時間ごとに実行してくれるので、これを使うのが手軽でしょう。
設定として、まず最初に slapd に対して環境変数 KRB5CCNAME で credential cache (TGTを保管するfile) の場所を指示してやります。 これは /etc/sysconfig/slapd (RHEL7系の場合) などに書いてやります。 cronでそのcredential cacheに対してTGTを取得するようにすればokです。 最後にOS起動時にもTGTを取得させるように、 /etc/rc.d/rc.localなど起動時に実行されるfileから cron scriptを呼び出すようにしておきます。
/etc/sysconfig/slapd (RHEL>=7)
KRB5CCNAME=/var/lib/ldap/krb5_cc_ldap ...
/etc/sysconfig/ldap (RHEL<=6)
export KRB5CCNAME=/var/lib/ldap/krb5_cc_ldap ...
/etc/cron.hourly/update_slapd_cc.sh
#!/bin/sh # Load LDAP config (KRB5CCNAME) source /etc/sysconfig/slapd [ -z "${KRB5CCNAME}" ] || KRB5CCNAME=/var/lib/ldap/krb5_cc_ldap # Obtain TGT and save it into new credential cache file ( ${KRB5CCNAME}.new ) if kinit -k -t /etc/krb5.keytab -c "${KRB5CCNAME}.new" '[email protected]'; then # Change owner of credential cache to slapd run user chown ldap:ldap "${KRB5CCNAME}.new" mv "${KRB5CCNAME}.new" "${KRB5CCNAME}" fi
/etc/rc.d/rc.local (distributionごと適切なfile)
... /etc/cron.hourly/update_slapd_cc.sh ...
OpenLDAPに含まれるschemaにはActive Directoryで使われている sAMAccountNameなどが含まれていないため、 標準設定のままでは (sAMAccountName=myaccount) のような問い合わせをしても 何も返ってきません。
Active Directory用のschemaを作る必要があるのですが、 1から調べてつくるとそれなりに大変なので、 LISM projectで公開されている ad.schema を使わせてもらいます。 ad.schema を /etc/openldap/schema へ保存して、slapd.confに以下を追記します。
include /etc/openldap/schema/ad.schema
複数のdomainが存在する場合、基本的にはdomainごとにsuffixとuriを書くというのが正攻法のはずです。
# for work.hanabusa.net database ldap suffix "dc=work,dc=hanabusa,dc=net" uri "ldap://ldap1.work.hanabusa.net/" idassert-authzFrom dn.regex:.* idassert-bind bindmethod=SASL saslmech=GSSAPI mode=none overlay pcache ... # for hobby.hanabusa.net database ldap suffix "dc=hobby,dc=hanabusa,dc=net" uri "ldap://ldap1.hobby.hanabusa.net" idassert-authzFrom dn.regex:.* idassert-bind bindmethod=SASL saslmech=GSSAPI mode=none overlay pcache ...
ただ、domainが多いと保守がめんどくさいこともあって、Active Directoryの場合は TCP 3268 の global catalog service を使うのが楽ちんでしょう。 TCP 3268 でLDAP問い合わせをするとすべてのdomainまとめて検索可能です。 以下のようにsuffixを"dc=hanabusa,dc=net"のみにして、 uriで3268を指定します。
# for *.hanabusa.net database ldap suffix "dc=hanabusa,dc=net" uri "ldap://ldap1.work.hanabusa.net:3268" idassert-authzFrom dn.regex:.* idassert-bind bindmethod=SASL saslmech=GSSAPI mode=none overlay pcache ...
LDAP cacheを作るついでにapplication serverのtest用databaseも用意しておくと便利です。 slapd.confの末尾に以下を追記します。
## for test LDAP database database hdb suffix "dc=test,dc=hanabusa,dc=net" directory /var/lib/ldap/test index objectClass eq index cn,sn,mail pres,eq,sub #index sAMAccountName eq
# slapadd -s -f /etc/openldap/slapd.conf -b dc=test,dc=hanabusa,dc=net -l testusers.ldif # chown -R ldap:ldap /var/lib/ldap/test
testusers.ldifには以下のような内容を書き込みます。
dn: dc=test,dc=hanabusa,dc=net objectClass: dcObject objectClass: organization dc: test o: test domain dn: ou=testusers,dc=test,dc=hanabusa,dc=net objectclass: organizationalUnit ou: testusers dn: cn=test01,ou=testusers,dc=test,dc=hanabusa,dc=net objectClass: top objectClass: person objectClass: organizationalPerson objectClass: user cn: test01 sn: test01 sAMAccountName: test01 displayName: Test User 01 mail: [email protected] telephonenumber: 012-345-678 objectSid: dn: cn=test02,ou=testusers,dc=test,dc=hanabusa,dc=net objectClass: top objectClass: person objectClass: organizationalPerson objectClass: user cn: test02 sn: test02 sAMAccountName: test02 displayName: Test User 02 mail: [email protected] telephonenumber: 012-345-678 objectSid:
ldapsearchで作成したtest01, test02 userを取得できれば正しく動いています。
$ ldapsearch -h localhost -b dc=test,dc=hanabusa,dc=net -x '(sAMAccountName=test01)' ...