OpenLDAP 密码策略深度配置与审计日志管理指南
一、 密码策略核心机制
OpenLDAP 通过 ppolicy 覆盖(overlay)提供了一套完善的密码管理机制。该机制不仅涵盖了密码的生命周期管理,还支持密码历史记录、强度校验、失败锁定以及宽限期登录等高级特性。策略可以灵活地应用于整个目录信息树(DIT)、特定的组织单元(OU)或单个用户。
1. 核心策略属性解析
在配置密码策略时,主要依赖 pwdPolicy 对象类中的属性。以下是关键属性的详细说明:
- pwdAttribute:指定应用策略的密码属性,通常为
userPassword。 - pwdMinAge / pwdMaxAge:定义密码的最短和最长使用期限(单位为秒)。
- pwdInHistory:记录密码历史数量,防止用户循环使用旧密码。
- pwdMinLength:限制密码的最小字符长度。
- pwdMaxFailure / pwdLockout / pwdLockoutDuration:控制连续认证失败的最大次数、是否启用账户锁定以及锁定的持续时间。
- pwdGraceAuthNLimit:密码过期后,允许用户进行"宽限登录"的次数。
- pwdMustChange / pwdSafeModify:控制用户重置密码后是否必须修改,以及修改时是否需要提供旧密码。
2. Shadow 账户属性辅助控制
除了 ppolicy,结合 shadowAccount 对象类可以实现更细粒度的过期控制,尤其在兼容 Linux PAM 认证时非常有效:
- shadowLastChange:自 1970-01-01 起至最近一次密码修改的天数。设为
0可强制用户下次登录时修改密码。 - shadowMin / shadowMax:密码修改的最小间隔天数和最大有效天数。
- shadowWarning:密码过期前提前警告的天数。
- shadowInactive:密码过期后,账户被彻底禁用前允许的宽限天数。
二、 服务端密码策略配置实战
1. 启用 ppolicy 模块与 Overlay
首先,需要确保 ppolicy 模块已加载,并在目标数据库上启用该 overlay。
# 检查当前已加载的模块
$ ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=module{0},cn=config olcModuleLoad
# 加载 ppolicy 模块
$ cat << 'EOF' | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.la
EOF
# 在 mdb 数据库上配置 ppolicy overlay
$ cat << 'EOF' | ldapadd -Y EXTERNAL -H ldapi:///
dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=standard,ou=policies,dc=mydomain,dc=net
olcPPolicyHashCleartext: TRUE
olcPPolicyUseLockout: TRUE
EOF
2. 创建策略容器与具体策略
在目录树中创建一个专门的 OU 来存放密码策略,并定义不同安全级别的策略条目。
# 创建策略容器
$ cat << 'EOF' | ldapadd -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: ou=policies,dc=mydomain,dc=net
objectClass: organizationalUnit
ou: policies
EOF
# 创建标准用户密码策略
$ cat << 'EOF' | ldapadd -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: cn=standard,ou=policies,dc=mydomain,dc=net
objectClass: pwdPolicy
objectClass: person
cn: standard
sn: Policy
pwdAttribute: userPassword
pwdMinAge: 0
pwdMaxAge: 7776000
pwdMinLength: 8
pwdInHistory: 5
pwdCheckQuality: 2
pwdMaxFailure: 5
pwdLockout: TRUE
pwdLockoutDuration: 600
pwdGraceAuthNLimit: 3
pwdFailureCountInterval: 300
pwdMustChange: TRUE
pwdAllowUserChange: TRUE
pwdSafeModify: FALSE
EOF
# 创建高权限管理员密码策略(更严格的过期和长度限制)
$ cat << 'EOF' | ldapadd -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: cn=privileged,ou=policies,dc=mydomain,dc=net
objectClass: pwdPolicy
objectClass: person
cn: privileged
sn: Policy
pwdAttribute: userPassword
pwdMinAge: 86400
pwdMaxAge: 2592000
pwdMinLength: 12
pwdInHistory: 10
pwdCheckQuality: 2
pwdMaxFailure: 3
pwdLockout: TRUE
pwdLockoutDuration: 1800
pwdGraceAuthNLimit: 0
pwdMustChange: TRUE
pwdAllowUserChange: TRUE
pwdSafeModify: TRUE
EOF
3. 将策略绑定至用户
通过修改用户的 pwdPolicySubentry 属性,将其指向特定的策略 DN。如果不指定,则使用 overlay 中配置的默认策略。
$ cat << 'EOF' | ldapmodify -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: uid=jdoe,ou=users,dc=mydomain,dc=net
changetype: modify
add: pwdPolicySubentry
pwdPolicySubentry: cn=standard,ou=policies,dc=mydomain,dc=net
EOF
4. 强制用户首次登录修改密码
有两种常用方式可以实现此需求:
方式一:使用 pwdReset 属性
$ cat << 'EOF' | ldapmodify -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: uid=jdoe,ou=users,dc=mydomain,dc=net
changetype: modify
replace: pwdReset
pwdReset: TRUE
EOF
方式二:利用 shadowLastChange 属性(推荐用于 Linux SSH 登录场景)
$ cat << 'EOF' | ldapmodify -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: uid=jdoe,ou=users,dc=mydomain,dc=net
changetype: modify
replace: shadowLastChange
shadowLastChange: 0
EOF
5. 客户端登录验证
当用户通过 SSH 首次登录客户端时,系统会拦截认证并要求重置密码。如果输入的新密码不符合策略(如长度不足或缺少复杂度),修改将被拒绝。
$ ssh jdoe@192.168.10.50
jdoe@192.168.10.50's password:
You are required to change your password immediately (administrator enforced).
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user jdoe.
(current) LDAP Password:
New password:
Retype new password:
passwd: Authentication token manipulation error
输入符合策略的强密码后,即可成功完成修改并登录系统。
三、 增强密码复杂度校验 (pqchecker)
OpenLDAP 原生的 pwdCheckQuality 仅能校验密码长度。若要实现包含大小写字母、数字和特殊字符的复杂规则,需引入第三方模块如 pqchecker。
1. 安装与配置 pqchecker
# 下载并安装 pqchecker RPM 包
$ sudo yum localinstall -y pqchecker-2.0.0-1.el7.x86_64.rpm
# 查看默认规则配置文件
$ cat /etc/openldap/pqchecker/pqparams.dat | grep -v "^#"
0|01010101
# 规则解析:01 01 01 01 分别代表至少需要 1个大写字母、1个小写字母、1个数字、1个特殊字符。
2. 将 pqchecker 集成到密码策略
$ cat << 'EOF' | ldapmodify -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: cn=standard,ou=policies,dc=mydomain,dc=net
changetype: modify
replace: pwdCheckQuality
pwdCheckQuality: 2
-
add: objectClass
objectClass: pwdPolicyChecker
-
add: pwdCheckModule
pwdCheckModule: pqchecker.so.2.0.0
EOF
配置完成后,用户在修改密码时,pqchecker 会拦截请求并根据 pqparams.dat 中的规则进行严格校验。
四、 启用审计日志 (Auditlog)
为了满足安全合规要求,记录用户对密码及属性的修改操作至关重要。可以通过加载 auditlog overlay 来实现。
# 加载 auditlog 模块
$ cat << 'EOF' | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: auditlog.la
EOF
# 配置 auditlog overlay 并指定日志文件路径
$ cat << 'EOF' | ldapadd -Y EXTERNAL -H ldapi:///
dn: olcOverlay=auditlog,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcAuditLogConfig
olcOverlay: auditlog
olcAuditlogFile: /var/log/openldap/audit.log
EOF
# 确保 openldap 用户对日志文件有写入权限
$ sudo touch /var/log/openldap/audit.log
$ sudo chown ldap:ldap /var/log/openldap/audit.log
五、 常见密码故障排查与恢复
1. 账户因密码错误次数过多被锁定
当用户连续输错密码触发 pwdMaxFailure 时,系统会在用户条目中自动添加 pwdAccountLockedTime 属性。管理员可通过删除该属性来手动解锁。
$ cat << 'EOF' | ldapmodify -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: uid=jdoe,ou=users,dc=mydomain,dc=net
changetype: modify
delete: pwdAccountLockedTime
EOF
2. 密码过期导致无法登录
如果用户密码已过期且宽限期结束,最直接的重置方法是清除旧的 userPassword 并重新赋值,同时重置相关的时间戳属性。
$ cat << 'EOF' | ldapmodify -x -D "cn=admin,dc=mydomain,dc=net" -W -H ldap://localhost
dn: uid=jdoe,ou=users,dc=mydomain,dc=net
changetype: modify
delete: userPassword
-
add: userPassword
userPassword: {SSHA}Base64EncodedHashHere==
-
replace: pwdReset
pwdReset: TRUE
-
replace: shadowLastChange
shadowLastChange: 0
EOF
注:在实际生产环境中,建议使用 slappasswd 生成哈希后的密码字符串,避免在 LDIF 中明文传输密码。