[openldap 2.4]ldapadd, ldapmodify, ldapsearch, phpldapadminでユーザ追加, LDAPユーザアカウントでSSHログイン

+ **この記事のMISSION**
 - openldapをインストールし,ldapadd/ldapmodifyでLDAPサーバの基本設定をする
 - phpldapadminを利用し, LDAPユーザを作成する
 - LDAPユーザアカウントでSSHログインする 
+ **サーバ環境**
 - `CentOS Linux release 7.6.1810`
 - `openldap-servers-2.4.44-21.el7_6.x86_64`
 - `openldap-clients-2.4.44-21.el7_6.x86_64`
 - `phpldapadmin-1.2.3-10.el7.noarch`

May 4, 2020 @pa_pa_paper

# LDAPサーバセットアップ
## openldapインストール
+ yumでopenldapの関連pkgをインストール
 - `openldap-servers`と`openldap-clients`をインストールする
 - 依存関係で`libtool-ltdl`というpkgもインストールされる

```
# yum install openldap-servers openldap-clients
~
~
Dependencies Resolved

===============================================================================================================
 Package                        Arch                 Version                          Repository          Size
===============================================================================================================
Installing:
 openldap-clients               x86_64               2.4.44-21.el7_6                  base               190 k
 openldap-servers               x86_64               2.4.44-21.el7_6                  base               2.2 M
Installing for dependencies:
 libtool-ltdl                   x86_64               2.4.2-22.el7_3                   base                49 k

Transaction Summary
===============================================================================================================
Install  2 Packages (+1 Dependent package)

Total download size: 2.4 M
Installed size: 5.7 M
Is this ok [y/d/N]:
```


+ インストールしたpkgのバージョン確認

```
# rpm -qa | grep openldap*
openldap-2.4.44-21.el7_6.x86_64
openldap-clients-2.4.44-21.el7_6.x86_64
openldap-servers-2.4.44-21.el7_6.x86_64
```


## LDAPサーバ基本設定
+ slapd起動前にDBのチューニング設定をする
 - slapdのDBファイルは`/var/lib/ldap`配下に作成される
 - `/var/lib/ldap`配下にDBチューニングのための設定ファイルを配置する
 - サンプルファイル(DB_CONFIG.example)が準備されているため, そのままコピーして利用する

```
# cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/
# ll /var/lib/ldap/
total 4
-rw-r--r-- 1 root root 845 May  4 16:46 DB_CONFIG.example
```

+ slapd起動/自動起動設定

```
# systemctl start slapd
# systemctl enable slapd
```

こんな感じ↓で`/usr/sbin/slapd`が稼動していたらok.

```
# ps aux | grep slapd
ldap      5178  0.0  1.6 114980  8424 ?        Ssl  16:49   0:00 /usr/sbin/slapd -u ldap -h ldapi:/// ldap:///
```


## LDAP DB設定
openldapの設定は設定ファイルをテキストエディタで直接編集するのではなく, ldapadd, ldapmodify等LDAPクライアントユーティリティを利用する.

+ ldapsearchでデフォルト設定を確認

```
# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'olcDatabase={2}hdb,cn=config'
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=my-domain,dc=com
olcRootDN: cn=Manager,dc=my-domain,dc=com
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
```

+ LDAPディレクトリツリーのDN(olcSuffix)設定変更

デフォルト設定
`olcSuffix: dc=my-domain,dc=com`


+ 管理用の特権DN(olcRootDN)設定変更

デフォルト設定
`olcRootDN: cn=Manager,dc=my-domain,dc=com`

+ 特権DNのパスワード(olcRootPW)設定変更

特権DNのパスワードは`slappasswd`コマンドで生成
*ソルト付きのハッシュパスワードが生成される

```
# slappasswd
New password:
Re-enter new password:
{SSHA}xxxx
```

作業用ディレクトリ配下に`hdb-init.ldif`ファイルを作成する

```hdb-init.ldif
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp

-

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp

-

dn: olcDatabase={2}hdb,cn=config
add: olcRootPW
olcRootPW: {SSHA}xxxx
```

ldapmodifyコマンドでldifファイルを指定し, 設定変更

