【初心者向け】OpenLDAPによるユーザ認証 ~Linux(CentOS)~

1. はじめに

サーバ台数がある程度増えてくると個々のサーバごとにユーザ管理するのは面倒かと思います。OpenLDAPによりユーザ認証制御を簡単に管理する方法を紹介しますので、ぜひ参考にしてみて下さい。今回はCentOS8にOpenLDAPの導入方法をご紹介します。
※OpenLDAPはRHEL7.4から非推奨になってはいますが、実際にはまだ使われているシステムも多いかと思います。ただし正式サポートされないことが一般的かと思いますので、将来的には他製品への移行を推奨します。

2. LDAPの用途

LDAPとはLightweight Directory Access Protocolの略で、ユーザー情報を階層的に管理、検索、認証するために利用されているプロトコルとなります。主な用途は下記となります。

・データの一元管理
ユーザ情報や機器の情報等を一元管理することができます。階層的なツリー構造を持たせて情報を管理する点が特徴で、条件を指定して情報を検索することも可能です。また、複数のLDAPサーバ間でレプリケーションすることで、データ保管の信頼性を向上させることもできます。

・ユーザ認証
ログインやsuコマンドによるユーザスイッチ時に、ユーザ認証を導入することができます。例えば、大量のサーバーを運用しているシステムにおいて1台1台のサーバに対してパスワード変更を行うとなると大変ですが、LDAPサーバを立てて一元管理しておけば、LDAPサーバにてパスワードを変更するだけで済むようになります。また、ユーザー認証時のログをLDAPサーバーで集中管理できるので、不正アクセス検出などの解析が容易になるというメリットもあります。

3. LDAPサーバの構築

LDAPによるデータ管理はツリー構造になっています。今回は下記のようなツリー構造を作成していきます。

まずはLDAP認証を行うLDAPサーバを構築していきましょう。インターネット接続できるサーバにて、dnfコマンドでopenldap-servers、openldap-clientsのパッケージをインストールしましょう。

[root@workernode1 ~]# dnf --enablerepo=powertools -y install openldap-servers openldap-clients
Dependencies resolved.
======================================================================================================================================================
 Package                                 Architecture                  Version                                Repository                         Size
======================================================================================================================================================
Installing:
 openldap-clients                        x86_64                        2.4.46-18.el8                          baseos                            202 k
 openldap-servers                        x86_64                        2.4.46-18.el8                          powertools                        2.2 M

Transaction Summary
======================================================================================================================================================
Install  2 Packages

Total download size: 2.4 M
Installed size: 5.4 M
Downloading Packages:
(1/2): openldap-servers-2.4.46-18.el8.x86_64.rpm                                                                      3.1 MB/s | 2.2 MB     00:00
(2/2): openldap-clients-2.4.46-18.el8.x86_64.rpm                                                                      247 kB/s | 202 kB     00:00
------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                 2.8 MB/s | 2.4 MB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                                              1/1
  Running scriptlet: openldap-servers-2.4.46-18.el8.x86_64                                                                                        1/2
  Installing       : openldap-servers-2.4.46-18.el8.x86_64                                                                                        1/2
  Running scriptlet: openldap-servers-2.4.46-18.el8.x86_64                                                                                        1/2
  Installing       : openldap-clients-2.4.46-18.el8.x86_64                                                                                        2/2
  Running scriptlet: openldap-clients-2.4.46-18.el8.x86_64                                                                                        2/2
[/usr/lib/tmpfiles.d/slapd.conf:2] Line references path below legacy directory /var/run/, updating /var/run/openldap → /run/openldap; please update the tmpfiles.d/ drop-in file accordingly.

  Verifying        : openldap-clients-2.4.46-18.el8.x86_64                                                                                        1/2
  Verifying        : openldap-servers-2.4.46-18.el8.x86_64                                                                                        2/2

Installed:t  openldap-clients-2.4.46-18.el8.x86_64                                     openldap-servers-2.4.46-18.el8.x86_64

Complete!
[root@workernode1 ~]#

データベースのサンプル設定ファイルが格納されているので/var/lib/ldap配下にコピーします。キャッシュサイズやログファイルの最大サイズ等を設定できるので、要件に応じて設定変更してみて下さい。今回はデフォルトの設定とします。

[root@workernode1 ~]# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
[root@workernode1 ~]#
[root@workernode1 ~]# chown ldap. /var/lib/ldap/DB_CONFIG
[root@workernode1 ~]#
[root@workernode1 ~]# ls -ld /var/lib/ldap/DB_CONFIG
-rw-r--r-- 1 ldap ldap 845 Apr  7 06:10 /var/lib/ldap/DB_CONFIG
[root@workernode1 ~]#

