服务账号密码过期,应用为何批量认证失败?

安全部例行改密后 17 个应用连环报数据库认证失败。根因是共享服务账号密码在 AD 中命中过期策略,而应用侧密码写死在配置里无法自动跟进;配套的变更通知也只发了两轮。修复后以 gMSA 和账号台账补上轮换断链。

问题背景

公司 AD 里有一个服役多年的共享服务账号 svc_appdb,被 17 个内部应用用来连数据库与相互调用——报表平台、工单系统、短信网关、数据同步服务全挂在这一个账号上。因为"改一次密码要通知一堆应用",这个账号的密码四年没有轮换过,是安全部年度审计报告上的老问题。

10 月上旬,安全部启动账号治理专项:所有超过一年未改密的账号强制重置,svc_appdb 在名单里。安全部按流程发了变更通知邮件,应用团队回了"已知悉",随后在维护窗口改掉了 AD 里的密码——原计划是"各应用按文档自助更新配置"。

次日上午 9 点 20 分起,工单系统开始报数据库认证失败;半小时内 17 个应用中有 14 个连环告警,数据同步全部中断,报表平台查询报错。一场以"提升安全"为目的的改密,把半个应用层打瘫了。

故障现象

  • 应用侧报错统一:Login failed for user 'svc_appdb'(状态 18456),连接池重建后依然失败——不是瞬时抖动,是凭据问题。
  • kubectl exec 抽查两个应用容器,配置文件里的密码确实是旧密码;环境变量注入的另几个应用同样如此。
  • AD 侧确认:新密码已生效,账号未锁定(没有锁定事件)——排除了"改错密码"和"误触发账户锁定策略"。
  • 17 个应用里 3 个正常——事后核实,这 3 个用的根本不是这个服务账号,而是各自独立的账号;依赖 svc_appdb 的 14 个全军覆没。
  • 故障没有自愈迹象:连接池重试永远失败,因为旧密码在服务端已经失效。

排查过程

第一步还原时间线,确定"谁改的、改了什么"。AD 审计日志(4723 密码修改尝试/4724 重置)确认 9:00 维护窗口内 svc_appdb 被重置,操作者是安全部治理专项的服务账号——变更属实、流程走了,问题在"改完之后"。

第二步弄清"为什么应用没跟上"。应用侧的密码落地方式盘点下来有三类:写在配置文件里(6 个)、注入环境变量(5 个)、走 K8s Secret(3 个)——没有任何一类有自动轮换机制,全部依赖人工按通知去改。而安全部的通知只发了应用团队邮箱列表,17 个应用的负责人里只有 5 人在列表里,其中 2 人当天休假;“按文档自助更新"的前提根本不成立。

第三步回答"为什么密码会过期”。此前四年没人动过这个账号,大家默认"服务账号不受密码过期策略约束"——这个认知是错的。AD 的域密码策略按账号应用,svc_appdb 所在 OU 没有配置例外 PSO(Fine-Grained Password Policy),四年没过期纯属"运气差在恰好这次审计触发了重置";本次重置同时落入了"下次过期时间 = 现在 + 90 天"的默认策略,意味着三个月后同样的事故会精确重演,除非中间有人补上治理机制。

第四步明确修复边界。紧急恢复只需要把新密码同步到 14 个应用;但要避免三个月后重演,必须回答"这个账号到底该怎么管"——一个账号被 14 个应用共享,本身就是轮换断链的根源。

解决方案

  1. 紧急恢复(30 分钟):从密码保险库取新密码,按应用清单逐个更新配置/Secret 并滚动重启;10:05 全部 14 个应用恢复。清单来自 CMDB 的依赖登记——这次能快速对齐,靠的是去年资产梳理时留下的"服务账号 → 应用"映射表。
  2. 账号拆分(治本):废弃 svc_appdb 一号通吃模式,按应用拆分为 14 个独立服务账号;每个账号的密码落在密码保险库,由 K8s External Secrets Operator 同步到对应 Secret。
  3. 轮换自动化:优先把支持 gMSA 的 Windows 侧服务迁移到组托管服务账号(AD 自动轮换 120 天,应用零改动);Linux 侧与数据库接入凭据轮换工具,配置"改密 → 分发 → 验证 → 回滚"四步流水线,人工只做审批。
  4. 策略例外与台账:为暂时无法自动轮换的账号建 PSO 例外(延长过期周期)+ 显式登记"轮换责任人/下次轮换日";AD 里所有服务账号打上 svc- 前缀并纳入季度审计,超期未轮换自动告警到安全部与应用团队双清单。

根因分析

直接根因是服务账号密码重置后,14 个依赖应用侧的旧凭据没有任何自动跟进机制,全部静默失效。深层根因有三层:其一,一个账号被 14 个应用共享,密码轮换的爆炸半径天然失控;其二,“服务账号不受密码策略约束"的错误认知使账号四年裸奔,过期策略一触发就现出原形;其三,变更通知的触达名单不全,“通知即生效"的流程假设在组织上就不成立。三层缺一,事故都到不了"半个应用层瘫痪"的量级。

预防措施

  • 服务账号一律禁止跨应用共享,新应用接入默认独立账号+保险库+自动同步;
  • 可迁移服务分批 gMSA 化,季度通报迁移进度;
  • 变更通知强制要求"逐应用确认回执”,未回执的应用在变更窗口内暂停执行;
  • 密码过期类变更执行前先跑依赖映射检查,输出受影响应用清单作为变更附件;
  • 安全治理专项与运维变更日历对齐,杜绝"审计驱动突袭改密”。

总结

这次事故最讽刺的地方在于:它是一次成功的安全整改的直接后果。审计发现了问题、流程走了、密码改了——但改密动作和应用侧的凭据跟进之间隔着一条没人负责的断链。服务账号治理的本质不是"定期改密码"这个动作,而是让每个凭据都有明确的属主、自动化的分发通道和可验证的生效确认;三者齐了,改密才是安全的收尾而不是事故的开场。那 3 个没受影响的应用,靠的正是当初坚持用了独立账号——正确的架构比任何变更流程都可靠。

延伸阅读

使用 Hugo 构建
主题 Stack 由 Jimmy 设计