```
# ldapmodify -Y EXTERNAL -H ldapi:/// -f hdb-init.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={2}hdb,cn=config"

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

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

こんな感じ↓でDB設定が変更される

```
# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'olcDatabase={2}hdb,cn=config'
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
olcRootPW: {SSHA}xxxx
olcSuffix: dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
olcRootDN: cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
```


## LDAPスキーマ登録

LDAPスキーマはLDAP DBのエントリに登録できるデータの種類/型を定義する.
`/etc/openldap/schema/`配下にスキーマ登録に利用するldifファイルがある.

```
# ls /etc/openldap/schema/
collective.ldif    core.schema     dyngroup.ldif         java.schema  openldap.ldif    ppolicy.schema
collective.schema  cosine.ldif     dyngroup.schema       misc.ldif    openldap.schema
corba.ldif         cosine.schema   inetorgperson.ldif    misc.schema  pmi.ldif
corba.schema       duaconf.ldif    inetorgperson.schema  nis.ldif     pmi.schema
core.ldif          duaconf.schema  java.ldif             nis.schema   ppolicy.ldif
```

デフォルトでは`core`スキーマしか利用できないため, `nis`, `cosine`スキーマを追加登録する
*nisはユーザを管理するためのスキーマ. nisの依存でcosineも必要になる.

+ cosine, nis, inetOrgPersonスキーマの登録

```
# 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"

# 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"

# 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"
```


## LDAPエントリ登録

+ 基本組織, 特権DN, ユーザアカウント組織, グループ組織を登録

```base.ldif
dn: dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectClass: dcObject
objectClass: organization
dc: xxxx
o: xxxx

-

dn: cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectclass: organizationalRole
cn: Manager

-

dn: ou=People,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectClass: organizationalUnit
ou: People

-

dn: ou=Group,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectClass: organizationalUnit
ou: Group
```

`dn: dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp`・・・xxxx.vs.sakura.ne.jp組織の基本となるエントリ
`dn: cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp`・・・特権DNのエントリ
`dn: ou=People,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp`・・・ユーザを管理する組織単位
`dn: ou=Group,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp`・・・グループを管理する組織単位

毎度のことながらldapaddコマンドでLDAPエントリを登録.

```
# ldapadd -x -D "cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp" -W -f b
ase.ldif
Enter LDAP Password:
adding new entry "dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp"

adding new entry "cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp"

adding new entry "ou=People,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp"

adding new entry "ou=Group,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp"
```

ちゃんとエントリが登録されたか確認.

```
# ldapsearch -x -LLL -b "dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp" "(objectCl
ass=*)"
dn: dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectClass: dcObject
objectClass: organization
dc: xxxx
o: xxxx

dn: cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectClass: organizationalRole
cn: Manager

dn: ou=People,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
objectClass: organizationalUnit
ou: Group
```

真面目にldifファイル作成 -> ldapaddコマンドで登録でもいいけど, ldifファイルを作成するのが少々手間なので**PhpLDAPadmin**というLDAPデータ管理用のWeb U/Iをインストールする.
*httpdとかphpが依存関係で必要になる

# PhpLDAPadminでユーザ追加
## phpldapadminインストール

```
# yum install phpldapadmin.noarch
```
```
# rpm -qa | grep phpldapadmin
phpldapadmin-1.2.3-10.el7.noarch
```

phpldapadminをインストールすると, 自動的に`/etc/httpd/conf.d/phpldapadmin.conf`が作成される.

デフォルト設定

```/etc/httpd/conf.d/phpldapadmin.conf
#
#  Web-based tool for managing LDAP servers
#

Alias /phpldapadmin /usr/share/phpldapadmin/htdocs
Alias /ldapadmin /usr/share/phpldapadmin/htdocs

<Directory /usr/share/phpldapadmin/htdocs>
  <IfModule mod_authz_core.c>
    # Apache 2.4
    Require local
  </IfModule>
  <IfModule !mod_authz_core.c>
    # Apache 2.2
    Order Deny,Allow
    Deny from all
    Allow from 127.0.0.1
    Allow from ::1
  </IfModule>
</Directory>
```

+ Apache 2.4の場合は`Require ip`等でアクセス許可設定を追加

```/etc/httpd/conf.d/phpldapadmin.conf
  <IfModule mod_authz_core.c>
    # Apache 2.4
    # Require local
    Require ip xxx.xxx.xxx.xxx
  </IfModule>
```

+ 特権DNでログインするため`/etc/phpldapadmin/config.php`も変更

```/etc/phpldapadmin/config.php 
# diff -u /etc/phpldapadmin/config.php.org /etc/phpldapadmin/config.php
--- /etc/phpldapadmin/config.php.org    2020-05-04 18:19:53.042332321 +0900
+++ /etc/phpldapadmin/config.php        2020-05-04 18:47:51.484235633 +0900
@@ -394,8 +394,8 @@
    Leave blank or specify 'dn' to use full DN for logging in. Note also that if
    your LDAP server requires you to login to perform searches, you can enter the
    DN to use when searching in 'bind_id' and 'bind_pass' above. */
-// $servers->setValue('login','attr','dn');
-$servers->setValue('login','attr','uid');
+$servers->setValue('login','attr','dn');
+//$servers->setValue('login','attr','uid');

 /* Base DNs to used for logins. If this value is not set, then the LDAP server
    Base DNs are used. */
