LDAP2.4でslapd.confを使わずにパスワードポリシーを適用させる

#はじめに
現在のLDAP/openLDAPのバージョンだとかつてあったslapd.confファイルはなくなり、LDAPの設定はslapd.d内のスキーマファイルで管理されている。
LDAPアカウントにパスワードポリシーを適用させる必要が出てきたが、既存記事だとslapd.confファイルをダミー化させてパスワードポリシーを適用させるという方法が多かった。
今回はその方法を取らず、シンプルにスキーマをいじってポリシーをいじって適用させる手順を記録する。

#ゴール
ldap2.4にパスワードポリシー を適用させる

#ポリシースキーマの有効化
デフォルトではポリシーは無効化されているので、まずはそれを有効化させる。

```
$ldapmodify -x -a -H ldap：/// -D cn=admin、dc=domain,dc=net -W -f/etc/ldap/schema/ppolicy.ldif
```

スキーマが有効化されていることを確認する

```
$ldapsearch -Q -LLL -H ldapi:/// -Y EXTERNAL -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}ppolicy,cn=schema,cn=config

dn: cn={5}dhcp,cn=schema,cn=config

dn: cn={6}dnszone,cn=schema,cn=config

dn: cn={7}mail,cn=schema,cn=config

dn: cn={8}mmc,cn=schema,cn=config

dn: cn={9}openssh-lpk,cn=schema,cn=config

dn: cn={10}quota,cn=schema,cn=config

dn: cn={11}radius,cn=schema,cn=config

dn: cn={12}samba,cn=schema,cn=config

dn: cn={13}zarafa,cn=schema,cn=config

```

#オーバーレイの有効化
オーバーレイを適用化させるファイルを作成

```
$vi ppolicy-module.ldif

dn: cn=module{0},cn=config
changeType: modify
add: olcModuleLoad
olcModuleLoad: ppolicy
```

これをldapmodifyコマンドで適用させる

```
$ldapmodify -x -H ldap:/// -D cn=admin,dc=domain,dc=net -W -f ppolicy-module.ldif
```

モジュールが有効化されているかの確認

```
$ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b "cn=config" "(objectClass=olcModuleList)"

dn: cn=module{0},cn=config
olcModuleLoad: {0}back_mdb
olcModuleLoad: {1}ppolicy
```

#オーバーレイの中身設定

オーバーレイの中身を定義するファイルを作成する

```
$vi ppolicy-conf.ldif

dn: olcOverlay=ppolicy,olcDatabase={1}hdb,cn=config
objectClass: olcPpolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=ppolicy,dc=domain,dc=net
olcPPolicyUseLockout: FALSE
olcPPolicyHashCleartext: TRUE
```

上記の設定を適用させる

```
$ldapmodify -x -a -H ldap:/// -D cn=admin,dc=domain,dc=net -W -f ppolicy-conf.ldif
```

設定の確認

```
$ldapsearch -x -H ldap:/// -D cn=admin,dc=domain,dc=net -W -b cn=config "(objectClass=olcPpolicyConfig)" -LLL

dn: olcOverlay={0}ppolicy,olcDatabase={1}hdb,cn=config
objectClass: olcPPolicyConfig
olcOverlay: {0}ppolicy
olcPPolicyDefault: cn=ppolicy,dc=ldaptuto,dc=net
olcPPolicyHashCleartext: TRUE
olcPPolicyUseLockout: FALSE
```

#パスワードポリシーの中身を定義する
パスワードポリシーの定義ファイルを作成する

```
$vi ppolicy-defaut.ldif

dn: cn=ppolicy,dc=gauss,dc=local
objectClass: top
objectClass: inetOrgPerson
objectClass: pwdPolicyChecker
objectClass: pwdPolicy
cn: ppolicy
sn: ppolicy
pwdAttribute: userPassword
pwdMaxFailure: 3
pwdMustChange: FALSE
pwdMinLength: 8
pwdInHistory: 1
pwdCheckQuality: 1
pwdMinAge: 0
pwdLockout: TRUE
pwdMaxAge: 0
pwdExpireWarning: 0
pwdReset: FALSE
pwdLockoutDuration: 600
pwdGraceAuthNLimit: 3
```

