私的サーバー構築日誌：LDAPサーバー OpenLDAP・ユーザー登録

# 能書き

[私的サーバー構築日誌：仕切り直し](https://qiita.com/katz_engineer/items/1f21de2bd9072c260ae6)からの自宅サーバー構築の続きです。

LDAPにユーザーを登録します。[以前もやりました](https://qiita.com/katz_engineer/items/693ab241fc6aa8452b0d#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E7%99%BB%E9%8C%B2%E3%81%A8%E9%96%A2%E9%80%A3%E6%93%8D%E4%BD%9C)が、今回はそれらの操作をLDAPサーバーのコンテナ内で実施します。

なお、LDAPに関する各種コマンド操作は、ネットを漂えば解説記事が色々と出てきます。詳細はそちらを読んで下さい。

# 目標

- LDAPにユーザーを登録。

今回はSSSDはやりません。

# 参考文献

- [自宅サーバー構築譚：LDAPサーバー OpenLDAP](https://qiita.com/katz_engineer/items/729645f6bca28f4a3708) … 拙作の記事ですが、LDAPへの一般ユーザー登録手順を書いています。
- [自宅サーバー構築譚：LDAPサーバー OpenLDAP・SSSD を利用したログイン](https://qiita.com/katz_engineer/items/693ab241fc6aa8452b0d) … こちらも拙作記事です。一般ユーザー登録と、SSSDについての記事です。
- [【Linux】OpenLDAPを利用したユーザ認証およびユーザ管理　- インストールから利用まで – - ぺんぎんや](https://e-penguiner.com/linux-user-management-using-openldap/) … ユーザー登録やユーザーへのセカンダリグループ登録などについて、丁寧に書かれていて、参考になります。

# ユーザー登録

## 準備

まず、[前回作成した](https://qiita.com/katz_engineer/items/7ad51c3a8f1ff98efdd1#docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A)LDAPサーバーのDockerコンテナに入ります。

```console:サーバー側
cd
cd docker-slapd
docker compose exec slapd /bin/bash
```

ここでパスワードを手入力。そうすればパスワードは```$RO_PWD```で参照できるようになります。

```console:コンテナ内
read -s RO_PWD
```

念の為、LDAPの動作を確認します。

```console:コンテナ内
ldapsearch -x -LLL -H ldapi:/// -b dc=home -D cn=readonly,dc=home -w $RO_PWD
```

下記のような感じに表示されればOKです。

```console:コンテナ内
# ldapsearch -x -LLL -H ldapi:/// -b dc=home -D cn=readonly,dc=home -w $RO_PWD
dn: dc=home
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Home.
dc: home

dn: cn=readonly,dc=home
cn: readonly
objectClass: simpleSecurityObject
objectClass: organizationalRole
userPassword:: e1NTSEF9ODJ3eUhLenhYWUtmN2EvUXczcHRaWjd1YWNzVDRUY0g=
description: LDAP read only user

```

管理者ユーザーでも一応確認。

```console:コンテナ内
read -s ADMIN_PWD
```

```console:コンテナ内
ldapsearch -x -LLL -H ldapi:/// -b dc=home -D cn=admin,dc=home -w $ADMIN_PWD
```

```readonly```ユーザーでの実行結果と同じように表示されます。

```console:コンテナ内
# ldapsearch -x -LLL -H ldapi:/// -b dc=home -D cn=admin,dc=home -w $ADMIN_PWD
dn: dc=home
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Home.
dc: home

dn: cn=readonly,dc=home
cn: readonly
objectClass: simpleSecurityObject
objectClass: organizationalRole
userPassword:: e1NTSEF9ODJ3eUhLenhYWUtmN2EvUXczcHRaWjd1YWNzVDRUY0g=
description: LDAP read only user

```

## ユーザー登録の準備

基本となる組織単位を登録します。```ldapadd```コマンドは、```-f```オプションでファイルを指定されなければ標準入力からデータを読み込むようです。

```console:コンテナ内
ldapadd -x -H ldapi:/// -D cn=admin,dc=home -w $ADMIN_PWD <<___
dn: ou=people,dc=home
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=home
objectClass: organizationalUnit
ou: groups

___
```

確認。

```console:コンテナ内
ldapsearch -x -LLL -H ldapi:/// -b dc=home -D cn=readonly,dc=home -w $RO_PWD "ou=*"
```

正しく登録された場合はこう表示されます。

```console:コンテナ内
# ldapsearch -x -LLL -H ldapi:/// -b dc=home -D cn=readonly,dc=home -w $RO_PWD "ou=*"
dn: ou=people,dc=home
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=home
objectClass: organizationalUnit
ou: groups

```

何かの都合で削除する場合は下記コマンドになります。

```console:コンテナ内
ldapdelete -x -H ldapi:/// -D cn=admin,dc=home -w $ADMIN_PWD ou=groups,dc=home
ldapdelete -x -H ldapi:/// -D cn=admin,dc=home -w $ADMIN_PWD ou=people,dc=home
```

## ユーザー登録

例えばアカウント名をtaro、姓をfamilyname、パスワードを適当に生成した8文字Ma9H%6jgとする場合。姓を指定するのは、それが必須属性だからです。

更にuidとgidを決めます。uidとgidは自動生成されないようですな。不便。

```console:コンテナ内
ACCOUNT=taro
SURNAME=familyname
PASSWORD=Ma9H%6jg
USERID=10000
GROUPID=10000
```

```console:コンテナ内
cd
cd ldif
```

```console:コンテナ内
cat <<___ >user_$ACCOUNT.ldif
dn: uid=$ACCOUNT,ou=people,dc=home
objectClass: inetOrgPerson
objectClass: posixAccount
sn: $SURNAME
uid: $ACCOUNT
cn: $ACCOUNT
uidNumber: $USERID
gidNumber: $GROUPID
homeDirectory: /home/$ACCOUNT
loginShell: /bin/bash
userPassword: $(slappasswd -T <(echo -n $PASSWORD))

dn: cn=$ACCOUNT,ou=groups,dc=home
objectClass: posixGroup
cn: $ACCOUNT
gidNumber: $GROUPID

___
```

ldifファイルを作成したら、ユーザー（及びプライマリグループ）は下記コマンドで追加します。

```console:コンテナ内
ldapadd -x -H ldapi:/// -D cn=admin,dc=home -w $ADMIN_PWD -f user_$ACCOUNT.ldif
```

ユーザーとグループが追加された事を確認します。

```console:コンテナ内
cat <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=$ACCOUNT,ou=people,dc=home) <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=$ACCOUNT,ou=groups,dc=home) | diff -s -U0 user_$ACCOUNT.ldif -
```

実行結果は下記。パスワードのみ取得できず、それが差分となって現れます。

```console:コンテナ内
# cat <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=$ACCOUNT,ou=people,dc=home) <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=$ACCOUNT,ou=groups,dc=home) | diff -s -U0 user_$ACCOUNT.ldif -
--- /root/user_taro.ldif        2023-11-07 03:02:41.344219475 +0000
+++ -   2023-11-07 03:07:26.199473579 +0000
@@ -11 +10,0 @@
-userPassword: {SSHA}erIsFCMu9uSWNKEKih3yNp2D1s+OGRGe
```

差分が現れるのを嫌うなら、こんなコマンドで。

```console:コンテナ内
cat <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=$ACCOUNT,ou=people,dc=home) <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=$ACCOUNT,ou=groups,dc=home) | diff -s -U0 -L user_$ACCOUNT.ldif <(grep -v ^userPassword: user_$ACCOUNT.ldif) -
```

綺麗に一致します。

```console:コンテナ内
# cat <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=$ACCOUNT,ou=people,dc=home) <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=$ACCOUNT,ou=groups,dc=home) | diff -s -U0 -L user_$ACCOUNT.ldif <(grep -v ^userPassword: user_$ACCOUNT.ldif) -
Files user_taro.ldif and - are identical
```

## ユーザー登録内容の変更

例えばtaroのログインシェルを```/bin/sh```に、ホームディレクトリを```/home/everyone```に変更したい場合。

```console:コンテナ内
cd
cd ldif
```

```console:コンテナ内
cat <<___ >user_taro_01.ldif
dn: uid=taro,ou=people,dc=home
changetype: modify
replace: loginShell
loginShell: /bin/sh
-
replace: homeDirectory
homeDirectory: /home/everyone
___
```

ldifファイルを用意したら、```ldapmodify```コマンドを実行します。

```console:コンテナ内
ldapmodify -x -H ldapi:/// -D cn=admin,dc=home -w $ADMIN_PWD -f user_taro_01.ldif
```

確認。

```console:コンテナ内
cat <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=taro,ou=people,dc=home) <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=taro,ou=groups,dc=home) | diff -s -U0 user_taro.ldif -
```

変更点、及び出力されない userPassword が差分として出てきます。

```console:コンテナ内
# cat <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=taro,ou=people,dc=home) <(ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=taro,ou=groups,dc=home) | diff -s -U0 user_taro.ldif -
--- /root/user_taro.ldif        2023-11-07 03:02:41.344219475 +0000
+++ -   2023-11-07 04:36:16.850686523 +0000
@@ -9,3 +9,2 @@
-homeDirectory: /home/taro
-loginShell: /bin/bash
-userPassword: {SSHA}erIsFCMu9uSWNKEKih3yNp2D1s+OGRGe
+loginShell: /bin/sh
+homeDirectory: /home/everyone
```

ちなみに実際の運用では、```ldapdelete```して```ldapadd```した方が良いという意見が目立つようです。```ldapmodify```のldifファイルを見たら、確かにその通りでしょう。

## ユーザー削除

ユーザーtaroを削除する場合は下記コマンドを実行します。

```console:コンテナ内
ldapdelete -x -H ldapi:/// -D cn=admin,dc=home -w $ADMIN_PWD uid=taro,ou=people,dc=home
```

プライマリグループも明示的に削除する必要があります。

```console:コンテナ内
ldapdelete -x -H ldapi:/// -D cn=admin,dc=home -w $ADMIN_PWD cn=taro,ou=groups,dc=home
```

ldapmodifyコマンドで削除する方法もあるようですが、そちらは必要ならば調べて下さい。

削除確認。

```console:コンテナ内
ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=taro,ou=people,dc=home
ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=taro,ou=groups,dc=home
```

キチンと削除されたようです。

```console:コンテナ内
# ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b uid=taro,ou=people,dc=home
No such object (32)
Matched DN: ou=people,dc=home
# ldapsearch -x -H ldapi:/// -D cn=readonly,dc=home -w $RO_PWD -LLL -b cn=taro,ou=groups,dc=home
No such object (32)
Matched DN: ou=groups,dc=home
```

# 仕舞い

作業が終了したら、コンテナから抜けます。

```console:コンテナ内
exit
```

LDAPへのユーザー登録と内容変更、削除について、LDAPサーバーのコンテナ内で実施しました。