LDAP検索ツール ldapsearch の覚書

LDAP検索ツール `ldapsearch` の使い方メモです。

`ldapsearch`は、OpenLDAP に含まれるクライアントツールです。
LDAPサーバに対して問い合わせを行うことができます。

# インストール

Ubuntu、その他deb族。

```shell
sudo apt install -y ldap-utils
```

CentOS Stream 8、その他rpm族。

```shell
dnf install -y openldap-clients
```

CentOS8 から、LDAPサーバは `OpenLDAP` から `389ds` へ変わりました。しかし、操作ツールは引き続き `openldap-clients` です。

# 認証方法指定のオプション

| option | 説明 |
|--------|------|
| `-x`   | simple認証を選択します。 |
| `-Y MECH` | SASL認証を選択します。その機構として `MECH` を指定します。 |

simple認証は、ユーザー名、パスワードによる認証です。
simple認証とは別の認証方式として、SASL[^sasl]認証があります。

[^sasl]: https://ja.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer

認証は `-x` のsimple認証で十分です(私見)。
ただし、simple認証だけだと、通信路にパスワードが平文で流れてしまうので、TLS で通信路を保護します。

SASL認証では、ワンタイムパスワードやチャレンジ-レスポンスなどの機構を用いて、通信路の傍受でパスワードを知られてしまうことを防ぎます。
しかし、TLSで通信路を保護するならパスワードが流れてしまっても良いんじゃないかと思います。

SASLは、TLSが気軽には使えなかった時代の名残なのではないでしょうか。

# LDAPサーバ指定のオプション

| option | 説明 |
|--------|------|
| `-H URL`   | LDAPサーバを URL形式で指定します。 |
| `-h HOST` | LDAPサーバのホストを指定します。(非推奨) |
| `-p PORT` | LDAPサーバのTCPポート番号を指定します。(非推奨) |

`-h` `-p` は `man ldapsearch`で、以下のように書かれています。

> Deprecated in favor of -H.

`-H` を使いましょう。
URLのスキームは`ldap` か `ldaps` です。`ldaps` だとTLSを使用します。
TCPポート番号のデフォルトは、TLSの場合 636、非TLSの場合 389です。

例)

* `-H ldaps://myldap.example.com`: TLSを使う。アドレスは `myldap.example.com`。TCPポート番号は 636。
* `-H ldaps://192.168.0.1:10636`: TLSを使う。アドレスは `192.168.0.1`。TCPポート番号は 10636。
* `-H ldap://192.168.0.1`: TLSを使わない。アドレスは `192.168.0.1`。TCPポート番号は 389。

## TLS使用時の注意

LDAPサーバの TLS証明書がちゃんとした証明書であれば問題ないのですが、自己署名証明書だったり、期限切れだったりするとエラーになります。

```text
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)
```

環境変数 `LDAPTLS_REQCERT` に `allow` を設定するか、設定ファイルに `TLS_REQCERT allow` を書きましょう。

設定ファイルは以下のいずれかです。

* `/etc/openldap/ldap.conf`
* `$HOME/ldaprc`, `$HOME/.ldaprc`
* カレントフォルダの `ldaprc`

もちろん、LDAPサーバのTLS証明書がちゃんとした証明書であるのがベストなのは言うまでもありません。

参照: [man ldap.conf](https://linux.die.net/man/5/ldap.conf)

# 接続アカウント指定のオプション

| option | 説明 |
|--------|------|
| `-D BIND_DN`   | Bind DNを指定します。 |
| `-W` | Bind DNのパスワードをキーボード入力します。 |
| `-w PASSWORD` | Bind DNのパスワードをコマンドラインオプションで指定します。 |
| `-y FILE` | Bind DNのパスワードをFILE から読み込みます。 |

Bind DN[^DN]は、平たく言うとLDAPサーバへ接続する際のアカウント名です。
[^DN]: Distinguished Name

例) `cn=Manager,dc=example,dc=com`

`-W`, `-w`, `-y` はパスワードの指定方法です。

`-W` はちょっと試す時には良いですが、毎回キーボード入力が要るので自動化・無人化には向きません。
`-w` はキーボード入力は不要ですが、コマンドラインにパスワードが入るので、`ps` 等で見えてしまいます。
`-y` だとキーボード入力不要で、コマンドラインにパスワードが見えてしまうこともありません。

プロセス置換も使えます。`pass`[^pass] などのパスワードマネージャからパスワードを流し込むことができます。
[^pass]: <https://www.passwordstore.org/>

```shell
ldapsearch -x -y <(pass ldap_password | tr -d '\n\r') ...
```

`| tr -d '\n\r'` を付けている理由は、出力から改行を取り除くためです。

<https://9to5answer.com/ldapsearch-password-file-format>

直接ファイルから読み込むときも同様です。
emacs や vi でファイルを作ると末尾に改行が入ってしましますが、ldapsearch はその改行コードもパスワードの一部とみなしてしまいます。
改行コードを含まないファイルを作るか、`| tr -d '\n\r'` 等の方法で改行を取り除きましょう。

# 表示のオプション

| option | 説明 |
|--------|------|
| `-L`  | 表示結果を LDIFv1 フォーマットにします。 |
| `-LL` | -Lに加えて、コメント行の出力を止めます。 |
| `-LLL` | -LLに加えて、LDIFバージョンの表示も止めます。 |

単純に、`L` が増えるほど表示がシンプルになると思えば良いです。

# 検索条件のオプション

| option | 説明 |
|--------|------|
| `-b DN`  | 基点になるDNを指定します。このDN配下が検索対象になります。 |

# ldapsearch の例

```shell
$ export LDAPTLS_REQCERT=allow
$ ldapsearch \
    -x \
    -LLL \
    -H "ldaps:ldap_server.example.com" \
    -D "cn=manager,dc=example,dc=com" \
    -y <(cat ~/.ldap_password | tr -d '\n\r') \
    -b "ou=people,dc=example,dc=com" \
    "(& (objectClass=posixAccount) (uid=testuser_01))" "uidNumber"
dn: uid=testuser_01,ou=People,dc=example,dc=com
uidNumber: 1001
```