具体的なオプションの意味は参考ページを参照してください

定義ファイルを適用させる

```
$ldapadd -H ldapi:/// -D "cn=admin,dc=gauss,dc=local" -W -f ppolicy-default.ldif
```

適用されたかを確認する

```
$ldapsearch -x -H ldap:/// -D cn=admin,dc=domain,dc=local -W -b dc=domain,dc=local "(objectClass=pwdPolicy)" -LLL

dn: cn=ppolicy,dc=gauss,dc=local
objectClass: top
objectClass: inetOrgPerson
objectClass: pwdPolicyChecker
objectClass: pwdPolicy
cn: ppolicy
sn: ppolicy
pwdAttribute: userPassword
pwdMaxFailure: 3
pwdMustChange: FALSE
pwdMinLength: 8
pwdInHistory: 1
pwdCheckQuality: 1
pwdMinAge: 0
pwdLockout: TRUE
pwdMaxAge: 0
pwdExpireWarning: 0
pwdReset: FALSE
pwdLockoutDuration: 600
pwdGraceAuthNLimit: 3
```

これで適用完了

#本当に適用されているかを確認する

パスワードを変えてみる

```
$ldappasswd -x -D 'cn=user,ou=people,dc=domain,dc=net' -W -S
```

今回、パスワードの最低文字数が8なので、8未満だとポリシー違反で弾かれ、8以上だと設定変更できる、はず

#ポリシーを変更してみる
一度適用させたポリシーを変更させるファイルを作成し、適用させる

```
$vi ppolicy-modify.ldif

dn: dc=domain,dc=net
changetype: modify
replace: pwdMaxAge
pwdMaxAge: 3600

$ldapmodify -x -D "cn=admin,dc=domain,dc=local" -W -f ppolicy-modify.ldif
```

#ロックアウトされたアカウントを解除する
pwdLockoutがTRUEだとパスワードを複数回間違えた際にロックされる

そのロックの解除方法

```
#ロックされたアカウントの確認
$ldapsearch -x -D "cn=admin,dc=domain,dc=net" -W -b "dc=domain,dc=net" pwdAccountLockedTime=* pwdAccountLockedTime

#ロック解除のファイルを作成、適用
$vi ppolicy-unlock.ldif

dn:uid=user,ou=people,dc=domain,dc=net
changetype:modify
delete: pwdAccountLockedTime

$ldapmodify -x -D "cn=admin,dc=domain,dc=net" -W -f ppolicy-unlock.ldif

#解除されたかを確認
$ldapsearch -x -D "cn=admin,dc=domain,dc=net" -W -b "dc=domain,dc=net" pwdAccountLockedTime=* pwdAccountLockedTime
```

#おまけ
普段のLDAP操作はphpldapadminを使用している
ldappasswdコマンドではパスワードポリシーは適用されるが、phpldapadmin上でユーザーがパスワードを変更する際、パスワードが暗号化されているとポリシーチェックにおいて文字数を数えられなくなってしまう
ポリシーを適用させるためには、[ssha]などのハッシュを無くし、平文で保存する[clear]を選択する必要がある

しかしパスワードの平文保存をするのは、これはこれでセキュリティ的にもどうなの？というところもあるため、
なにかもっといい方法がないか要審議

ご注意を

#終わりに
コマンド実行時はSASL認証とadminアカウントでの認証どちらかでしか通らなかったりしてその違いがまだよくわからず、理解がまだ足りない。
ldapの情報自体少なくここまでくるのに時間がかかってしまったが、なんとか設定できてよかった
今後はロックされたアカウントを解除させるシェルを作ったり、パスワード期限が近づいた際にアラートを発信できるようにしたい

#参考ページ
[OpenLDAP password policy](http://tutoriels.meddeb.net/openldap-password-policy-managing-users-accounts/)
[パスワードポリシーの詳細](http://www.zytrax.com/books/ldap/ch6/ppolicy.html)
[LDAPのデータ更新](https://qiita.com/tkj/items/8e2e992280f933dbae7c)
[LDAP パスワードポリシーについて](https://memo.wakaue.info/memo/ldap-password-policy/)