LDAP Managerを使ってみた！ 1. LDAPサーバ構築編

## はじめに
[前回](https://qiita.com/ahra_/items/a5e545ca397a45279ef0)に引き続きID管理について学習中のahra@ITdoです。
今回私は、LDAPサーバを中心にさまざまなシステムとの連携による統合ID管理を実現する、国産ID管理製品の[LDAP Manager](https://www.exgen.co.jp/lm/)について検証しました。
LDAP Managerにはさまざまなプラグインが存在し、非常に多機能なため、どのようにプラグインを使用すればよいか判断が難しい、と思われる方もいるかもしれません。
そんな方に、この記事でLDAP Managerの各プラグインについて簡単にご紹介できればと思います。

## LDAPサーバー構築
LDAP ManagerによるID管理の中心となるLDAPサーバを「メタディレクトリサーバ」と呼びます。
この記事では、「メタディレクトリサーバ」となるLDAPサーバを構築する手順を紹介します。

### 環境
OS: **RedHat Enterprise Linux 9.4**
設定: SELinux、firewalld無効化（検証の簡略化のため）
RHELではOpenLDAPが非推奨で標準のリポジトリに存在しないため、Symas版のOpenLDAPを使用しました。
### OpenLDAPのインストール
以下のコマンドにより、リポジトリの追加とOpenLDAPのインストールを行います。
``` 
$ wget -q https://repo.symas.com/configs/SOLDAP/rhel9/release26.repo -O /etc/yum.repos.d/soldap-release26.repo
$ dnf update
$ dnf install symas-openldap-clients symas-openldap-servers
```
### OpenLDAPの起動
まずは以下のコマンドで、LDAPルートユーザのパスワードハッシュを生成します。
生成したハッシュ値はメモしておきましょう。
```
[root@localhost ~]# slappasswd
New password:
Re-enter new password:
{SSHA}(Password Hash)
``` 
次に、設定データベースに登録するための`.ldif`ファイルを準備します。
テンプレートが用意されているので、それをコピーして使用します。
```
$ cp -p /opt/symas/etc/openldap/slapd.ldif.default /opt/symas/etc/openldap/slapd.ldif
```
`slapd.ldif`をエディタで開き、`olcSuffix`、`olcRootDN`、`olcRootPW`の値を変更して保存します。
``` slapd.ldif
olcSuffix: dc=itdo,dc=example,dc=com
olcRootDN: cn=Manager,dc=itdo,dc=example,dc=com
olcRootPW: {SSHA}(生成したPassword Hash)
```
以下のコマンドで`slapd.ldif`ファイルの内容を`slapd`データベースに登録させ、slapdを起動します。
```
$ slapadd -n 0 -F /opt/symas/etc/openldap/slapd.d -l /opt/symas/etc/openldap/slapd.ldif
$ systemctl start slapd
```

### OpenLDAPの設定
デフォルトでは設定ディレクトリへのアクセス権がなく、スキーマの追加等が行えないのでこれを変更します。
以下のような`.ldif`ファイルを作成し、保存します。

``` /tmp/config.ldif
dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcAccess
olcAccess: to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
```
これを以下のコマンドで追加し、`slapd`を再起動します。
これで、SASL/EXTERNALでバインドされたユーザが設定ディレクトリの変更を行えます。
```
$ systemctl stop slapd
$ slapmodify -n 0 -F /opt/symas/etc/openldap/slapd.d/ -l /tmp/config.ldif
$ systemctl start slapd
``` 
次に、基本的なスキーマを設定します。
以下のコマンドのように、追加したいスキーマの`.ldif`ファイルを指定し、追加します。
```
$ ldapadd -Y EXTERNAL -H ldapi:/// -f /opt/symas/etc/openldap/schema/inetorgperson.ldif
$ ldapadd -Y EXTERNAL -H ldapi:/// -f /opt/symas/etc/openldap/schema/cosine.ldif
$ ldapadd -Y EXTERNAL -H ldapi:/// -f /opt/symas/etc/openldap/schema/core.ldif
```
次に、ベースDNにエントリを追加するための設定、またOUを追加します。
以下のような`.ldif`ファイルを作成します。
``` /tmp/basedn.ldif
dn: dc=itdo,dc=example,dc=com
objectClass: dcObject
objectClass: organization
dc: itdo
o: itdo

dn: ou=Users,dc=itdo,dc=example,dc=com
ou: Users
description: LM
objectClass: organizationalUnit

dn: ou=Groups,dc=itdo,dc=example,dc=com
ou: Groups
description: LM
objectClass: organizationalUnit
```
その後、以下のコマンドでエントリを追加します。
```
$ ldapadd -D 'cn=Manager,dc=itdo,dc=example,dc=com' -W -f /tmp/basedn.ldif
```
### LDAP Manager用の設定
まずは、LDAP ManagerのシステムIDなどを格納する属性などについて定義します。
リセラーKIT内にサンプルファイル（`esdsystem.schema`）がありましたので、それを使用します。
まず、`esdsystem.schema`ファイルを任意の場所にコピーします。今回は`/tmp/esdsystem.schema`とします。
次に、以下のようなファイルを用意します。
``` /tmp/esdsystem.conf
/tmp/esdsystem.schema
```
このファイルをもとに、以下のコマンドで`.schema`ファイルを`.ldif`ファイルに変換します。
```
$ slaptest -f /tmp/esdsystem.conf -F /tmp/
config file testing succeeded
```
これで、`/tmp//cn\=config/cn\=schema/cn\=\{0\}esdssystem.ldif`が作成されます。
このファイルを、以下の通り編集して保存します。
``` diff
- dn: cn={0}esdssystem
+ dn: cn=esdssystem,cn=schema,cn=config
- cn: {0}esdssystem 
+ cn: esdssystem
- structualObjectClass: olcSchemaConfig 以後のすべて
```
作成した`.ldif`ファイルでスキーマを追加します。
```
$ ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp//cn\=config/cn\=schema/cn\=\{0\}esdssystem.ldif
```
追加したら、LDAP ManagerのシステムIDを登録します。
以下のようなldifファイルを用意します。
``` /tmp/lisence.ldif
#LDAP Manager LICENSE
dn: cn=esdssystem,dc=itdo,dc=example,dc=com
cn: esdssystem
objectClass: top
objectClass: esdssystem
esdssystemid: (ディレクトリサーバ用システムID）
```
これを、以下のコマンドで追加します。
```
$ ldapadd -D 'cn=Manager,dc=itdo,dc=example,dc=com' -W -f /tmp/lisence.ldif
```
その他、LDAP Manager用の拡張オブジェクトクラスや属性を以下の通り定義しました。
OIDの`*****`の部分は実際には弊社の[Private Enterprise Number - PEN](https://www.iana.org/assignments/enterprise-numbers/)を設定しています。

:::  note info
記事の執筆後に知りましたが、一意性の確保のため独自のLDAP属性やオブジェクトクラスの名称を指定する際は接頭辞`x-`を付けることが推奨されているようです。
:::
``` グループ用拡張オブジェクトクラス、属性用 .ldif ファイル
dn: cn=exgroupOfNames,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: exgroupOfNames
olcAttributeTypes: {0}( 1.3.6.1.4.1.*****.1.4001 NAME 'exgmember' DESC 'member attr for LM' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SUP distinguishedName )
olcAttributeTypes: {1}( 1.3.6.1.4.1.*****.1.4002 NAME 'exexgmember1' DESC 'extended member 1' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SUP distinguishedName )
olcAttributeTypes: {2}( 1.3.6.1.4.1.*****.1.4003 NAME 'exexgmember2' DESC 'extended member 2' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SUP distinguishedName )
olcObjectClasses: {0}( 1.3.6.1.4.1.*****.2.4 NAME 'exgroupOfNames' DESC 'An extension of groupOfNames objectclass that member attr is NOT a must' SUP top STRUCTURAL MUST ( cn ) MAY ( exgmember $ exexgmember1 $ exexgmember2 $ businessCategory $ seeAlso $ owner $ ou $ o $ description $ departmentNumber)) 
```
Active Directory反映を使用する場合、「AD反映用パスワード属性」が必要です。
今回はexgPersonオブジェクトクラスの許可属性となるように定義しています。
``` AD反映用パスワード属性用 .ldif ファイル
dn: cn={1}esdssystem,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: {4} ( 1.3.6.1.4.1.*****.1.5001 NAME 'exgPasswdInfo' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
-
delete: olcObjectClasses
olcObjectClasses: {1}
-
add: olcObjectClasses
olcObjectClasses: {1}( 1.3.6.1.4.2 NAME 'exgPerson' SUP top AUXILIARY MUST ( cn $ objectclass ) MAY ( exgUserPassword $ exgEnabledFlag $ exgOldContainer $exgPasswdInfo))
```
これで、メタディレクトリサーバの構築は完了です。

[次の記事](https://qiita.com/ahra_/items/56f062f49b03eadd3860)では、**LDAP Manager**を構築します。