Access Server 会忽略你在磁盘上改过的 post_auth 脚本
在磁盘上修改 post_auth 文件没有用:Access Server 运行的是配置数据库里的副本。按决策路径走,并执行 sacli 命令。
改过的 mac.py 却毫无变化,这是最常见的第一现象。磁盘上的文件并不是 Access Server 执行的那份;认证服务从服务器的配置数据库加载脚本,真正决定登录的是那份存储起来的副本。只要存储值没有被替换,你做的每次测试都只能证明旧脚本还在工作。
三件事决定怎么处理:这个值有没有进过配置数据库,服务有没有被要求重新加载,以及你改的代码是否真的在每次连接时执行。三者症状各不相同,修错方向会白白浪费一个维护窗口。
文件只是来源,不是运行副本
Access Server 把 post-auth 脚本放在 auth.module.post_auth_script 这个键下面。改文件只更新你本地的副本,守护进程读的是配置数据库里的值,所以在删除旧条目、把新文件放到位置之前,这次修改看不见。那份存储值才是认证服务唯一查看的副本。
动手前先读出来。如果它已经和改过的文件一致,问题不在存储,可以直接跳到范围问题。如果它显示的是旧版本,说明修改根本没到服务那边。
./sacli -k auth.module.post_auth_script ConfigGet先替换存储副本,再让它生效
先删再写不是装饰。ConfigPut 配合 --value_file 一步替换掉值,而先执行 ConfigDel 则让陈旧或损坏的条目没有机会残留。开始之前,把能用的脚本复制一份放到脚本目录之外。
./sacli -k auth.module.post_auth_script ConfigDel
# store the file, then apply it
./sacli -k auth.module.post_auth_script --value_file=/root/post_auth.py ConfigPut
./sacli startsacli start 把改动后的配置应用到内部服务上,这正是新脚本生效的原因。它和重启整台机器或守护进程不是一回事,除非你的改动确实要求,否则不要用后者替代。
值文件要用绝对路径,并确认 root 能读到它。从你的 shell 里能解析、服务账号却解析不了的路径,会存下一个在 ConfigGet 里看着正常、第一次登录就失败的值。sacli start 之后再看一次存储结果,而不是之前。
模块范围还是每次连接:查询该放在哪里
Python 只在加载脚本时执行一次模块级语句。因此写在文件顶部的数据库查询是在加载时读表,并把那个答案保留给之后的每一次连接。这就是修改看起来没反应的第二个原因:代码确实执行了,但不在你预期的时刻。
把查询放进 post_auth 处理函数内部,让它在每次认证时执行。保持文档中给出的签名,调整处理函数收到的认证结果,并返回同一个对象,而不是一个裸数字。
连接的处理也放在处理函数里。导入时打开的连接可能会在第一个用户登录之前被服务器关掉,由此产生的错误看起来像凭据被拒绝,而不是脚本坏了。
两条拒绝路径,一个负责人
如果判定是本地查询,结果由 Python 处理函数负责。如果是外部 HTTP 检查,就让命令的退出状态携带答案:以非零码退出的包装脚本会拒绝登录,最后一条命令的状态无需显式 exit 就成为脚本的状态。
把机密留在进程列表之外。root 可读的文件或服务传入的环境值,比任何本地用户都能从 ps 里读到的命令行参数更安全。调用前把端点固定到变量里,让拼写错误在配置阶段失败,而不是在某人登录时失败。像对待其他凭据一样轮换这个机密。
每项检查只选一个负责人。既查数据库又调用 HTTP 服务的脚本,必须有明文规定的优先级规则来处理两者不一致的情况,否则日志里的拒绝原因和告诉用户的话对不上。
在不锁死管理员的前提下上线
两道保险让改动可回退:一个不依赖该脚本的第二个管理员账号,以及一份放在脚本目录之外、已知可用的副本。在维护窗口里应用改动,然后在断开之前先看一次测试登录和一次故意拒绝。如果日志里出现语法错误而不是认证判定,说明存储的脚本坏了,所有人都登录不了。
两种情况说明该等一等:无法以 root 读取值文件,或者没有进入管理界面的第二条路径。两者都会把小改动变成锁死,都不值得在一天结束时的生产服务器上试。Access Server 文档覆盖了 post-auth 接口及其支持的字段。