OpenLDAPの機能を有効にするためにslapdというサービスを起動します。

[root@workernode1 ~]# systemctl enable --now slapd
Created symlink /etc/systemd/system/openldap.service → /usr/lib/systemd/system/slapd.service.
Created symlink /etc/systemd/system/multi-user.target.wants/slapd.service → /usr/lib/systemd/system/slapd.service.
[root@workernode1 ~]#
[root@workernode1 ~]# systemctl status slapd
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2025-04-07 06:12:09 JST; 6s ago
     Docs: man:slapd
           man:slapd-config
           man:slapd-hdb
           man:slapd-mdb
           file:///usr/share/doc/openldap-servers/guide.html
  Process: 32404 ExecStart=/usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:/// (code=exited, status=0/SUCCESS)
  Process: 32390 ExecStartPre=/usr/libexec/openldap/check-config.sh (code=exited, status=0/SUCCESS)
 Main PID: 32405 (slapd)
    Tasks: 2 (limit: 11272)
   Memory: 3.1M
   CGroup: /system.slice/slapd.service
           └─32405 /usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:///

Apr 07 06:12:09 workernode1 systemd[1]: Starting OpenLDAP Server Daemon...
Apr 07 06:12:09 workernode1 runuser[32393]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
Apr 07 06:12:09 workernode1 runuser[32393]: pam_unix(runuser:session): session closed for user ldap
Apr 07 06:12:09 workernode1 slapd[32404]: @(#) $OpenLDAP: slapd 2.4.46 (Aug 10 2021 05:11:20) $
                                                  mockbuild@x86-02.mbox.centos.org:/builddir/build/BUILD/openldap-2.4.46/openldap-2.4.46/servers/slapd
Apr 07 06:12:09 workernode1 slapd[32405]: slapd starting
Apr 07 06:12:09 workernode1 systemd[1]: Started OpenLDAP Server Daemon.
[root@workernode1 ~]#

LDAP認証関連のログを出力させるためにrsyslog .confに設定を追加しましょう。LDAPのログはlocal4ファシリティにログを送付していますのでlocal4の設定を追加します。設定追加したらrsyslogを再起動します。

[root@workernode1 ~]# cp -p /etc/rsyslog.conf /etc/rsyslog.conf_bk
[root@workernode1 ~]#
[root@workernode1 ~]# vi /etc/rsyslog.conf
[root@workernode1 ~]# diff /etc/rsyslog.conf /etc/rsyslog.conf_bk
67,68d66
< # LDAP log
< local4.*                                                /var/log/slapd
[root@workernode1 ~]#
[root@workernode1 ~]# systemctl restart rsyslog
[root@workernode1 ~]# systemctl status rsyslog
● rsyslog.service - System Logging Service
   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2025-04-11 06:33:58 JST; 3s ago
     Docs: man:rsyslogd(8)
           https://www.rsyslog.com/doc/
 Main PID: 2953 (rsyslogd)
    Tasks: 3 (limit: 11272)
   Memory: 1.0M
   CGroup: /system.slice/rsyslog.service
           └─2953 /usr/sbin/rsyslogd -n

Apr 11 06:33:58 workernode1 systemd[1]: rsyslog.service: Succeeded.
Apr 11 06:33:58 workernode1 systemd[1]: Stopped System Logging Service.
Apr 11 06:33:58 workernode1 systemd[1]: Starting System Logging Service...
Apr 11 06:33:58 workernode1 rsyslogd[2953]: [origin software="rsyslogd" swVersion="8.2102.0-5.el8" x-pid="2953" x-info="http>
Apr 11 06:33:58 workernode1 systemd[1]: Started System Logging Service.
Apr 11 06:33:58 workernode1 rsyslogd[2953]: imjournal: journal files changed, reloading...  [v8.2102.0-5.el8 try https://www>
[root@workernode1 ~]#

管理パスワードの設定を行いましょう。slappasswdコマンドで生成したパスワードを設定します。

[root@workernode1 openldap]# vi chrootpw.ldif
[root@workernode1 openldap]# cat chrootpw.ldif
dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW:{SSHA}iJbk98REweIFUvi7MapUUZs0biVkuNv6
[root@workernode1 openldap]#
[root@workernode1 openldap]# ldapadd -Y EXTERNAL -H ldapi:/// -f chrootpw.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={0}config,cn=config"

[root@workernode1 openldap]#

デフォルトで登録されているcoreスキーマ以外の標準スキーマを登録していきます。

[root@workernode1 openldap]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=cosine,cn=schema,cn=config"

[root@workernode1 openldap]#
[root@workernode1 openldap]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=nis,cn=schema,cn=config"

[root@workernode1 openldap]#
[root@workernode1 openldap]# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif

SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=inetorgperson,cn=schema,cn=config"

[root@workernode1 openldap]#

続いてドメインを登録するために、chdomain.ldifファイルを下記の通り作成してください。dcとはDomain Componentの略となりまして、ご自身でしてした名称を指定するようにしてください。

[root@workernode1 openldap]# vi chdomain.ldif
[root@workernode1 openldap]# cat chdomain.ldif
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth"
  read by dn.base="cn=Manager,dc=eeengineer,dc=localdomain" read by * none

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=eeengineer,dc=localdomain

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=eeengineer,dc=localdomain

dn: olcDatabase={2}mdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}7vmZXlKr66RSGAiQi4tR8p2sHJGUguZg

dn: olcDatabase={2}mdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange by
  dn="cn=Manager,dc=eeengineer,dc=localdomain" write by anonymous auth by self write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by dn="cn=Manager,dc=eeengineer,dc=localdomain" write by * read
[root@workernode1 openldap]#

作成したchdomain.ldifファイルを適用します。

[root@workernode1 openldap]# ldapmodify -Y EXTERNAL -H ldapi:/// -f chdomain.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={1}monitor,cn=config"

modifying entry "olcDatabase={2}mdb,cn=config"

modifying entry "olcDatabase={2}mdb,cn=config"

modifying entry "olcDatabase={2}mdb,cn=config"

modifying entry "olcDatabase={2}mdb,cn=config"

[root@workernode1 openldap]#

続いてベースドメインの作成をします。同様にldifファイルを作成して適用します。

[root@workernode1 openldap]# vi basedomain.ldif
[root@workernode1 openldap]# cat basedomain.ldif
dn: dc=eeengineer,dc=localdomain
objectClass: top
objectClass: dcObject
objectclass: organization
o: eeengineer organization
dc: eeengineer

dn: cn=Manager,dc=eeengineer,dc=localdomain
objectClass: organizationalRole
cn: Manager
description: Directory Manager

dn: ou=People,dc=eeengineer,dc=localdomain
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=eeengineer,dc=localdomain
objectClass: organizationalUnit
ou: Group

[root@workernode1 openldap]#
[root@workernode1 openldap]# ldapadd -x -D cn=Manager,dc=eeengineer,dc=localdomain -W -f basedomain.ldif
Enter LDAP Password:
adding new entry "dc=eeengineer,dc=localdomain"

adding new entry "cn=Manager,dc=eeengineer,dc=localdomain"

adding new entry "ou=People,dc=eeengineer,dc=localdomain"

adding new entry "ou=Group,dc=eeengineer,dc=localdomain"

[root@workernode1 openldap]#

ここからは自己証明書を作成して、LDAP通信をSSL/TLS化していきます。ますopenssl.cnfに下記内容を追記してください。subjectAltNameにworkernode1を登録します。

[root@workernode1 openldap]# vi /etc/pki/tls/openssl.cnf
[root@workernode1 openldap]# cat /etc/pki/tls/openssl.cnf
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#

~~Omission~~

#Added
[eeengineer.localdomain]
subjectAltName = DNS:workernode1
[root@workernode1 openldap]# 

秘密鍵を作成して権限を変更します。

[root@workernode1 certs]# openssl genrsa -aes128 2048 > server.key
Generating RSA private key, 2048 bit long modulus (2 primes)
.........................................................+++++
..................................................+++++
e is 65537 (0x010001)
Enter pass phrase:
Verifying - Enter pass phrase:
[root@workernode1 certs]#
[root@workernode1 certs]# openssl rsa -in server.key -out server.key
Enter pass phrase for server.key:
writing RSA key
[root@workernode1 certs]#
[root@workernode1 certs]# chmod 600 server.key
[root@workernode1 certs]#
[root@workernode1 certs]# ls -l server.key
-rw------- 1 root root 1679 Apr  7 06:57 server.key
[root@workernode1 certs]#

自己証明書を作成します。有効期限は10年(3650日)を指定しています。

[root@workernode1 certs]# openssl x509 -in server.csr -out server.crt -req -signkey server.key -days 3650
Signature ok
subject=C = JP, ST = Tokyo, L = Tokyo, O = eeengineer, OU = eeengineer organization, CN = workernode1, emailAddress = eeengineer@gmail.com
Getting Private key
[root@workernode1 certs]#

作成した秘密鍵、証明書等を/etc/openldap/certs配下にコピーして権限を修正します。

[root@workernode1 certs]# cp /etc/pki/tls/certs/server.key \
> /etc/pki/tls/certs/server.crt \
> /etc/pki/tls/certs/ca-bundle.crt \
> /etc/openldap/certs/
[root@workernode1 certs]#
[root@workernode1 certs]# chown ldap. /etc/openldap/certs/server.key \
> /etc/openldap/certs/server.crt \
> /etc/openldap/certs/ca-bundle.crt
[root@workernode1 certs]#
[root@workernode1 certs]# ls -l /etc/openldap/certs/
total 204
-r--r--r-- 1 ldap ldap 200578 Apr  7 07:10 ca-bundle.crt
-rw-r--r-- 1 ldap ldap   1371 Apr  7 07:10 server.crt
-rw------- 1 ldap ldap   1679 Apr  7 07:10 server.key
[root@workernode1 certs]#

証明書関連の設定を記載したldifファイルを作成して適用します。

[root@workernode1 certs]# vi mod_ssl.ldif
[root@workernode1 certs]# cat mod_ssl.ldif
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/certs/ca-bundle.crt
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/server.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/server.key
[root@workernode1 certs]#
[root@workernode1 certs]# ldapmodify -Y EXTERNAL -H ldapi:/// -f mod_ssl.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"

[root@workernode1 certs]#

slapdサービスを再起動してください。

[root@workernode1 certs]# systemctl restart slapd
[root@workernode1 certs]# systemctl status slapd
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2025-04-07 07:11:23 JST; 4s ago
     Docs: man:slapd
           man:slapd-config
           man:slapd-hdb
           man:slapd-mdb
           file:///usr/share/doc/openldap-servers/guide.html
  Process: 33866 ExecStart=/usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:/// (code=exited, status=0/SUCCESS)
  Process: 33851 ExecStartPre=/usr/libexec/openldap/check-config.sh (code=exited, status=0/SUCCESS)
 Main PID: 33867 (slapd)
    Tasks: 2 (limit: 11272)
   Memory: 3.9M
   CGroup: /system.slice/slapd.service
           └─33867 /usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:///

Apr 07 07:11:23 workernode1 systemd[1]: Stopped OpenLDAP Server Daemon.
Apr 07 07:11:23 workernode1 systemd[1]: Starting OpenLDAP Server Daemon...
Apr 07 07:11:23 workernode1 runuser[33854]: pam_unix(runuser:session): session opened for user ldap by (uid=0)
Apr 07 07:11:23 workernode1 runuser[33854]: pam_unix(runuser:session): session closed for user ldap
Apr 07 07:11:23 workernode1 slapd[33866]: @(#) $OpenLDAP: slapd 2.4.46 (Aug 10 2021 05:11:20) $
                                                  mockbuild@x86-02.mbox.centos.org:/builddir/build/BUILD/openldap-2.4.46/openldap-2.4.46/servers/slapd
Apr 07 07:11:23 workernode1 slapd[33867]: slapd starting
Apr 07 07:11:23 workernode1 systemd[1]: Started OpenLDAP Server Daemon.
[root@workernode1 certs]#

続いてユーザを登録していきます。下記サイトに便利なシェルが公開されていたので使ってみます。
https://www.server-world.info/query?os=CentOS_7&p=openldap&f=2

[root@workernode1 openldap]# vi ldapuser.sh
[root@workernode1 openldap]# cat ldapuser.sh
#!/bin/bash

SUFFIX='dc=eeengineer,dc=localdomain'
LDIF='ldapuser.ldif'

echo -n > $LDIF
GROUP_IDS=()
grep "x:[1-9][0-9][0-9][0-9]:" /etc/passwd | (while read TARGET_USER
do
    USER_ID="$(echo "$TARGET_USER" | cut -d':' -f1)"

    USER_NAME="$(echo "$TARGET_USER" | cut -d':' -f5 | cut -d' ' -f1,2)"
    [ ! "$USER_NAME" ] && USER_NAME="$USER_ID"

    LDAP_SN="$(echo "$USER_NAME" | cut -d' ' -f2)"
    [ ! "$LDAP_SN" ] && LDAP_SN="$USER_NAME"

    LASTCHANGE_FLAG="$(grep "${USER_ID}:" /etc/shadow | cut -d':' -f3)"
    [ ! "$LASTCHANGE_FLAG" ] && LASTCHANGE_FLAG="0"

    SHADOW_FLAG="$(grep "${USER_ID}:" /etc/shadow | cut -d':' -f9)"
    [ ! "$SHADOW_FLAG" ] && SHADOW_FLAG="0"

    GROUP_ID="$(echo "$TARGET_USER" | cut -d':' -f4)"
    [ ! "$(echo "${GROUP_IDS[@]}" | grep "$GROUP_ID")" ] && GROUP_IDS=("${GROUP_IDS[@]}" "$GROUP_ID")

    echo "dn: uid=$USER_ID,ou=People,$SUFFIX" >> $LDIF
    echo "objectClass: inetOrgPerson" >> $LDIF
    echo "objectClass: posixAccount" >> $LDIF
    echo "objectClass: shadowAccount" >> $LDIF
    echo "sn: $LDAP_SN" >> $LDIF
    echo "givenName: $(echo "$USER_NAME" | awk '{print $1}')" >> $LDIF
    echo "cn: $USER_NAME" >> $LDIF
    echo "displayName: $USER_NAME" >> $LDIF
    echo "uidNumber: $(echo "$TARGET_USER" | cut -d':' -f3)" >> $LDIF
    echo "gidNumber: $(echo "$TARGET_USER" | cut -d':' -f4)" >> $LDIF
    echo "userPassword: {crypt}$(grep "${USER_ID}:" /etc/shadow | cut -d':' -f2)" >> $LDIF
    echo "gecos: $USER_NAME" >> $LDIF
    echo "loginShell: $(echo "$TARGET_USER" | cut -d':' -f7)" >> $LDIF
    echo "homeDirectory: $(echo "$TARGET_USER" | cut -d':' -f6)" >> $LDIF
    echo "shadowExpire: $(passwd -S "$USER_ID" | awk '{print $7}')" >> $LDIF
    echo "shadowFlag: $SHADOW_FLAG" >> $LDIF
    echo "shadowWarning: $(passwd -S "$USER_ID" | awk '{print $6}')" >> $LDIF
    echo "shadowMin: $(passwd -S "$USER_ID" | awk '{print $4}')" >> $LDIF
    echo "shadowMax: $(passwd -S "$USER_ID" | awk '{print $5}')" >> $LDIF
    echo "shadowLastChange: $LASTCHANGE_FLAG" >> $LDIF
    echo >> $LDIF
done

for TARGET_GROUP_ID in "${GROUP_IDS[@]}"
do
    LDAP_CN="$(grep ":${TARGET_GROUP_ID}:" /etc/group | cut -d':' -f1)"

    echo "dn: cn=$LDAP_CN,ou=Group,$SUFFIX" >> $LDIF
    echo "objectClass: posixGroup" >> $LDIF
    echo "cn: $LDAP_CN" >> $LDIF
    echo "gidNumber: $TARGET_GROUP_ID" >> $LDIF

    for MEMBER_UID in $(grep ":${TARGET_GROUP_ID}:" /etc/passwd | cut -d':' -f1,3)
    do
        UID_NUM=$(echo "$MEMBER_UID" | cut -d':' -f2)
        [ $UID_NUM -ge 1000 -a $UID_NUM -le 9999 ] && echo "memberUid: $(echo "$MEMBER_UID" | cut -d':' -f1)" >> $LDIF
    done
    echo >> $LDIF
done
)
[root@workernode1 openldap]#

シェルを実行してみましょう。uidが1000以上であるeeengineerとpostgresユーザを登録するldifファイルができています。

[root@workernode1 openldap]# sh ldapuser.sh
[root@workernode1 openldap]#
[root@workernode1 openldap]# cat ldapuser.ldif
dn: uid=eeengineer,ou=People,dc=eeengineer,dc=localdomain
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
sn: eeengineer
givenName: eeengineer
cn: eeengineer
displayName: eeengineer
uidNumber: 1000
gidNumber: 1000
userPassword: {crypt}$6$LSrxF/Ufsejhrj7A$UQ8TmbebEJTJcQTZPHgR2bIHgaXuygv0StywziHwbXYfDfrPiywlQMHFoClqxXQbNg4nd7.ugoJQDGaxxCZUa1
gecos: eeengineer
loginShell: /bin/bash
homeDirectory: /home/eeengineer
shadowExpire: -1
shadowFlag: 0
shadowWarning: 7
shadowMin: 0
shadowMax: 99999
shadowLastChange: 20084

dn: uid=postgres,ou=People,dc=eeengineer,dc=localdomain
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
sn: postgres
givenName: postgres
cn: postgres
displayName: postgres
uidNumber: 1001
gidNumber: 1001
userPassword: {crypt}$6$oK1GqGAU7ALEox3y$Adc0HtAvxPxkDQ5X1dSvny1hs54zMLiNm4br2./cUrbhF/nqXsuFKjI6lr2zhUI3BCKyQPUAC7H9y9giSh9OV0
gecos: postgres
loginShell: /bin/bash
homeDirectory: /home/postgres
shadowExpire: -1
shadowFlag: 0
shadowWarning: 7
shadowMin: 0
shadowMax: 99999
shadowLastChange: 20098
c
dn: cn=eeengineer,ou=Group,dc=eeengineer,dc=localdomain
objectClass: posixGroup
cn: eeengineer
gidNumber: 1000
memberUid: eeengineer

dn: cn=postgres,ou=Group,dc=eeengineer,dc=localdomain
objectClass: posixGroup
cn: postgres
gidNumber: 1001
memberUid: postgres

[root@workernode1 openldap]#

ldifファイルを適用します。下記の通りnew entryが追加されていれば成功です。

[root@workernode1 openldap]# ldapadd -x -D cn=Manager,dc=eeengineer,dc=localdomain -W -f ldapuser.ldif
Enter LDAP Password:
adding new entry "uid=eeengineer,ou=People,dc=eeengineer,dc=localdomain"

adding new entry "uid=postgres,ou=People,dc=eeengineer,dc=localdomain"

adding new entry "cn=eeengineer,ou=Group,dc=eeengineer,dc=localdomain"

adding new entry "cn=postgres,ou=Group,dc=eeengineer,dc=localdomain"

[root@workernode1 openldap]#

4. LDAPクライアントの構築

続いてLDAPクライアント側の構築をしていきましょう。LDAP認証を適用するサーバに必要なパッケージをインストールしていきます。今回はLDAPサーバとは別のサーバに設定をしています。

[root@workernode2 ~]# dnf -y install openldap-clients nss-pam-ldapd
Last metadata expiration check: 0:00:33 ago on Sat 12 Apr 2025 06:33:47 AM JST.
Dependencies resolved.
=============================================================================================================================
 Package                           Architecture            Version                          Repository                  Size
=============================================================================================================================
Installing:
 nss-pam-ldapd                     x86_64                  0.9.9-3.el8                      appstream                  189 k
 openldap-clients                  x86_64                  2.4.46-18.el8                    baseos                     202 k
Installing weak dependencies:
 nscd                              x86_64                  2.28-164.el8                     baseos                     133 k

Transaction Summary
=============================================================================================================================
Install  3 Packages

Total download size: 524 k
Installed size: 1.3 M
Downloading Packages:
(1/3): nscd-2.28-164.el8.x86_64.rpm                                                          305 kB/s | 133 kB     00:00
(2/3): nss-pam-ldapd-0.9.9-3.el8.x86_64.rpm                                                  397 kB/s | 189 kB     00:00
(3/3): openldap-clients-2.4.46-18.el8.x86_64.rpm                                             202 kB/s | 202 kB     00:01
-----------------------------------------------------------------------------------------------------------------------------
Total                                                                                        511 kB/s | 524 kB     00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                     1/1
  Running scriptlet: nscd-2.28-164.el8.x86_64                                                                            1/3
  Installing       : nscd-2.28-164.el8.x86_64                                                                            1/3
  Running scriptlet: nscd-2.28-164.el8.x86_64                                                                            1/3
  Running scriptlet: nss-pam-ldapd-0.9.9-3.el8.x86_64                                                                    2/3
  Installing       : nss-pam-ldapd-0.9.9-3.el8.x86_64                                                                    2/3
  Running scriptlet: nss-pam-ldapd-0.9.9-3.el8.x86_64                                                                    2/3
  Installing       : openldap-clients-2.4.46-18.el8.x86_64                                                               3/3
  Running scriptlet: openldap-clients-2.4.46-18.el8.x86_64                                                               3/3
[/usr/lib/tmpfiles.d/nss-pam-ldapd.conf:2] Line references path below legacy directory /var/run/, updating /var/run/nslcd → /run/nslcd; please update the tmpfiles.d/ drop-in file accordingly.

  Verifying        : nss-pam-ldapd-0.9.9-3.el8.x86_64                                                                    1/3
  Verifying        : nscd-2.28-164.el8.x86_64                                                                            2/3
  Verifying        : openldap-clients-2.4.46-18.el8.x86_64                                                               3/3

Installed:
  nscd-2.28-164.el8.x86_64          nss-pam-ldapd-0.9.9-3.el8.x86_64          openldap-clients-2.4.46-18.el8.x86_64

Complete!
[root@workernode2 ~]#

nslcd(Name Service LDAP Daemon)というLDAPを使ってユーザ認証を行うサービスを利用します。nslcd.confにldapサーバのホスト名と、base dc(ドメインコンポーネント)を自身の環境に合わせて変更して下さい。

[root@workernode2 ~]# cp -p /etc/nslcd.conf /etc/nslcd.conf_bk
[root@workernode2 ~]#
[root@workernode2 ~]# vi /etc/nslcd.conf
[root@workernode2 ~]#
[root@workernode2 ~]# diff /etc/nslcd.conf_bk /etc/nslcd.conf
18c18,19
< uri ldap://127.0.0.1/
---
> #uri ldap://127.0.0.1/
> uri ldap://workernode1/
25c26,27
< base dc=example,dc=com
---
> #base dc=example,dc=com
> base dc=eeengineer,dc=localdomain
[root@workernode2 ~]#

nslcdサービスを再起動します。

[root@workernode2 ~]# systemctl restart nslcd.service
[root@workernode2 ~]# systemctl status nslcd.service
● nslcd.service - Naming services LDAP client daemon.
   Loaded: loaded (/usr/lib/systemd/system/nslcd.service; disabled; vendor preset: disabled)
   Active: active (running) since Sat 2025-04-12 07:07:52 JST; 1min 0s ago
     Docs: man:nslcd(8)
           man:nslcd.conf(5)
  Process: 32973 ExecStart=/usr/sbin/nslcd (code=exited, status=0/SUCCESS)
 Main PID: 32975 (nslcd)
    Tasks: 6 (limit: 11272)
   Memory: 3.7M
   CGroup: /system.slice/nslcd.service
           └─32975 /usr/sbin/nslcd

Apr 12 07:07:52 workernode2 systemd[1]: Starting Naming services LDAP client daemon....
Apr 12 07:07:52 workernode2 nslcd[32975]: version 0.9.9 starting
Apr 12 07:07:52 workernode2 nslcd[32975]: accepting connections
Apr 12 07:07:52 workernode2 systemd[1]: Started Naming services LDAP client daemon..
[root@workernode2 ~]#

ここではsuコマンドでユーザスイッチする際の認証に対して、LDAP認証を導入していきます。

[root@workernode2 ~]# cp -p /etc/pam.d/su /etc/pam.d/su_bk
[root@workernode2 ~]#
[root@workernode2 ~]# vi /etc/pam.d/su
[root@workernode2 ~]#
[root@workernode2 ~]# diff /etc/pam.d/su_bk /etc/pam.d/su
3c3
< auth          sufficient      pam_rootok.so
---
> #auth         sufficient      pam_rootok.so
7a8
> auth            sufficient      pam_ldap.so
[root@workernode2 ~]#

4. LDAP認証(ログイン)の動作確認

クライアント側でsuコマンドを実行し、LDAP認証対象のユーザにスイッチしてみて下さい。

[root@workernode2 ~]# su - eeengineer
Password:
[eeengineer@workernode2 ~]$

LDAPサーバ側でslapd.logの内容を確認してみてください。いろいろ出力されますが、err=0となっていれば認証に成功しています。

[root@workernode1 openldap]# tail -f /var/log/slapd/slapd.log

Apr 12 16:18:49 workernode1 slapd[1172]: conn=1006 op=7 SRCH base="dc=eeengineer,dc=localdomain" scope=2 deref=0 filter="(&(objectClass=posixAccount)(uid=eeengineer))"
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1006 op=7 SRCH attr=uid uidNumber
Apr 12 16:18:49 workernode1 slapd[1172]: <= mdb_equality_candidates: (uid) not indexed
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1006 op=7 SEARCH RESULT tag=101 err=0 nentries=1 text=
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 fd=18 ACCEPT from IP=192.168.56.103:47932 (IP=0.0.0.0:389)
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=0 BIND dn="uid=eeengineer,ou=People,dc=eeengineer,dc=localdomain" method=128
Apr 12 16:18:49 workernode1 slapd[1172]: slap_global_control: unrecognized control: 1.3.6.1.4.1.42.2.27.8.5.1
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=0 BIND dn="uid=eeengineer,ou=People,dc=eeengineer,dc=localdomain" mech=SIMPLE ssf=0
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=0 RESULT tag=97 err=0 text=
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=1 SRCH base="uid=eeengineer,ou=People,dc=eeengineer,dc=localdomain" scope=0 deref=0 filter="(objectClass=*)"
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=1 SRCH attr=dn
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=2 ABANDON msg=2
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 op=3 UNBIND
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1009 fd=18 closed
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1006 op=8 SRCH base="dc=eeengineer,dc=localdomain" scope=2 deref=0 filter="(&(objectClass=shadowAccount)(uid=eeengineer))"
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1006 op=8 SRCH attr=shadowFlag shadowMax shadowMin shadowLastChange uid shadowExpire shadowInactive shadowWarning
Apr 12 16:18:49 workernode1 slapd[1172]: <= mdb_equality_candidates: (uid) not indexed
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1006 op=8 SEARCH RESULT tag=101 err=0 nentries=1 text=
Apr 12 16:18:49 workernode1 slapd[1172]: conn=1006 op=9 ABANDON msg=9

続いて、OpenLDAPサーバが正常に稼働していない場合にどのようになるのか挙動を見てみましょう。
まず、LDAPサーバのslapdサービスを停止します。

[root@workernode1 ~]# systemctl stop slapd
[root@workernode1 ~]# systemctl status slapd
● slapd.service - OpenLDAP Server Daemon
   Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since Sat 2025-04-12 17:04:25 JST; 3s ago
     Docs: man:slapd
           man:slapd-config
           man:slapd-hdb
           man:slapd-mdb
           file:///usr/share/doc/openldap-servers/guide.html
  Process: 3252 ExecStart=/usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:/// (code=exited, status=0/SUCCESS)
  Process: 3238 ExecStartPre=/usr/libexec/openldap/check-config.sh (code=exited, status=0/SUCCESS)
 Main PID: 3253 (code=exited, status=0/SUCCESS)

Apr 12 17:04:25 workernode1 slapd[3253]: daemon: shutdown requested and initiated.
Apr 12 17:04:25 workernode1 slapd[3253]: conn=1000 fd=15 closed (slapd shutdown)
Apr 12 17:04:25 workernode1 slapd[3253]: conn=1002 fd=18 closed (slapd shutdown)
Apr 12 17:04:25 workernode1 slapd[3253]: conn=1004 fd=19 closed (slapd shutdown)
Apr 12 17:04:25 workernode1 slapd[3253]: conn=1005 fd=20 closed (slapd shutdown)
Apr 12 17:04:25 workernode1 slapd[3253]: conn=1006 fd=21 closed (slapd shutdown)
Apr 12 17:04:25 workernode1 slapd[3253]: slapd shutdown: waiting for 0 operations/tasks to finish
Apr 12 17:04:25 workernode1 slapd[3253]: slapd stopped.
Apr 12 17:04:25 workernode1 systemd[1]: slapd.service: Succeeded.
Apr 12 17:04:25 workernode1 systemd[1]: Stopped OpenLDAP Server Daemon.
[root@workernode1 ~]#

続いて、先ほどと同様にLDAPクライアント側でsuコマンドを実行します。今度はAuthentication failureのメッセージが出てユーザスイッチできないはずです。

[root@workernode2 ~]# su - eeengineer
Password:
su: Authentication failure
[root@workernode2 ~]#

LDAPクライアント側のシスログを確認してください。LDAPサーバにアクセスできない旨のメッセージが出力されるはずです。

[root@workernode2 ~]# tail -f /var/log/messages
Apr 12 16:24:33 workernode2 nslcd[2941]: [495cff] <authc="eeengineer"> failed to bind to LDAP server ldap://workernode1/: Can't contact LDAP server: Transport endpoint is not connected
Apr 12 16:24:33 workernode2 nslcd[2941]: [495cff] <authc="eeengineer"> no available LDAP server found: Can't contact LDAP server: Transport endpoint is not connected
Apr 12 16:24:35 workernode2 su[3252]: FAILED SU (to eeengineer) root on pts/0

5. まとめ

LDAPサーバ、LDAPクライアントの構築方法の概要は以上となります。セキュリティ要件の高いシステムにおいてユーザ管理は非常に重要な要素となりますので、ぜひLDAPの仕組みを理解して導入を検討してみてはいかがかと思います。

6. 参考文献

コメント