```

+ httpdの構文チェックと設定反映

```
# httpd -t
Syntax OK
# apachectl graceful
```

## phpldapadminにブラウザアクセス

+ phpldapadminのログイン画面にアクセス

phpLDAPadmin (1.2.3) - 
http://xxxx.vs.sakura.ne.jp/phpldapadmin/

+ ログイン 
 - ログインDN `cn=Manager,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp`
 - パスワード `特権DNのパスワード`

*TLS/SSL対応していないと「警告: このウェブ接続は暗号化されていません.」とエラー表示されるが, ログイン後の使用感には影響しない.

+ 以下テンプレートを利用して**Posix Group**と**User Account**を追加
 - `Generic: Posix Group`
 - `Generic: User Account` 

*Posix Groupも追加しないと下記エラーメッセージが表示される.
`テンプレート値のエラー
This template uses a selection list for attribute [gidNumber], however the selection list is empty.
You may need to create some dependancy entries in your LDAP server so that this attribute renders with values. Alternatively, you may be able to define the appropriate selection values in the template file.`

+ ldapsearchでユーザが作成できたか確認

```
# ldapsearch -x -LLL -b "dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp" "(uid=*)"
dn: cn=Woody,ou=People,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
givenName: Woody
sn: Woody
cn: Woody
uid: woody
userPassword:: xxxx
gidNumber: 500
homeDirectory: /home/woody
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
uidNumber: 1002
loginShell: /bin/bash

dn: cn=buzz,ou=People,dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp
givenName: buzz
sn: buzz
cn: buzz
uid: buzz
userPassword:: xxxx
gidNumber: 500
homeDirectory: /home/buzz
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
uidNumber: 1003
loginShell: /bin/bash
```


## LDAPユーザーストア設定

+ nss-pam-ldapdインストール

nss-pam-ldapdはユーザがローカルのldapクエリを実行できるようにするローカルldapネームサービス.

```
# yum install nss-pam-ldapd
```
```
# rpm -qa | grep nss-pam-ldapd
nss-pam-ldapd-0.8.13-22.el7.x86_64
```

+ authconfigコマンドでLDAPユーザストアの接続情報を設定

```
# authconfig --enableldap --enableldapauth --ldapserver=xxx.xxx.xxx.xxx --ldapbasedn="dc=xxxx,dc=vs,dc=sakura,dc=ne,dc=jp" --update
```

## ホームディレクトリ自動作成設定

+ oddjob-mkhomedirインストール

oddjob-mkhomedirはホームディレクトリ作成のoddjobヘルパー.

```
# yum install oddjob-mkhomedir
```
```
# rpm -qa | grep oddjob-mkhomedir
oddjob-mkhomedir-0.31.5-4.el7.x86_64
```

+ authconfigコマンドでホームディレクトリ作成を有効化

```
# authconfig --enablemkhomedir --update
```

+ oddjobd起動/自動起動設定

```
# systemctl start oddjobd
# systemctl enable oddjobd
```

# LDAPユーザアカウントでSSHログイン

+ ひとまず作成したLDAPユーザアカウントにユーザ切り替えできるか確認

```
# su - woody
Creating home directory for woody.
```

**Creating home directory for woody.**と表示されたので, ホームディレクトリが自動作成できたようです. pwd, idコマンドで現在位置, ユーザ情報を確認してみる.

```
$ pwd
/home/woody
$ id woody
uid=1002(woody) gid=500(toystory) groups=500(toystory)
```

*`/etc/nsswitch.conf`の設定を見てみると, 下記のように書換えされていました. 

```/etc/nsswitch.conf
# diff -u /etc/nsswitch.conf.bak /etc/nsswitch.conf
--- /etc/nsswitch.conf.bak      2019-04-10 01:36:08.000000000 +0900
+++ /etc/nsswitch.conf  2020-05-05 11:24:02.929418319 +0900
@@ -30,13 +30,13 @@
 #shadow:    db files nisplus nis
 #group:     db files nisplus nis

-passwd:     files sss
-shadow:     files sss
-group:      files sss
+passwd:     files sss ldap
+shadow:     files sss ldap
+group:      files sss ldap
 #initgroups: files sss

 #hosts:     db files nisplus nis dns
-hosts:      files dns
+hosts:      files dns myhostname

 # Example - obey only what nisplus tells us...
 #services:   nisplus [NOTFOUND=return] files
@@ -55,10 +55,10 @@
 rpc:        files
 services:   files sss

-netgroup:   nisplus sss
+netgroup:   files sss ldap

 publickey:  nisplus

-automount:  files nisplus sss
+automount:  files ldap
 aliases:    files nisplus
```

+ LDAPユーザアカウントでSSHログイン

```
Creating home directory for buzz.

SAKURA Internet [Virtual Private Server SERVICE]

$ pwd
/home/buzz
$ id
uid=1003(buzz) gid=500(toystory) groups=500(toystory)
```