基于OpenLDAP和PAM用户登录系统
假设你手上管着十几台Linux服务器,日常运维中要给新人开账号、给离职员工删账号、把不同业务线的人分到不同权限组里。一开始每台机器手动useradd还能接受,但机器一多,这套“散养模式”迟早会变成灾难:同一个用户名在A机器上存在、在B机器上被删过,改密码改了一台漏了三台,半夜做审计的时候还得对着几十个“僵尸账号”发呆。
我也这么折腾过一段时间,后来实在扛不住,决定做一套集中式的用户登录认证。前后对比了轻量目录服务、活动目录域控、以及一些SaaS认证方案,最终在成本、可控性和维护难度之间取了个平衡,定下了OpenLDAP + PAM这套组合。它的思路很直接:所有用户、密码、属组、Shell、家目录路径全部集中在LDAP目录里,所有Linux服务器统一通过PAM去完成认证,通过NSS去查询用户属性。登录一台新机器,不需要再手动建账号,只要配好客户端,同一个账号直接登录所有服务器。
这篇内容适合手里有不止一台Linux服务器、想做统一账号管理的运维同学,也适合对Linux认证机制感兴趣的开发者和刚入门的基础设施工程师。我会从原理讲到落地,把服务端和客户端的完整配置、实践中的坑、以及怎么排查都梳理一遍,你自己照着做就能搭起来。
1. 为什么需要一套统一登录认证体系
先说痛点。当我们只有一两台服务器时,本地账号完全够用,useradd一条命令解决问题。但服务器数量一旦上来,本地账号管理的弊端会集中爆发。
第一个问题是账号生命周期管理没法统一。新人入职,你得在每台服务器上创建一次账号;员工离职,你得记得在所有机器上删号或者禁用账号。实际操作中经常出现的情况是:这人已经离开三个月了,某台冷门服务器上还挂着他的账号,而且还开着一个没人记得的定时任务。这种风险在安全审计的时候特别刺眼。
第二个问题是密码策略失控。每台机器上的密码策略各自为政,有的要求每90天修改,有的默认永不过期。用户为了省事,经常在几台机器上用同一个密码,一旦某台弱密码机器被攻破,其他机器也跟着遭殃。你明明定了密码策略,但落实不到每一台机器上,等于白定。
第三个问题是权限管理混乱。同样的一个开发人员,在这台机器上属于dev组,在那台机器上可能根本没被加进任何组,账号权限完全取决于当时操作的人心情。时间久了,整个权限体系会变成一团乱麻,没人能说清楚谁在哪台机器上到底有什么权限。
我当初选择OpenLDAP + PAM,核心就看重三点:统一的用户信息存储、统一的认证入口、统一的权限属性下发。
方案对比上,我也简单梳理一下。本地账号管理不用多说,是最原始的方式,适合一两台机器的场景。活动目录域控(AD)在企业Windows环境里是标准答案,但对于一个Linux集群来说显得有点重,协议复杂,维护成本高。SaaS化认证服务省心,但对内网封闭环境不友好,而且很多甲方并不希望把账号体系放在第三方平台上。OpenLDAP作为开源目录服务,协议轻量、部署简单、生态成熟,配合Linux自带的PAM和NSS机制,几乎不需要额外引入中间件,就能把统一认证这件事做扎实。
这套架构整体是客户端-服务器模式。一台OpenLDAP服务器作为目录数据库,专门存储组织结构、用户条目、用户组信息。每台业务服务器上配置nslcd作为LDAP客户端服务,再通过PAM模块和NSS模块对接系统登录链路。用户发起SSH登录、本地终端登录、su切换,或者passwd修改密码,这些动作会逐一经过PAM验证,而PAM的LDAP模块则去请求LDAP服务器,校验账号密码、拉取用户属性。用户信息返回后,系统再通过NSS的LDAP映射,把用户名转换成UID、GID、家目录路径、登录Shell这些系统登录所必需的内容。
这种架构的好处是,业务服务器本身不保存任何用户密码,即使某一台机器被攻破,攻击者拿到的也只是认证请求结果,而不是口令明文。密码集中存放在LDAP服务器上,只需要把一台服务器的安全做好,就能守住整个集群的认证入口。
2. 核心原理:LDAP、PAM 与 NSS 的分工
很多第一次接触这套体系的同学,总把OpenLDAP、PAM、NSS这三个概念搅在一起。实际上它们各自负责完全不同的环节,搞清楚各自边界,后面排错会顺很多。
2.1 LDAP目录树到底怎么存用户
LDAP全称是轻量目录访问协议,从设计之初就是为“读多写少”的目录型数据设计的。它的数据模型像一棵倒挂的树,根在最上面,逐层向下展开。这棵树叫目录信息树(DIT),每个节点是一个条目(entry),每个条目有自己的唯一标识(DN)。
拿我之前搭的一套举例。根域是dc=example,dc=com,往下按照用途分成几个组织单元(OU):ou=people放用户,ou=groups放用户组,ou=infra放开机启动相关的服务账号。每个用户是一个叶子条目,DN类似uid=alice,ou=people,dc=example,dc=com。
条目本身存储的是若干属性(attribute)。定义用户时,最少要包含三个对象类(objectClass):inetOrgPerson提供姓名、邮箱、电话等人员属性;posixAccount提供Linux账号必需的UID、GID、家目录、Shell等属性;shadowAccount提供密码过期参数,对应/etc/shadow的字段。
这里有个容易犯迷糊的地方:LDAP不替系统决定用户能不能登录,它只是按照schema格式存储用户数据。真正判断密码对不对、用户是否过期,这些工作分散在PAM模块和OpenLDAP的认证机制里。数据是数据,校验是校验,两者别混为一谈。
2.2 PAM 不是一种认证方式,而是一个框架
PAM(可插拔认证模块)是Linux用来统一认证处理流程的框架。系统里那些常见的认证场景,比如登录shell、SSH、su切换、sudo,原本各自写一套密码验证逻辑,PAM把它们全部抽象成统一接口。
PAM把一次认证拆成四个阶段:auth负责校验用户身份,account负责检查该用户当前是否被允许访问(比如账号是否过期、时间段是否受限),password负责处理密码更新,session负责登录前后要做的额外动作(比如打印登录横幅、创建家目录、记录utmp日志)。
每个阶段可以串联多个模块,模块按配置顺序执行。比如auth阶段可以配置先用pam_unix.so做本地认证,如果失败再交给pam_ldap.so做LDAP认证;也可以配置只要LDAP认证成功就直接放行,不再看本地账号。模块的结果有success、ignore、fail等不同语义,配合精确配置能实现很多灵活的认证策略。判定是否放行,依据的是整个阶段链路最终的返回结果,而不是单个模块的结果。
2.3 NSS 解决了"系统怎么知道这个用户存在"的问题
用户能不能登录,除了密码正确,系统还得能把这个用户名解析成完整账号信息:UID是多少、GID是多少、家目录在哪儿、登录Shell是什么。系统用户信息查询是通过NSS(Name Service Switch)完成的,它默认从/etc/passwd、/etc/group、/etc/shadow读取数据,但NSS支持通过动态库扩展数据源。
我们配置NSS引用LDAP数据源后,getent passwd、文件系统属主解析、进程权限判断这些环节,就会自动去LDAP目录里查询用户信息。这里的间接层是nslcd:一个本地守护进程,负责把系统的用户查询请求转发给LDAP服务器,并缓存结果。系统本身不直接抱着LDAP连接不放,而是统一找nslcd要数据,这样连接管理、超时控制、重连机制都由nslcd处理,稳定很多。
2.4 一次完整登录请求的完整链路
以SSH登录为例,完整链路是这样的:用户在客户端执行ssh alice@server,SSH服务收到后调用PAM的auth阶段;配置在auth阶段里的pam_ldap.so会拿到用户输入的密码,用这个密码和用户名去LDAP服务器做一次绑定操作,绑定成功基本可以认定为密码正确;auth通过后进入account阶段,LDAP模块检查账号是否过期禁用等状态。
账号状态没问题,系统接着通过NSS查询alice的UID、GID、家目录和Shell,完成本地会话初始化;最后进入session阶段,pam_mkhomedir.so会在家目录不存在时自动按/etc/skel模板创建。整个链路看起来长,实际配置好后,从客户端输入密码到进入shell,一般也就是一两秒的事情。
3. 服务端搭建:OpenLDAP 初始化与用户入库
服务端是整个体系的核心,我会按步骤讲清楚部署过程。下面以RedHat系系统(CentOS 7/8等)为主。Debian系包的名称略有差异,我会在对应位置标注。
3.1 初始化 OpenLDAP 与根配置
安装服务端Gluon包:
yum install -y openldap-servers openldap-clients systemctl enable --now slapdDebian系对应安装slapd和ldap-utils两个包。安装完成之后,需要先设置管理密码,并用它来修改默认配置。OpenLDAP服务端有一个管理配置的接口叫cn=config,其中olcDatabase={2}mdb,cn=config是实际存放业务数据的数据库实例。
生成密码哈希:
slappasswd -s your_admin_password把生成的{SSHA}...串填到下面的LDIF里,建立管理员的rootDN和rootPW。rootDN是目录库的超级管理员,区别于后续业务中要用的只读查询账号,这两个概念后面会再次强调。
dn: olcDatabase={2}mdb,cn=config changetype: modify replace: olcSuffix olcSuffix: dc=example,dc=com dn: olcDatabase={2}mdb,cn=config changetype: modify replace: olcRootDN olcRootDN: cn=admin,dc=example,dc=com dn: olcDatabase={2}mdb,cn=config changetype: modify add: olcRootPW olcRootPW: {SSHA}...写入配置:
ldapmodify -Y EXTERNAL -H ldapi:/// -f change.ldif这一步里最关键的是这两个changetype操作都作用于olcDatabase={2}mdb,cn=config,但拆成了三个独立条目写入。实际执行时如果数据库实例编号不是2,需要先用slapcat看下实际配置里数据库的编号。
接着导入标准schema。posixAccount、shadowAccount这些对象类定义在nis schema里,inetOrgPerson在inteorgperson schema里:
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif3.2 组织架构与用户的 LDIF 设计
接下来创建顶层目录结构和首批用户。建议用LDIF文件批量导入,而不是一条条命令手工敲,后者既容易出错也不适合后续审计。
基础结构文件base.ldif:
dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization dc: example o: Example Inc dn: ou=people,dc=example,dc=com objectClass: organizationalUnit ou: people dn: ou=groups,dc=example,dc=com objectClass: organizationalUnit ou: groups dn: ou=services,dc=example,dc=com objectClass: organizationalUnit ou: services我用ou=services单独放服务账号,和应用账号做隔离。导入:
ldapadd -x -D "cn=admin,dc=example,dc=com" -W -f base.ldif创建用户alice的定义alice.ldif:
dn: uid=alice,ou=people,dc=example,dc=com objectClass: top objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: alice cn: Alice sn: User displayName: Alice User mail: alice@example.com uidNumber: 10001 gidNumber: 10001 homeDirectory: /home/alice loginShell: /bin/bash userPassword: {SSHA}... shadowLastChange: 19000 shadowMin: 0 shadowMax: 99999 shadowWarning: 7密码的{SSHA}哈希可以用slappasswd生成。注意uidNumber和gidNumber别跟系统已有的UID段冲突,从10000起分配比较安全。导入用户:
ldapadd -x -D "cn=admin,dc=example,dc=com" -W -f alice.ldif再创建对应的posixGroup条目:
dn: cn=devs,ou=groups,dc=example,dc=com objectClass: top objectClass: posixGroup cn: devs gidNumber: 10001 memberUid: alice用户组用memberUid属性把成员串起来即可。后续svn、git等应用需要按组控制读写权限时,可以直接去LDAP里查members,不用在每台机器上维护/etc/group。
3.3 给系统创建只读查询账号
这一步很容易被跳过,但我强烈建议不要用admin账号当客户端的bind账号。nslcd会常驻连接LDAP,如果它拿的是admin凭据,一旦某台客户端被入侵,等于直接把目录库的超级管理员口令交出去了。正确做法是单独创建一个只读账号,只有查询用户和用户组的权限。
创建只读账号:
dn: cn=ldapreader,dc=example,dc=com objectClass: organizationalRole objectClass: simpleSecurityObject cn: ldapreader userPassword: {SSHA}... description: Readonly bind account for Linux clients还需调整访问控制策略,允许这个账号读取用户属性,但没有修改权限。修改olcDatabase={2}mdb,cn=config中的olcAccess规则:
dn: olcDatabase={2}mdb,cn=config changetype: modify replace: olcAccess olcAccess: to attrs=userPassword by self write by anonymous auth by dn.exact="cn=ldapreader,dc=example,dc=com" read by * none olcAccess: to * by self write by dn.exact="cn=ldapreader,dc=example,dc=com" read by * none这里的意思比较直白:用户密码属性只有用户自己可以改,匿名用户只能用于认证比对,ldapreader这个账号可以读取但无法写入,其他任何人没有访问权限。这种最小化授权原则,是这套系统后续能不能通过等保审计的关键。
4. 客户端集成:PAM 与 NSS 配置全过程
服务端准备好之后,剩下就是让每一台业务服务器“认识LDAP”。客户端配置是整个系统里最容易出幺蛾子的环节,我按顺序一步步说清楚。
4.1 安装与基础配置
RedHat系安装:
yum install -y nss-pam-ldapd systemctl enable --now nslcdDebian系对应的包是libnss-ldapd和libpam-ldapd,安装时通常会弹一个交互配置界面,按提示填写服务器地址即可。
核心配置文件是/etc/nslcd.conf,它负责定义nslcd守护进程如何连接LDAP,以及如何把目录数据映射成系统账号属性。一个典型的配置如下:
uri ldap://10.0.10.10/ base dc=example,dc=com binddn cn=ldapreader,dc=example,dc=com bindpw your_reader_password filter passwd (objectClass=posixAccount) filter group (objectClass=posixGroup) map passwd homeDirectory "/home/$uid" map passwd uidNumber uid map passwd gidNumber gid map passwd loginShell loginShell map passwd gecos cn说几个容易忽略的细节。uri可以写多行,比如uri ldap://ldap1/ ldap://ldap2/,nslcd会自动做故障切换。filter用来指定哪些条目被当作系统用户,如果没写会根据对象类自动判断,但显式写出来更利于控制边界。map passwd homeDirectory "/home/$uid"这条比较实用,它允许我用一个模板字符串统一生成家目录路径,而不必依赖LDAP条目里是否写了homeDirectory。
配置完成后顺手重启服务:
systemctl restart nslcd4.2 nsswitch.conf 让系统认识 LDAP 用户
/etc/nsswitch.conf决定系统按什么顺序、从哪些数据源查询用户信息。原文件里默认是files,也就是/etc/passwd等本地文件。我们改成:
passwd: files ldap group: files ldap shadow: files ldap这样系统先查本地文件,本地找不到再查LDAP。files放在前面很重要,避免某些本地系统账号(root、daemon等)因为LDAP里恰好存在同名条目而被截胡。改完后不需要重启服务,立刻生效。验证方法:
getent passwd alice如果能看到alice的记录并且返回UID、GID、家目录等字段,说明NSS链路已经通了。
4.3 PAM 栈改造与 home 目录自动创建
PAM配置这一步要十分小心,改坏了可能导致本地账号也登不上。改之前先备份:
cp -a /etc/pam.d/system-auth /etc/pam.d/system-auth.bak cp -a /etc/pam.d/password-auth /etc/pam.d/password-auth.bak以CentOS 7为例,system-auth文件中auth段加一行:
auth sufficient pam_ldap.so use_first_passsufficient关键字的意思是这个模块成功就直接放行,失败了继续往下走,兜底用本地的pam_unix.so。这样保证LDAP服务器临时抽风时,本地root账号仍然能登录,不至于把自己锁在门外。
account段加:
account sufficient pam_ldap.sopassword段加:
password sufficient pam_ldap.so use_authtoksession段加:
session optional pam_mkhomedir.so skel=/etc/skel umask=0022pam_mkhomedir.so会在这个用户首次登录时自动创建家目录,并把/etc/skel下的模板文件拷贝进去。如果缺了这一条,LDAP用户认证成功后会出现“没有家目录,无法创建工作环境”的报错,然后强退或者掉到临时目录,体验很差。
需要特别注意的是,按上述方式直接改system-auth文件,在CentOS 7上可行;但RedHat 8及以上版本默认用authselect管理PAM配置,直接改文件会被定期覆盖回去,导致配置“神秘消失”。对这种新版本,建议创建自定义profile:
authselect create-profile ldap-auth authselect select custom/ldap-auth然后编辑/etc/authselect/custom/ldap-auth/system-auth,写入同样的PAM规则。这样既能持久生效,也保留了authselect的配置一致性管理。Debian系则要改/etc/pam.d/common-auth等文件,并配合pam-auth-update管理。
SSH登录场景还需要确认/etc/ssh/sshd_config里UsePAM yes是开启状态,否则PAM认证不会介入SSH登录。顺便把UseDNS no开上省掉一坨反向解析延迟。
4.4 验证整个过程
配置完成后的第一轮验证建议从这几步来:
getent passwd alice getent group devs id alice ssh alice@localhostid alice能列出正确的UID和组,说明NSS链路OK。ssh alice@localhost能登录成功并且自动创建了/home/alice,说明PAM的auth、account、session三个阶段全部生效了。
首次登录如果不放心,可以在客户端开一个终端看日志:
tail -f /var/log/secure登录时会看到PAM模块依次调用的过程,哪个阶段报错一目了然。pam_mkhomedir创建目录时如果被SELinux拦了,日志会有明确提示,sestatus查一下状态,必要时调整对应布尔值。
5. 三个值得直接落地的扩展
基础登录认证能跑通之后,这套体系只是完成了第一步。实际使用中还有三个场景几乎必碰,我这里把思路讲一下。
5.1 LDAP 里的 sudo 规则
每台机器的/etc/sudoers还是各自管各自的,LDAP用户登录后能执行什么命令,会退回到本地配置。统一管理又没了。解决方式是加载sudo的schema,把sudo规则存进LDAP目录。
客户端需要把sudoers数据源改为LDAP。在/etc/sudo-ldap.conf里指定:
uri ldap://10.0.10.10/ base ou=sudo,dc=example,dc=com再在/etc/nsswitch.conf里加一行:
sudoers: files ldap这样sudo会先查本地文件,查不到就去LDAP里按sudoRole条目解析授权规则。LDAP服务器侧加载sudo.schema后,创建类似下面的条目:
dn: cn=%devs,ou=sudo,dc=example,dc=com objectClass: sudoRole cn: %devs sudoUser: %devs sudoHost: ALL sudoCommand: ALL sudoOption: !requirettysudoUser: %devs表示devs组内成员全部生效,sudoHost: ALL限制这台规则只对全部主机生效。维护一套规则,所有服务器同步生效,这才是“统一”该有的样子。
5.2 传输加密
不加密的LDAP认证在局域网内还能勉强接受,一旦客户端和服务端跨越不可信网络,密码明文走389端口传输就是个大漏洞。生产环境必须要上LDAPS或者TLS。
服务端需要一张证书,自签或者内部CA签发都可以。以自签为例,先生成CA和服务端证书,然后在slapd配置中启用TLS:
olcTLSCertificateFile: /etc/openldap/certs/server.crt olcTLSCertificateKeyFile: /etc/openldap/certs/server.key olcTLSVerifyClient: never客户端ldap.conf里做对应设置:
TLS_CACERT /etc/openldap/certs/cacert.crt TLS_REQCERT allowURI改为ldaps://10.0.10.10/,连接时强制加密。这一步不做,前面所有账号体系都等于裸奔。
5.3 多节点复制
单台LDAP服务器毕竟是单点,挂了全集群登录都受影响。OpenLDAP官方做法是provider-consumer复制:一台主节点接受写入,多台从节点提供读取,客户端URI里按优先级把多台服务器都写上。
主节点上为每个从节点配置syncrepl复制关系,从节点只需把olcSyncrepl指向主节点,并设置type=refreshAndPersist保持长连接增量同步。配置并不复杂,但需要仔细处理复制冲突。客户端的URI改成多主机形式:
uri ldap://ldap01.example.com/ ldap://ldap02.example.com/主节点宕机后,nslcd自动切换查询到从节点,认证服务不中断。从节点上同时开一个只读bind账号,配合TLS,高可用和安全性就都齐了。
6. 常见问题与排查经验
这部分是实际运维过程中踩过的坑和对应的排查思路,按出现频率排序整理出来。我把最典型的几条现象、原因和解决方式列成一个速查表,日常出了问题可以先看这张表,大部分问题能在五分钟内定位。
| 现象 | 可能原因 | 排查思路 |
|---|---|---|
| getent查不到LDAP用户 | nslcd未启动、URI错误、filter写得不对 | systemctl status nslcd,再用ldapsearch手动验证 |
| 登录时报账号不存在 | nsswitch.conf没改、nslcd查询失败 | getent passwd alice逐步确认 |
| 认证成功但无家目录 | 缺pam_mkhomedir、SELinux拦截 | 检查PAM session段、journal日志 |
| SSH登录卡顿几秒 | sshd开启DNS反查 | 配UseDNS no |
| 改密码失败或不同步 | 用户objectClass缺shadowAccount、权限不足 | 检查LDAP访问控制规则 |
| 用户组权限长时间不变 | nscd缓存 | 停用nscd,重启nslcd |
| LDAP服务器正常但客户端连不上 | 网络不通、端口被防火墙挡了 | telnet 机器 389、ldapsearch -x -H |
6.1 查询不到用户的排查顺序
getent passwd alice查不到人是出现频率最高的问题。按下面顺序排查,别一上来就怀疑LDAP数据坏了。
从最外层开始:先确认nslcd进程还活着,systemctl status nslcd看一眼;接着直接向LDAP服务器发起查询:
ldapsearch -x -H ldap://10.0.10.10/ -b "dc=example,dc=com" -D "cn=ldapreader,dc=example,dc=com" -w 密码 "(uid=alice)"这个命令能查到alice,说明服务端和bind账号没问题,问题出在客户端配置或过滤规则。查不到,则要么是目录里确实没这个条目,要么是bind凭据没权限。特别注意binddn和bindpw如果写错了,nslcd只能在日志里看到一个认证失败,表面上却表现得像是“找不到人”,非常容易误判。
6.2 登录成功却没有 shell / 家目录
这个坑我最初也踩过。eval用户能通过认证,但登录后立刻被弹回或者提示找不到shell。解决办法分两块:一是确认PAM的session段里加了pam_mkhomedir.so,并且skel参数指定的目录存在;二是在RedHat系上别忘了SELinux。getsebool -a | grep ssh看看SSH相关布尔值,尤其是有自定义家目录路径时,调整home_root相关的上下文。
还有种隐蔽情况:LDAP里用户条目的loginShell字段设成了一个不存在的路径,比如写成了/bin/bashs,认证链路再通畅也会在最后一步被系统拒绝。查这个字段用一条ldapsearch就能发现。
6.3 登录缓慢
登录从输入密码到出现shell,耗时三秒以上,多半不是PAM或者LDAP本身有问题,而是SSH在做DNS反查。UseDNS no加上之后立竿见影。如果还不是这个原因,大概率是nslcd连接LDAP时超时了,检查URI是否可路由、目标端口是否通。生产环境建议在uri多写一台节点,避免单点卡死整个认证流程。
6.4 nscd 缓存导致的不一致
nscd是系统默认的Name Service Cache Daemon,默认会缓存passwd和group结果。它缓存后,用户改了UID、移出组,客户端机器上仍然显示旧信息,权限判断全部按缓存走,坑得不轻。我遇到过用户明明已被移出devs组,某台机器上还能切换到这个组的权限,查了半天才发现是nscd缓存。
考虑到nslcd自身已有缓存机制,多一层nscd不但多余还会引发不一致。建议直接停用:
systemctl disable --now nscd如果环境里确实需要nscd,要确认它没在缓存passwd/group,只保留hosts之类的缓存。这个细节很重要,日常排错最容易忽视。
6.5 修改密码失败
用户用passwd改密码报错,最常见的原因是LDAP里用户条目缺少shadowAccount这个对象类。没有这个对象类,pam_ldap.so无法把新密码通过shadowLastChange等属性写回目录库。检查一下条目的objectClass,通过ldapmodify补上缺失的对象类即可。
另一种情况是权限问题:如果olcAccess没有配置成“用户可以修改自己的userPassword”,密码更新也会被目录库拒绝。用ldapmodify改olcAccess规则时要格外小心,改错可能把自己都锁在外面,建议事先把原配置导出一份备份。
7. 关于这套体系的几点维护心得
这套系统上线后,日常维护其实不重,但有几点心得还是值得留下来。第一,目录结构规划一定要在初始阶段做仔细,父OU的命名定了之后就别随便改,因为客户端和sudo规则里的base都依赖它。第二,严格按最小权限给bind账号、给普通用户、给应用服务分配访问权限,不要图省事直接向全员开放read,更不要让客户端用admin账号去查询。
日常巡检的话,我习惯用一段简单的ldapsearch脚本,每天早上检查目录库连通性、尝试用ldapreader查询一个已知用户;再配合客户端上用id抽查几个关键账号,确认nslcd链路正常。这套巡检脚本极大减少了我半夜被一口咬定“系统登不上了”的概率。
对刚开始接触这套体系的朋友,个人建议先在两台虚拟机里把完整流程走一遍,即使第一次实验就遇到各种报错也完全正常,因为这恰恰是理解PAM模块顺序和NSS数据流的最佳方式。等原理彻底弄明白,再在真实环境里切换,心里就有底了。这套方案不是银弹,但它绝对能帮我们这些没有专职安全团队的小运维团队,把账号管理这件最基础也最容易出事的事情,做得体面一些。