SASLからOpenLDAP＆ActiveDirectoryへ問い合わせを行う

社内にWebシステムが立ち上がるたびに、各システムローカルの認証情報がつくられることにうんざりしていた。
ただし、社内のActiveDirectoryにユーザ登録してもらうのもハードルが高いので、協力会社メンバーのアカウントはOpenLDAPで管理したい、というのが発端。

で、まずは自分が管理するsubversionリポジトリの認証をSASLに変更。
入力したユーザIDがSASL経由でLDAPに渡り、OpenLDAP:uid、ActiveDirectory:sAMAccountName　のどちらかにhitすればよい。とした。

最初は簡単だろ、と思ったが日本語のサイトには情報がぜんぜんなかったのでメモ。

<dl>
<dt>前提とするOS/MWのバージョン</dt>
<dd>CentOS 5.11(x86_64)</dd>
<dd>cyrus-sasl：2.1.22</dd>
<dd>openldap-servers：2.3.43</dd>
<dd>openldap：2.3.43</dd>
</dl>

**ベースディレクトリ定義**
　AD：dc=XXXX,dc=local
　LDAP：dc=ldap,dc=XXXX,dc=local
*ADのサブドメインとすることで一つのツリーに見せかけた*

**ユーザDN**
　AD：cn=%名前%,OU=OU_Users,dc=XXXX,dc=local
　LDAP：uid=%ユーザID%,ou=partner,dc=ldap,dc=XXXX,dc=local
*"%"の部分は環境依存値。以降も同様*

*上記の状態でOpenLDAPとSASLは導入済みとします。*

**参考ページ**
　http://www.linuxtopia.org/online_books/network_administration_guides/ldap_administration/overlays_Chaining.html

<h2>１．ActiveDirectory用のスキーマファイル取得</h2>
```
 # wget http://lism.sourceforge.jp/docs/ad.schema -O /etc/openldap/schema/ad.schema
```
<h2>２．OpenLDAPの設定</h2>
*※ACLは省略*

```text:/etc/openldap/slapd.conf
include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/nis.schema

pidfile         /var/run/openldap/slapd.pid
argsfile        /var/run/openldap/slapd.args

# ActiveDirectoryのSchema設定（追加）
include         /etc/openldap/schema/ad.schema
sizelimit unlimited

# ActiveDirectoryのChain設定（追加）
overlay chain
chain-max-depth 2
chain-return-error TRUE
chain-uri "ldap://aaa.bbb.ccc.ddd/"
chain-rebind-as-user true
chain-idassert-bind bindmethod="simple" binddn="cn=%検索用ユーザー%,OU=OU_Users,dc=XXXX,dc=local" credentials="%パスワード%" mode="legacy" flags="non-prescriptive"
chain-acl-bind bindmethod="simple" binddn="cn=%検索用ユーザー%,OU=OU_Users,dc=XXXX,dc=local" credentials="%パスワード%"

password-hash   {SSHA}

# For Local LDAP
database        bdb
suffix          "dc=ldap,dc=XXXX,dc=local"
rootdn          "cn=Manager,dc=ldap,dc=XXXX,dc=local"
rootpw          {SSHA}ReO7KDZeKSxWfn8T9903YzbS8TqizgqR
directory       /var/lib/ldap

# For Local Index
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub

# ActiveDirectoryのIndex（追加）
index sAMAccountName                    eq,pres
index distinguishedName                 eq,pres


# ActiveDirectoryへの問い合わせ設定（追加）
database        ldap
chase-referrals no
suffix          "dc=XXXX,dc=local"
uri             ldap://aaa.bbb.ccc.ddd/
acl-bind        bindmethod="simple" binddn="cn=%検索用ユーザー%,OU=OU_Users,dc=XXXX,dc=local" credentials="%パスワード%"
idassert-bind   bindmethod="simple" binddn="cn=%検索用ユーザー%,OU=OU_Users,dc=XXXX,dc=local" credentials="%パスワード%" mode="legacy" flags="non-prescriptive"
```

```text:/etc/openldap/ldap.conf
URI     ldap://127.0.0.1/
BASE    dc=ldap,dc=XXXX,dc=local
SASL_REALM ldap.XXXX.local

scope sub
ssl no
sizelimit unlimited

TLS_CACERTDIR   /etc/openldap/certs
```

<h2>３．SASLの設定</h2>
```text:/etc/sysconfig/saslauthd
MECH=ldap
FLAGS="-O /etc/saslauthd.conf"
```
上記のように変更

