OpenLDAP Server 日本語訳

[OpenLDAP Server](https://help.ubuntu.com/lts/serverguide/openldap-server.html) の日本語訳。

Lightweight Directory Access Protocol (LDAP) は
TCP/IP 上で動作する X.500 に基づくディレクトリサービスへ
問合せと更新を行う為のプロトコルである。
最新の LDAP のバージョンは RFC4510 に基づいて定義された
LDAPv3 である。 Ubuntu では OpenLDAP として実装されている。

LDAP プロトコルは LDAP ディレクトリへ接続し、
いくつかの概念と用語を持つ:

1. LDAP ディレクトリは階層的なデータ登録のツリーとなっており、
   Directory Information Tree (DIT) と呼ばれる。

2. 登録されたデータは属性を持つ。

3. 属性は種類(名前 / 説明)を持ち、一つまたは複数の値を持つ。

4. 全ての属性は最低一つの objectClass を必ず定義しなければならない。

5. 属性と objectClass はスキーマへ定義する。
   (objectClass は実際には特別な種類の属性として認識される)

6. 各登録は一意の識別子を持つ:
   Distinguished Name(DN または dn)
   DN は Relative Distinguished Name (RDN) を持ち、
   RDN の後には 親の DN 登録が記述される。

7. DN の登録は属性ではない。
   DN そのものはデータ登録の一部とはみなされない。

*Note:*
object, container, node とさまざま呼び名があるが、
いずれも登録を意味する技術用語である。

例えば、下記の登録は 11 の属性から構成される:

* DN は “cn=John Doe,dc=example,dc=com”

* RDN は “cn=John Doe”

* 親の DN は “dc=example,dc=com”

```bash:DIT
dn: cn=John Doe,dc=example,dc=com
cn: John Doe
givenName: John
sn: Doe
telephoneNumber: +1 888 555 6789
telephoneNumber: +1 888 555 1232
mail: john@example.com
manager: cn=Larry Smith,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
```

上記の登録は LDIF 形式 (LDAP Data Interchange Format) で
記述されている。DIT へ記述する情報は全て 
LDIF 形式で記述しなければならない。
LDIF は RFC2849 に定義されている。

本手引では LDAP を認証に使用する方法を説明する。
属性に基づく(name:value)バックエンドである LDAP は
情報の取得を要求する接続要求の大量処理に適している。
アドレス帳、 email アドレスの一覧、メールサーバの設定を
例として掲載する。

#インストール
OpenLDAP サーバデーモンと伝統的な LDAP 管理ユーティリティを
インストールする。
OpenLDAP サーバデーモンと LDAP 管理ユーティリティは 
slapd と ldap-utilsのパッケージに含まれている。

slapd をインストールすると動作設定が作成される。
slapd はユーザのデータを保存することができる
データベースインスタンスを作成する。
データベースインスタンスの接尾辞(またはベース DN)は
ローカルホストのドメイン名から決定される。
独自に設定したい場合は ``/etc/hosts`` を編集してドメイン名を書換え、
任意の接尾辞を指定する。
例えば接尾辞を ``dc=example,dc=com`` としたい場合、
``/etc/hosts`` は下記のように記述する:

```bash:/etc/hosts
127.0.1.1       hostname.example.com hostname
```

ユーザはパッケージインストール後に変更を元に戻すことができる。

*Note:*
本手引ではデータベース接尾辞として
``dc=example,dc=com`` を使用する。

インストールを進める:

```bash
sudo apt install slapd ldap-utils
```

Ubuntu 8.10 から slapd は外部ファイルへ分離した
DIT を準備することで slapd の内部で
自身を設定するように設計されている。
これはサービスを再起動せずに slapd の設定を
動的に変更することを可能にする。
設定データベースは ``/etc/ldap/slapd.d`` 配下に配置された
テキストベースの LDIF ファイルのコレクションから構成される。

この動作方式はいくつかの名前で知られている: 

* the slapd-config method
* the RTC method (Real Time Configuration)
* the cn=config method 

伝統的な flat-file method (slapd.conf) を
使用することもできるが、推奨しない; 
flat-file method は段階的に廃止されていく。

*Note:*
Ubuntu は現在 slapd-config method を使用して 
slapd の設定を行っており、
本手引では slapd-config method に従う。

インストールの間、管理者の資格情報を定義するプロンプトが表示される。
ユーザのデータベースインスタンスの roorDN の資格情報は 
LDAP に基づく。
ユーザの DN の既定値は ``cn=admin,dc=example,dc=com`` 。
また slapd-config データベースの管理者アカウントは既定では存在せず、
LDAP の外部から認証し接続する必要がある。詳細は後述する。

今日では古典的なスキーム(cosine, nis, inetorgperson)は 
slapd に内臓されている。
スキームを動作させる為に前もって必要な “core” スキームも含まれている。

#インストール後の検証
インストール処理では 2 つの DIT が設定される。
一つは slapd-config 、
もう一つはユーザ自身のデータ(dc=example,dc=com)である。
以下に例を掲載する。

slapd-config は database/DIT の形式となる。
データベースは LDIF に基づき、 
``/etc/ldap/slapd.d`` 配下で動作する:

* /etc/ldap/slapd.d/
* /etc/ldap/slapd.d/cn=config
* /etc/ldap/slapd.d/cn=config/cn=module{0}.ldif
* /etc/ldap/slapd.d/cn=config/cn=schema
* /etc/ldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif
* /etc/ldap/slapd.d/cn=config/cn=schema/cn={1}cosine.ldif
* /etc/ldap/slapd.d/cn=config/cn=schema/cn={2}nis.ldif
* /etc/ldap/slapd.d/cn=config/cn=schema/cn={3}inetorgperson.ldif
* /etc/ldap/slapd.d/cn=config/cn=schema.ldif
* /etc/ldap/slapd.d/cn=config/olcBackend={0}hdb.ldif
* /etc/ldap/slapd.d/cn=config/olcDatabase={0}config.ldif
* /etc/ldap/slapd.d/cn=config/olcDatabase={-1}frontend.ldif
* /etc/ldap/slapd.d/cn=config/olcDatabase={1}hdb.ldif
* /etc/ldap/slapd.d/cn=config.ldif

*Note:*
slapd-config データベースを直接編集してはならない。
LDAP プロトコル(ユーティリティ)経由で変更を行うこと。

LDAP プロトコル経由の slapd-config DIT の操作は下記のように行う:

*Warning:*
Ubuntu server 14.10 以降では
下記のコマンドはバグにより動作しないことがある。

```bash
sudo ldapsearch 
  -Q 
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=config dn

dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: olcBackend={0}hdb,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}hdb,cn=config
```

登録の説明:

1. cn=config: 全体の設定

2. cn=module{0},cn=config: 動的に読み込まれるモジュール

3. cn=schema,cn=config: ハードコーディングされた
   システムレベルのスキームを含む

4. cn={0}core,cn=schema,cn=config: ハードコーディングされた
   コアスキーム

5. cn={1}cosine,cn=schema,cn=config: コサインスキーム

6. cn={2}nis,cn=schema,cn=config: nis スキーム

7. cn={3}inetorgperson,cn=schema,cn=config:
   inetorgperson スキーム

8. olcBackend={0}hdb,cn=config:
   ‘hdb’ バックエンドストレージの種類

9. olcDatabase={-1}frontend,cn=config:
   フロントエンドデータベース。他のデータベース用の既定の設定

10. olcDatabase={0}config,cn=config:
    slapd 設定データベース (cn=config)

11. olcDatabase={1}hdb,cn=config:
    ユーザのデータベースインスタンス (dc=examle,dc=com)

dc=example,dc=com DIT を例示する:

```bash
ldapsearch -x -LLL -H ldap:/// -b dc=example,dc=com dn

dn: dc=example,dc=com
dn: cn=admin,dc=example,dc=com
```

登録の説明:

1. dc=example,dc=com: DIT のベース

2. cn=admin,dc=example,dc=com:
   (パッケージのインストール中に設定される)
   DIT の管理者 (rootDN)

#ユーザデータベースの更新 / 移行
データベースの内容を例示する。下記を登録する:

1. People という名前のノード(ユーザを保存する)

2. Group という名前のノード(グループを保存する)

3. miners という名前のグループ

4. john という名前のユーザ

下記の LDIF ファイルを作り、
``add_content.ldif`` と名前を付ける:

```bash:add_content.ldif
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups

dn: cn=miners,ou=Groups,dc=example,dc=com
objectClass: posixGroup
cn: miners
gidNumber: 5000

dn: uid=john,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: john
sn: Doe
givenName: John
cn: John Doe
displayName: John Doe
uidNumber: 10000
gidNumber: 5000
userPassword: johnldap
gecos: John Doe
loginShell: /bin/bash
homeDirectory: /home/john
```

*Note:*
ディレクトリ内で uid と gid の値が
local の値と衝突しないようにすることが重要。
5000 番から始まるような高い数値域を使用すること。
uid と gid の値を ldap 内で高く設定することによって
local ユーザが行う操作と ldap が行う操作の制御が簡単になる。
詳細については後述する。

内容を追加する。

```bash
ldapadd
  -x
  -D cn=admin,dc=example,dc=com
  -W -f add_content.ldif

Enter LDAP Password: ********
adding new entry "ou=People,dc=example,dc=com"
adding new entry "ou=Groups,dc=example,dc=com"
adding new entry "cn=miners,ou=Groups,dc=example,dc=com"
adding new entry "uid=john,ou=People,dc=example,dc=com"
```

ldapsearch ユーティリティを使用することで
情報が正しく登録されているかどうかを確認することができる:

```bash
ldapsearch
  -x
  -LLL
  -b dc=example,dc=com 'uid=john' cn gidNumber

dn: uid=john,ou=People,dc=example,dc=com
cn: John Doe
gidNumber: 5000
```

ldapsearch のスイッチの説明:

1. -x: “simple” バインディング; 既定の SASL メソッドを使用しない

2. -LLL: 外来情報の表示を無効にする

3. uid=john: john という名前のユーザを検索する “filter”

4. cn gidNumber: 特定の属性を表示するように要求する
   (既定では全ての属性が表示される)

#slapd 設定データベースの更新
slapd-config DIT は検索と更新を行うことができる。
下記に例を掲載する。

ldapmodify を使用して “Index” (DbIndex 属性) を
{1}hdb,cn=config database (dc=example,dc=com) へ追加する。
下記の内容でファイルを作成し、 ``uid_index.ldif`` と名前を付ける:

```bash:uid_index.ldif
dn: olcDatabase={1}hdb,cn=config
add: olcDbIndex
olcDbIndex: uid eq,pres,sub
```

下記のコマンドを実行する:

```bash
sudo ldapmodify
  -Q
  -Y EXTERNAL
  -H ldapi:///
  -f uid_index.ldif

modifying entry "olcDatabase={1}hdb,cn=config"
```

変更した内容は下記の方法で確認することができる:

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=config '(olcDatabase={1}hdb)' olcDbIndex

dn: olcDatabase={1}hdb,cn=config
olcDbIndex: objectClass eq
olcDbIndex: uid eq,pres,sub
```

スキーマを追加する。スキーマの作成は LDIF 形式への変換が必要となる。
``/etc/ldap/schema`` ディレクトリに変換前のスキームと、
変換後のスキームが配置されている。

*Note:*

1. slapd-config データベースからスキームを削除すると
   重大な問題を引き起こすことがある。
   試験的なスキームの追加は試験用のシステム上で行うこと。

2. スキームを追加する前に、
   スキームが既にインストールされているかどうかを確認すること
   (既定では ``out-of-the-box`` と出力される):

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=schema,cn=config dn

dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
```

以下の例では CORBA スキームを登録する。

下記の内容で ``schema_convert.conf`` という名前の
変換用設定ファイルを作成する:

```bash:schema_convert.conf
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/collective.schema
include /etc/ldap/schema/corba.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/duaconf.schema
include /etc/ldap/schema/dyngroup.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/java.schema
include /etc/ldap/schema/misc.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/openldap.schema
include /etc/ldap/schema/ppolicy.schema
include /etc/ldap/schema/ldapns.schema
include /etc/ldap/schema/pmi.schema
```

``ldif_output`` という名前の出力用ディレクトリを作成する。

スキーマのインデックスを決定する:

```bash
slapcat -f schema_convert.conf -F ldif_output -n 0
  | grep corba,cn=schema

cn={1}corba,cn=schema,cn=config
```

*Note:*
slapd が親の DN と同じオブジェクトを受け取る場合、
受け取ったオブジェクトへインデックスを作成する。
インデックスは ``{X}`` の形式で記録される:

slapcat を使用して変換を実行する:

```bash
slapcat 
  -f schema_convert.conf
  -F ldif_output
  -n 0
  -H ldap:///cn={1}corba,cn=schema,cn=config
  -l cn=corba.ldif
```

変換されたスキーマは ``cn=corba.ldif`` となる。

``cn=corba.ldif`` を編集し、下記の属性を検索する:

```bash:cn=corba.ldif
dn: cn=corba,cn=schema,cn=config
...
cn: corba
```

下記の行を削除する:

```bash:cn=corba.ldif
structuralObjectClass: olcSchemaConfig
entryUUID: 52109a02-66ab-1030-8be2-bbf166230478
creatorsName: cn=config
createTimestamp: 20110829165435Z
entryCSN: 20110829165435.935248Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20110829165435Z
```

属性の値が変更される。

最後に ldapadd を使用して
新しいスキーマを slapd-config DIT へ登録する:

```bash
sudo ldapadd
  -Q
  -Y EXTERNAL
  -H ldapi:///
  -f cn\=corba.ldif

adding new entry "cn=corba,cn=schema,cn=config"
```

現在読み込まれているスキーマを確認する:

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=schema,cn=config dn

dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: cn={4}corba,cn=schema,cn=config
```

*Note:*
外部のアプリケーションとクライアントを 
LDAP を使用して認証する為には、
アプリケーションとクライアント毎に設定が必要となる。
詳細はクライアント側の文書を参照すること。

#ログの記録
OpenLDAP に基づくソリューションを実装する場合は
slapd の動作履歴の記録は欠かすことができないが、
ソフトウェアのインストール後に必ず手動で有効にしなければならない。
手動操作を行わない場合は基本的なメッセージのみがログに記録される。
他の slapd 設定と同様に、
ログの記録は slapd-config データベースを介して有効となる。

OpenLDAP は複数のログ記録サブシステム(levels)を備えており、
各 level に下位のサブシステム(additive)を保持している。
統計がその一例だ。
サブシステムの詳細については slapd-config のマニュアルページを参照。

``logging.ldif`` という名前のファイルを下記の内容で作成する:

```bash:logging.ldif
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats
```

変更を反映する:

```bash
sudo ldapmodify
  -Q
  -Y EXTERNAL
  -H ldapi:///
  -f logging.ldif
```

これはログの重要度を定義し、製品として稼働を始めたシステムの
ログ詳細レベルを小さく絞る。
このモードで稼働している間、ホストの syslog エンジン(rsyslog)は
接続の維持が困難になった場合に下記のメッセージを出力することがある:

```bash
rsyslogd-2177: imuxsock lost 228 messages 
from pid 2547 due to rate-limiting
```

rsyslog の設定変更を検討する場合は
``/etc/rsyslog.conf`` へ下記を追記する:

```bash:/etc/rsyslog.conf
# レートの制限を無効化する。
# (既定では 5 秒間に 200 メッセージ;
# 下記の例では 5 から 0 へ変更する)
$SystemLogRateLimitInterval 0
```

rsyslog デーモンを再起動する:

```bash
sudo systemctl restart syslog.service
```

#複製
LDAP サービスへ依存するネットワークシステムが増えるにつれて
LDAP サービスは重要さを増していく。
LDAP サービスへ依存する環境では
LDAP サーバが応答しなくなった場合の混乱を防止する為に
LDAP の冗長化(高い可用性)を行う。
冗長化は LDAP の複製を通じて行われる。

複製は Syncrepl エンジンを介してアーカイブ化される。
Syncrepl エンジンは Consumer-Provider モデルを使用して
同期を行う。本手引では下記のモードの組合せで複製機能を実装する:

* refreshAndPersist
* delta-syncrepl

変更が発生すると同時に Provider が
変更された登録を Consumer へ送信するが、
変更の送信のみを行い、変更の登録は行われない。

Provider の設定を行う。

LDIF ファイルを下記の内容で作成し、 
``provider_sync.ldif`` と名前を付ける:

```bash:provider_sync.ldif
# フロントエンドデータベースへインデックスを登録する。
dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: entryCSN eq
-
add: olcDbIndex
olcDbIndex: entryUUID eq

# syncprov モジュールと accesslog モジュールを読み込む。
dn: cn=module{0},cn=config
changetype: modifyadd: olcModuleLoad
olcModuleLoad: syncprov
-
add: olcModuleLoad
olcModuleLoad: accesslog

# accesslog データベースの定義
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap/accesslog
olcSuffix: cn=accesslog
olcRootDN: cn=admin,dc=example,dc=com
olcDbIndex: default eq
olcDbIndex: entryCSN,objectClass,reqEnd,reqResult,reqStart

# Accesslog db syncprov.
dn: olcOverlay=syncprov,olcDatabase={2}hdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov
olcSpNoPresent: TRUE
olcSpReloadHint: TRUE

# プライマリデータベースの syncrepl Provider
dn: olcOverlay=syncprov,olcDatabase={1}hdb,cn=configchangetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov
olcSpNoPresent: TRUE

# プライマリデータベースの accesslog overly 定義
dn: olcOverlay=accesslog,olcDatabase={1}hdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcAccessLogConfig
olcOverlay: accesslog
olcAccessLogDB: cn=accesslog
olcAccessLogOps: writes
olcAccessLogSuccess: TRUE

# accesslog データベースを毎日スキャンし、
# 7 日前より古い登録を削除する。
olcAccessLogPurge: 07+00:00 01+00:00
```

管理者が保持するディレクトリに合わせて
LDIF ファイルの rootDN を変更する。

slapd の apparmor プロファイルは 
accesslog データベースが
``/etc/apparmor.d/local/usr.sbin.slapd`` 
に含まれている為、調整の必要はない:

```bash:/etc/apparmor.d/local/usr.sbin.slapd
/var/lib/ldap/ r,/var/lib/ldap/** rwk,
```

ディレクトリを作成し、データベース設定ファイルを設置して
apparmor プロファイルを再起動する:

```bash
sudo -u openldap mkdir /var/lib/ldap/accesslog
sudo -u openldap cp /var/lib/ldap/DB_CONFIG /var/lib/ldap/accesslog
sudo systemctl reload apparmor.service
```

新しい内容を登録し、 apparmor へ変更を反映する為に
デーモンを再起動する:

```bash
sudo ldapadd
  -Q
  -Y EXTERNAL
  -H ldapi:///
  -f provider_sync.ldif

sudo systemctl restart slapd.service
```

Provider の設定は以上で完了する。

#Consumer の設定
Consumer を設定する。

手順に従ってソフトウェアをインストールする。
slapd-config データベースが 
Provider と同一であることを確認しておくこと。
特にスキームとデータベースの接尾辞が同一であることを確認しておくこと。

LDIF ファイルを下記の内容で作成し、 
``consumer_sync.ldif`` と名前を付ける:

```bash:consumer_sync.ldif
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: syncprov

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: entryUUID eq
-
add: olcSyncRepl
olcSyncRepl: rid=0
  provider=ldap://ldap01.example.com
  bindmethod=simple
  binddn="cn=admin,dc=example,dc=com"
  credentials=secret
  searchbase="dc=example,dc=com"
  logbase="cn=accesslog"
  logfilter="(&(objectClass=auditWriteObject)(reqResult=0))"
  schemachecking=on
  type=refreshAndPersist
  retry="60 +"
  syncdata=accesslog
-
add: olcUpdateRef
olcUpdateRef: ldap://ldap01.example.com
```

下記の属性が正しい値を確実に保持するようにする:

1. provider (Provider サーバのホスト名または IP アドレス。
   この例では ``ldap01.example.com`` とする)

2. binddn (管理者の DN)

3. credentials (管理者 DN のパスワード)

4. searchbase (データベースの接尾辞)

5. olcUpdateRef (Provider サーバのホスト名または IP アドレス)

6. rid (Replica ID 。複製を識別する一意の 3 桁の数値)
   各 consumer は最低でも一つの rid を保持しておく必要がある。

新しい内容を登録する:

```bash
sudo ldapadd
  -Q
  -Y EXTERNAL
  -H ldapi:///
  -f consumer_sync.ldif
```

Consumer の設定は以上で完了する。
2 つのデータベース(suffix: dc=example,dc=com)が
同期するようになる。

#動作テスト
複製を開始した後は Provider と Consumer の双方で
下記を実行することで監視を行うことができる。

```bash
ldapsearch
  -z1
  -LLLQY EXTERNAL
  -H ldapi:///
  -s base
  -b dc=example,dc=com contextCSN

dn: dc=example,dc=com
contextCSN: 20120201193408.178454Z#000000#000#000000
```

Provider と Consumer の出力
(上記の例では 20120201193408.178454Z#000000#000#000000)
が合致していれば正常に複製されている。
Provider で変更が行われる度にこの値は更新され、
Consumer でも同様の動作が実行される。

接続が遅い、または ldap データベースが巨大である場合、
consumer と provider の contextCSN の照合に
時間がかかることがある。
しかし consumer の contextCSN は着実に増えていく為
処理が進行中であることが判るだろう。

consumer の contextCSN が欠損している、
または provider に合致しない場合、
作業を中断してどこに問題が生じているのか確認する必要がある。
consumer の認証要求が成功している、
またはデータの取得要求(ldapsearch 文が大量に発行される)に
エラーが無い場合は provider の slapd (syslog) と
認証ログファイルを確認する。

単純なクエリが動作するかどうかを Consumer 上でテストする。
データベースの DN は:

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b dc=example,dc=com dn
```

以下の情報が出力される。

* ‘john’ という名前のユーザ

* ‘miners’ という名前のグループ

* ‘People’ と ‘Groups’ という名前のノード

#アクセスコントロール
ユーザがリソースに対してどのような種類の操作
(読取り、書込み等)を行うことができるかを管理することを
アクセスコントロールと呼ぶ。
関連する設定ディレクティブは Access Control Lists 
または ACL と呼称される。

slapd パッケージをインストールすると
さまざまな ACL が自動的に設定される。
既定で設定される ACL の中から 2 、 3 重要なものを見ていく。
ACL がどのように動作し、どのように設定されるのかを
理解する助けとなるだろう。

LDAP クエリの有効な ACL を取得する為には、
特別なフロントエンドデータベースのインスタンスと同様に、
問合せ先データベースの ACL 登録を参照する必要がある。
後述する ACL は、前者に合致しない場合は既定の ACL として動作する。
フロントエンドデータベースは二番目に参照され、
これら 2 つの ACL ソースの内最初に合致した ACL が適用される。
(“first match wins”)
下記のコマンドはそれぞれ hdb データベース(“dc=example,dc=com”)と
フロントエンドデータベースの ACL を取得する:

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=config '(olcDatabase={1}hdb)' olcAccess

dn: olcDatabase={1}hdb,cn=config
olcAccess:
  {0}to attrs=userPassword,shadowLastChange by self
  write by anonymous
  auth by dn="cn=admin,dc=example,dc=com"
  write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self
  write by dn="cn=admin,dc=example,dc=com"
  write by * read
```

*Note:*
rootDN は常にデータベースの完全な権限を保有する。
ACL は明確な設定を提供するが、 
slapd は動作制限を発生させる原因ともなる。

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=config '(olcDatabase={-1}frontend)' olcAccess

dn: olcDatabase={-1}frontend,cn=config
olcAccess:
  {0}to * by dn.exact=gidNumber=0+uidNumber=0,
    cn=peercred,cn=external,cn=auth
  manage by * break
olcAccess: {1}to dn.exact="" by * read
olcAccess: {2}to dn.base="cn=Subschema" by * read
```

最初の ACL は重要である:

```bash
olcAccess:
  {0}to attrs=userPassword,shadowLastChange by self 
  write by anonymous
  auth by dn="cn=admin,dc=example,dc=com"
  write by * none
```

これはより簡便に表記することができる:

```bash
to attrs=userPassword
   by self write
   by anonymous auth
   by dn="cn=admin,dc=example,dc=com" write
   by * none

to attrs=shadowLastChange
   by self write
   by anonymous auth
   by dn="cn=admin,dc=example,dc=com" write
   by * none
```

これを組合せた ACL は下記を実行する:

1. 匿名の ‘auth’ アクセスは最初の接続を行う為に
   userPassword 属性へ渡される。
   匿名で DIT へ接続する必要がない場合でも
   ‘by anonymous auth’ は必要となる。
   リモートエンドが一度接続されても認証が発生することがある。
   (次点を参照)

2. 全ユーザが ‘read’ (‘by self write’ の為に) 権限を持ち、
   userPassword 属性へアクセスするが故に認証が発生することがある。

3. 一方、 userPassword 属性は
   完全なアクセス権限を持つ rootDN を除いて
   他のユーザがアクセスすることはできない。

4. ユーザが自身のパスワードを変更する為には 
   passwd または他のユーティリティを使用する。
   shadowLastChange 属性は
   一度認証されたユーザの接続を許可する為に必要となる。

ACL が ‘by * read’ となっている為、
この DIT は匿名で検索することができる:

```bash
to *
   by self write
   by dn="cn=admin,dc=example,dc=com" write
   by * read
```

匿名で DIT を検索することを望まない場合は ACL を変更する必要がある。
バインド要求の際に認証を強制する場合は、
代わりに(または ACL の更新と組合せて) 
``‘olcRequire: authc’`` ディレクティブを使用する。

前述のように slapd-config データベースの管理者アカウントは
自動作成されないが、 slapd-config データベースの
完全なアクセス権限を持つ SASL ID が存在する。
SASL ID はローカルホストのスーパーユーザ(root / sudo)を表す。
下記に例を示す:

```bash
dn.exact=gidNumber=0+uidNumber=0,
  cn=peercred,cn=external,cn=auth
```

下記のコマンドは slapd-config データベースの ACL を表示する。

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=config '(olcDatabase={0}config)' olcAccess

dn: olcDatabase={0}config,cn=config
olcAccess:
  {0}to * by dn.exact=gidNumber=0+uidNumber=0,
    cn=peercred,cn=external,cn=auth manage by * break
```

これは SASL ID である為、 
LDAP ユーティリティによる問合せを実行する際に
SASL 機構を使用する必要があり、本手引の中で頻出する。
SASL 機構は EXTERNAL 機構である。
例として先述のコマンドを見てみよう。下記に留意してもらいたい:

1. ACL を照合する為に必ず sudo を使用して
   root ID へ切り替える必要がある。

2. EXTERNAL 機構は IPC (UNIX domain sockets) を介して
   動作する為、必ず ldapi URI 形式を使用する必要がある。

全 ACL を簡単に取得するには下記のように操作する:

```bash
sudo ldapsearch
  -Q
  -LLL
  -Y EXTERNAL
  -H ldapi:///
  -b cn=config '(olcAccess=*)' olcAccess olcSuffix
```

アクセスコントロールについての詳細は
slapd.access のマニュアルページを参照。

#TLS
OpenLDAP サーバの認証を行う際は
暗号化セッションを使用することが望ましい。
暗号化セッションは Tranport Layer Security (TLS) を
使用することで実現することができる。

本章では自身の端末を認証局として使用し、
LDAP サーバ証明書(CA)を作成・署名する。
slapd は gnutils library を使用してコンパイルされている為、
certtool ユーティリティを使用してサーバ証明書を作成・署名する。

gnutls-bin と ssl-cert パッケージをインストールする:

```bash
sudo apt install gnutls-bin ssl-cert
```

認証局の秘密鍵を作成する:

```bash
sudo sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem"
```

template/file /etc/ssl/ca.info を作成し、 CA を定義する:

```bash:/etc/ssl/ca.info
cn = Example Company
ca
cert_signing_key
```

自身で署名した CA 証明書を作成する:

```bash
sudo certtool
  --generate-self-signed 
  --load-privkey /etc/ssl/private/cakey.pem 
  --template /etc/ssl/ca.info 
  --outfile /etc/ssl/certs/cacert.pem
```

サーバの秘密鍵を作成する:

```bash
sudo certtool
  --generate-privkey
  --bits 1024
  --outfile /etc/ssl/private/ldap01_slapd_key.pem
```

*Note:*
ファイル名の ``ldap01`` の部分は
サーバのホスト名に合わせて置換える。
ホストの証明書と鍵に名前を付け、
どのサービスに使用する証明書と鍵なのかを明確にする。

下記の情報を含む ``/etc/ssl/ldap01.info`` ファイルを作成する:

```bash:/etc/ssl/ldap01.info
organization = Example Company
cn = ldap01.example.com
tls_www_server
encryption_key
signing_key
expiration_days = 3650
```

上記の証明書は 10 年間有効となる。必要に応じて調整すること。

サーバの証明書を作成する:

```bash
sudo certtool
  --generate-certificate
  --load-privkey /etc/ssl/private/ldap01_slapd_key.pem
  --load-ca-certificate /etc/ssl/certs/cacert.pem
  --load-ca-privkey /etc/ssl/private/cakey.pem
  --template /etc/ssl/ldap01.info
  --outfile /etc/ssl/certs/ldap01_slapd_cert.pem
```

``certinfo.ldif`` ファイルを下記の内容で作成する
( ``https://www.cacert.org`` を使用して作成した証明書を
例示する。必要に応じて調整すること):

```bash:certinfo.ldif
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap01_slapd_cert.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap01_slapd_key.pem
```

ldapmodify コマンドを使用して slapd へTLS が 
slapd-config データベースを介して動作することを通知する:

```bash
sudo ldapmodify
  -Y EXTERNAL
  -H ldapi:///
  -f /etc/ssl/certinfo.ldif
```

暗号化を使用する為に ``/etc/default/slapd`` の中に 
``ldaps://`` は必要ない:

```bash:/etc/default/slapd
SLAPD_SERVICES="ldap:/// ldapi:///"
```

*Note:*
LDAP の TLS/SSL (ldaps://) は 
StartTLS の採用により廃止された。
既存の LDAP セッション(TCP ポート 389 番で待受ける)は 
TLS/SSL によって保護されるようになった。 
HTTPS と同様に LDAPS は TCP ポート 636 番で動作する
encrypted-from-the-start プロトコルとは異なる。

所有権と権限を制限する:

```bash
sudo adduser openldap ssl-cert
sudo chgrp ssl-cert /etc/ssl/private/ldap01_slapd_key.pem
sudo chmod g+r /etc/ssl/private/ldap01_slapd_key.pem
sudo chmod o-r /etc/ssl/private/ldap01_slapd_key.pem
```

OpenLDAP を再起動する:

```bash
sudo systemctl restart slapd.service
```

ホストのログ( ``/var/log/syslog`` )を確認し、
サーバが正しく起動しているか確認する。

#複製と TLS
サーバ間で複製を設定している場合、盗聴防止の為に
通信を暗号化(StartTLS)することが望ましい。
複製の通信の暗号化は、上記の認証における暗号化の使用とは異なる。
本章では TLS-aunthentication の動作環境を構築する。

複製の章に従って Provider と Consumer の間で複製を設定し、
TLS の章に従って Provider へ認証における 
TLS を設定していることを前提とする。

上記では LDAP サービスにおいて
高い互換性を持つ複製の構築を目的としていた。
Provider 上で認証の TLS を設定している為、 
Consumer 上でも同様に認証の TLS が必要とされる。
本章では複製の通信を暗号化する。
Provider 上で鍵 / 証明書を生成して他の CA 証明書を受付不可とし、
必要な材料を Consumer へ転送する。

Provider 上では格納用のディレクトリ(転送時に使用する)を作成し、
Consumer の秘密鍵を作成する:

```bash
mkdir ldap02-ssl
cd ldap02-ssl
sudo certtool
  --generate-privkey
  --bits 1024
  --outfile ldap02_slapd_key.pem
```

Consumer サーバ用に情報のファイルを作成し、 
``ldap02.info`` と名前を付ける。
値は必要に応じて調整すること:

```bash:ldap02.info
organization = Example Company
cn = ldap02.example.com
tls_www_server
encryption_key
signing_key
expiration_days = 3650
```

Consumer の証明書を作成する:

```bash
sudo certtool
  --generate-certificate
  --load-privkey ldap02_slapd_key.pem
  --load-ca-certificate /etc/ssl/certs/cacert.pem
  --load-ca-privkey /etc/ssl/private/cakey.pem
  --template ldap02.info
  --outfile ldap02_slapd_cert.pem
```

CA 証明書のコピーを取得する:

```bash
cp /etc/ssl/certs/cacert.pem .
```

以上で設定は完了し、 ldap02-ssl ディレクトリが 
Consumer へ転送される。

scp を使用する(必要に応じて調整すること):

```bash
cd ..
scp -r ldap02-ssl user@consumer:
```

Consumer 上で TLS 認証を設定する:

```bash
sudo apt install ssl-cert
sudo adduser openldap ssl-cert
sudo cp ldap02_slapd_cert.pem cacert.pem /etc/ssl/certs
sudo cp ldap02_slapd_key.pem /etc/ssl/private
sudo chgrp ssl-cert /etc/ssl/private/ldap02_slapd_key.pem
sudo chmod g+r /etc/ssl/private/ldap02_slapd_key.pem
sudo chmod o-r /etc/ssl/private/ldap02_slapd_key.pem
```

``/etc/ssl/certinfo.ldif`` ファイルを下記の内容で作成する
(必要に応じて調整すること):

```bash:/etc/ssl/certinfo.ldif
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap02_slapd_cert.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap02_slapd_key.pem
```

slapd-config データベースを設定する:

```
sudo ldapmodify
  -Y EXTERNAL
  -H ldapi:///
  -f certinfo.ldif
```

``/etc/default/slapd`` を 
Provider (SLAPD_SERVICES) へ作成する。

Consumer 上で Consumer 側の複製用の TLS を設定する。
いくつか TLS オプションを設定し、
既存の olcSyncrepl 属性を更新する。
属性値の変更方法を下記に例示する。

``consumer_sync_tls.ldif`` ファイルを下記の内容で作成する:

```bash:consumer_sync_tls.ldif
dn: olcDatabase={1}hdb,cn=config
replace: olcSyncRepl
olcSyncRepl: rid=0 provider=ldap://ldap01.example.com bindmethod=simple
binddn="cn=admin,dc=example,dc=com" credentials=secret
searchbase="dc=example,dc=com"
logbase="cn=accesslog"
logfilter="(&(objectClass=auditWriteObject)(reqResult=0))"
schemachecking=on type=refreshAndPersist retry="60 +" syncdata=accesslog
starttls=critical tls_reqcert=demand
```

追加のオプションを指定し、各 consumer が必ず StartTLS を使用し、
CA 証明書が Provider の ID 確認を要求するようにする。
IDIF シンタックスの属性(‘replace’)の値の変更にも留意すること。

ここまでの変更を反映する:

```bash
sudo ldapmodify
  -Y EXTERNAL
  -H ldapi:///
  -f consumer_sync_tls.ldif
```

slapd を再起動する:

```bash
sudo systemctl restart slapd.service
```

Provider 上で TLS セッションが確立されていることを確認する。
``/var/log/syslog`` 内で ‘conns’-level logging の設定が
提供され、下記のようなメッセージが表示される:

```bash:/var/log/syslog
slapd[3620]: conn=1047 fd=20 ACCEPT
  from IP=10.153.107.229:57922 (IP=0.0.0.0:389)
slapd[3620]: conn=1047 op=0 EXT oid=1.3.6.1.4.1.1466.20037
slapd[3620]: conn=1047 op=0 STARTTLS
slapd[3620]: conn=1047 op=0 RESULT oid= err=0 text=
slapd[3620]: conn=1047 fd=20 TLS established tls_ssf=128 ssf=128
slapd[3620]: conn=1047 op=1 BIND
  dn="cn=admin,dc=example,dc=com" method=128
slapd[3620]: conn=1047 op=1 BIND
  dn="cn=admin,dc=example,dc=com"
  mech=SIMPLE ssf=0
slapd[3620]: conn=1047 op=1 RESULT tag=97 err=0 text
```

#LDAP 認証
LDAP サーバが稼働を始めたら、サーバへ通信を行う為のライブラリを
クライアントへインストールする必要がある。
Ubuntu では伝統的に libnss-ldap パッケージを
インストールすることでサーバへの通信を実現する。
libnss-ldap パッケージは、
設定の段階でユーザを補助するツール群を提供する。
下記を実行してパッケージをインストールする:

```bash
sudo apt install libnss-ldap
```

LDAP サーバの詳細を確認するプロンプトを表示する。
設定を間違えた場合は下記を実行することで修正することができる:

```bash
sudo dpkg-reconfigure ldap-auth-config
```

ダイアログの結果は ``/etc/ldap.conf`` に記録される。
サーバがメニューのオプションに対応していない場合は
``/etc/ldap.conf`` を編集する。

NSS 用の LDAP プロファイルを設定する:

```bash
sudo auth-client-config -t nss -p lac_ldap
```

認証の為に LDAP が使用するシステムを設定する:

```bash
sudo pam-auth-update
```

メニューから LDAP と必要とする他の認証機構を選択する。
LDAP に基づいた資格を使用してログインが可能となる。
複製が使用されている場合、 
LDAP クライアントは複数のサーバを参照する必要がある。
``/etc/ldap.conf`` へ下記のように記述する:

```bash:/etc/ldap.conf
uri ldap://ldap01.example.com ldap://ldap02.example.com
```

Provider (ldap01) が応答しない場合、
要求はタイムアウトして Consumer (ldap02) への接続を試行する。

Samba ユーザを保存する為に LDAP を使用する場合、
Samba サーバを LDAP を使用して認証するように設定する必要がある。
詳細は [Samba and LDAP](https://help.ubuntu.com/lts/serverguide/samba-ldap.html) を参照。

*Note:*
libnss-ldap パッケージの代替として 
libnss-ldapd パッケージを使用することができるが、
不必要な nscd パッケージがインストールされる。
不要なパッケージはインストール後に削除する。

#ユーザとグループの管理
ldap-utils パッケージはディレクトリの管理に必要な
ユーティリティを提供するが、長いオプションを必要とする為
ユーザにとって負担となることがある。
ldapscripts パッケージは 
ldap-utils のラッパースクリプトを有しており、
より簡単に使用することができる。

パッケージをインストールする:

```bash
sudo apt install ldapscripts
```

``/etc/ldapscripts/ldapscripts.conf`` を編集し、
下記の記述を検索する:

```bash:/etc/ldapscripts/ldapscripts.conf
SERVER=localhost
BINDDN='cn=admin,dc=example,dc=com'
BINDPWDFILE="/etc/ldapscripts/ldapscripts.passwd"
SUFFIX='dc=example,dc=com'
GSUFFIX='ou=Groups'
USUFFIX='ou=People'
MSUFFIX='ou=Computers'
GIDSTART=10000
UIDSTART=10000
MIDSTART=10000
```

``ldapscripts.passwd`` ファイルを作成し、 
rootDN へディレクトリへのアクセスを許可する。

```bash
sudo sh -c "echo -n 'secret' > /etc/ldapscripts/ldapscripts.passwd"
sudo chmod 400 /etc/ldapscripts/ldapscripts.passwd
```

*Note:*
“secret” の部分をデータベースの 
rootDN ユーザの実際のパスワードへ置換する。

スクリプトからディレクトリの管理を行う準備が整った。
使い方の例を下記に示す:

新しいユーザを作成する:

```bash
sudo ldapadduser george example
```

この例では george という uid のユーザを作成し、
ユーザのプライマリグループ(gid)を example に設定する。

ユーザのパスワードを変更する:

```bash
sudo ldapsetpasswd george
Changing password for user uid=george,ou=People,dc=example,dc=com
New Password:
New Password (verify):
```

ユーザを削除する:

```bash
sudo ldapdeleteuser george
```

グループを登録する:

```bash
sudo ldapaddgroup qa
```

グループを削除する:

```bash
sudo ldapdeletegroup qa
```

グループへユーザを登録する:

```bash
sudo ldapaddusertogroup george qa
```

memberUid 属性を参照すると qa グループの値として 
george が記録されている。

グループからユーザを削除する:

```bash
sudo ldapdeleteuserfromgroup george qa
```

memberUid 属性が qa グループから削除される。

ldapmodifyuser スクリプトはユーザの属性を
登録、削除、または更新する。
ldapmodifyuser スクリプトは 
ldapmodify ユーティリティと同じシンタックスを使用する。
例えば:

```bash
sudo ldapmodifyuser george
# 下記の登録を更新する:
dn: uid=george,ou=People,dc=example,dc=com
objectClass: account
objectClass: posixAccount
cn: george
uid: george
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/george
loginShell: /bin/bash
gecos: george
description: User account
userPassword:: e1NTSEF9eXFsTFcyWlhwWkF1eGUybVdFWHZKRzJVMjFTSG9vcHk=

# 更新内容を記述し、 CTRL-D で終了する。
dn: uid=george,ou=People,dc=example,dc=com
replace: gecos
gecos: George Carlin
```

ユーザの gecos は “George Carlin” となっている。

ldapscripts はテンプレートシステムを備えている。
テンプレートは下記の属性のカスタマイズを可能にする。

* user
* group
* machine objects

例えば user テンプレートを有効にするには
``/etc/ldapscripts/ldapscripts.conf`` を編集する:

```bash:/etc/ldapscripts/ldapscripts.conf
UTEMPLATE="/etc/ldapscripts/ldapadduser.template"
```

``/usr/share/doc/ldapscripts/examples`` ディレクトリに
サンプルテンプレートが格納されている。 ``ldapadduser.template.sample`` ファイルを
コピーまたは名前を変更して
``/etc/ldapscripts/ldapadduser.template`` を作成する:

```bash
sudo cp
  /usr/share/doc/ldapscripts/examples/ldapadduser.template.sample
  /etc/ldapscripts/ldapadduser.template
```

新しいテンプレートを編集して独自の属性を登録する。
下記の例では inetOrgPerson の objectClass を使用して
新規ユーザを作成する:

```bash:/etc/ldapscripts/ldapadduser.template
dn: uid=<user>,<usuffix>,<suffix>
objectClass: inetOrgPerson
objectClass: posixAccount
cn: <user>
sn: <ask>
uid: <user>
uidNumber: <uid>
gidNumber: <gid>
homeDirectory: <home>
loginShell: <shell>
gecos: <user>
description: User account
title: Employee
```

``<ask>`` オプションは sn 属性用に使用されている。
これは ldapadduser へ値を入力するプロンプトを追加する。

パッケージが提供するユーティリティの一覧を掲載する:

* ldaprenamemachine
* ldapadduser
* ldapdeleteuserfromgroup
* ldapfinger
* ldapid
* ldapgid
* ldapmodifyuser
* ldaprenameuser
* lsldap
* ldapaddusertogroup
* ldapsetpasswd
* ldapinit
* ldapaddgroup
* ldapdeletegroup
* ldapmodifygroup
* ldapdeletemachine
* ldaprenamegroup
* ldapaddmachine
* ldapmodifymachine
* ldapsetprimarygroup
* ldapdeleteuser

#バックアップと復元
ldap を思いのままに操作できるようになったところで、
これまでに行った全操作を保存し、必要な時に復元ができるようにする。

ldap データベース、具体的にはバックエンド(cn=config)と
フロントエンド(dc=example,dc=com)の
バックアップを取得する方法が必要となる。
上記のデータベースのバックアップを 
``/export/backup`` へ出力する場合、
下記のスクリプトに例示するように slapcat を使用することができる。
このスクリプトに ``/usr/local/bin/ldapbackup`` と名前を付ける:

```bash:/usr/local/bin/ldapbackup
#!/bin/bash

BACKUP_PATH=/export/backup
SLAPCAT=/usr/sbin/slapcat

nice ${SLAPCAT} -n 0 > ${BACKUP_PATH}/config.ldif
nice ${SLAPCAT} -n 1 > ${BACKUP_PATH}/example.com.ldif
nice ${SLAPCAT} -n 2 > ${BACKUP_PATH}/access.ldif
chmod 640 ${BACKUP_PATH}/*.ldif
```

*Note:*
これらのファイルは非圧縮テキストファイルであり、
ldap データベースに含まれる
ツリーレイアウト、ユーザ名、全パスワードを含む。
従って ``/export/backup`` は暗号化されたパーティションへ作成し、
スクリプトは作成したファイルを暗号化することが望ましい。
理想としては両者を行うべきだが、セキュリティ要件に応じて決定する。

cron スクリプトへこのプログラムを自動実行するように登録する。
頻度としては日に一回で事足りるが、
場合によってはもっと高い頻度が要求されることもある。
cron スクリプトの例を下記に示す。
``/etc/cron.d/ldapbackup`` と名前を付け、
毎夜 22:45h: に実行する:

```bash:/etc/cron.d/ldapbackup
MAILTO=backup-emails@domain.com
45 22 * * *  root    /usr/local/bin/ldapbackup
```

作成されたファイル群はバックアップサーバへコピーされる。

ldap の再インストールを行う場合は
下記のように復元処理を行うことができる:

```bash
sudo systemctl stop slapd.service
sudo mkdir /var/lib/ldap/accesslog
sudo slapadd -F /etc/ldap/slapd.d -n 0 -l /export/backup/config.ldif
sudo slapadd -F /etc/ldap/slapd.d -n 1 -l /export/backup/domain.com.ldif
sudo slapadd -F /etc/ldap/slapd.d -n 2 -l /export/backup/access.ldif
sudo chown -R openldap:openldap /etc/ldap/slapd.d/
sudo chown -R openldap:openldap /var/lib/ldap/
sudo systemctl start slapd.service
```

#参考資料

1. [オンラインドキュメント](http://www.openldap.org/)

2. slapd パッケージには数多くのマニュアルページが存在する。
   下記に重要なマニュアルページを列記する:
   * slapd
   * slapd-config
   * slapd.access
   * slapo-syncprov

3. 他のマニュアルページ:
   * auth-client-config
   * pam-auth-update

4. Zytrax’s LDAP for Rocket Scientists; 
   簡潔かつ包括的な LDAP の扱い方

5. Ubuntu community OpenLDAP wiki page は
   資料のコレクションを有している。

6. O’Reilly’s LDAP System Administration 
   (textbook; 2003)

7. Packt’s Mastering OpenLDAP (textbook; 2007)