```text:/etc/saslauthd.conf
ldap_servers: ldap://127.0.0.1
ldap_use_sasl: no
ldap_bind_dn: uid=%LDAP検索用ユーザー%,ou=system,dc=ldap,dc=XXXX,dc=local
ldap_password: %パスワード%
ldap_mech: PLAIN
ldap_auth_method: bind
ldap_filter: (|(uid=%U)(sAMAccountName=%U))
ldap_scope: sub
ldap_search_base: dc=ldap,dc=XXXX,dc=local
ldap_deref: always
```

<h2>４．uidに該当するユーザで確認</h2>
```text:コマンド
# ldapsearch -x -D "uid=%LDAP検索ユーザー%,ou=system,dc=ldap,dc=XXXX,dc=local" "(|(uid=partnera)(sAMAccountName=partnera))" -W
```

```text:結果(LDAPからの返却値)
# extended LDIF
#
# LDAPv3
# base <> with scope subtree
# filter: (|(uid=partnera)(sAMAccountName=partnera))
# requesting: ALL
#

# partnera, partner, ldap.XXXX.local
dn: uid=partnera,ou=partner,dc=ldap,dc=XXXX,dc=local
objectClass: top
objectClass: inetOrgPerson
uid: partnera
mail: partnerA@XXXX.co.jp
givenName: %エンコードされた値%
sn: %エンコードされた値%
cn:: %エンコードされた値%
userPassword:: e1NTSEF9a3RoQUpKZE5icmFUNUlQRkE3a1BZdm5heHN4R1RscHRkbm95VEdSS1p
 ETT0=

# search result
search: 2
result: 0 Success

# numResponses: 2
```

<h2>５．sAMAccountNameに該当するユーザで確認</h2>
```text:コマンド
# ldapsearch -x -D "uid=%LDAP検索ユーザー%,ou=system,dc=ldap,dc=XXXX,dc=local" "(|(uid=%社員番号%)(sAMAccountName=%社員番号%))" -W
```

```text:結果（ActiveDirectoryからの返却値）
# extended LDIF
#
# LDAPv3
# base <> with scope subtree
# filter: (|(uid=%社員番号%)(sAMAccountName=%社員番号%))
# requesting: ALL
#

# %エンコードされた値%, OU_Users, XXXX.local
dn:: %エンコードされた値%
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn:: %エンコードされた値%
sn:: %エンコードされた値%
description:: %エンコードされた値%
givenName:: %エンコードされた値%
distinguishedName:: %エンコードされた値%
instanceType: 4
whenCreated: 20120329081907.0Z
whenChanged: 20141217011450.0Z
displayName:: %エンコードされた値%
uSNCreated: 8558
uSNChanged: 7815826
name:: %エンコードされた値%
objectGUID:: %エンコードされた値%
userAccountControl: 512
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 130607728713210993
lastLogoff: 0
lastLogon: 130632524744753546
pwdLastSet: 130632524908555646
primaryGroupID: 513
objectSid:: %エンコードされた値%
accountExpires: 9223372036854775807
logonCount: 12
sAMAccountName: %社員番号%
sAMAccountType: 805306368
userPrincipalName: %社員番号%@XXXX.local
lockoutTime: 0
objectCategory: cn=Person,cn=Schema,cn=Configuration,dc=XXXX,dc=local
dSCorePropagationData: 20140108085735.0Z
dSCorePropagationData: 16010101000000.0Z
LASTLOGONTIMESTAMP: 130632509056134209
mail: mailLocalPart@XXXX.co.jp

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
```

<h2>６．Subversionの設定</h2>
```text:svnserve.conf
[sasl]
use-sasl = true
```
上記を追加

```text:/usr/lib64/sasl2/svn.conf
pwcheck_method: saslauthd
auxprop_plugin: ldap
mech_list: PLAIN
ldapdb_mech: PLAIN
```
上記の内容で新規作成

<h2>おまけ．phpLDAPadmin</h2>
```text:/etc/phpldapadmin/config.php
$servers->setValue('login','attr','uid'); #コメントイン　
# 以下を最下行の　?>　前に追加
$servers->setValue('server','base',array('dc=XXXX,dc=local','dc=ldap,dc=XXXX,dc=local'));
$servers->setValue('login','base',array('dc=ldap,dc=XXXX,dc=local'));
$servers->setValue('login','bind_id','uid=%LDAP検索ユーザー%,ou=system,dc=ldap,dc=XXXX,dc=local');
$servers->setValue('login','bind_pass','%パスワード%');
$servers->setValue('login','fallback_dn',true);
```

上記の設定でLDAPはuid,dn、ActiveDirectoryはdn指定でログイン可能になる。