2. 密码策略的构成与版本化表达

密码策略版本治理的第一道工程门槛,不是“怎么改策略”,而是“策略到底由什么构成、如何被机器稳定地表达”。如果策略只以自然语言文档或控制台截图存在,任何一次参数调整都无法被追溯、比对和回滚。本节要建立一套可版本化的策略描述规范:把策略拆成要素,把要素组织成参数模型,把参数模型固化为模板,再用版本标识与元数据把每一次变更锚定在时间轴上。

一、策略要素:从“一句话要求”到可枚举字段

一条密码策略在业务上常被表述为“用户密码必须足够复杂且定期更换”。这种表述无法直接进入版本管理,必须拆解为可枚举、可赋值、可校验的要素。工程上通常把策略要素分为四类:

  • 约束要素:长度下限、长度上限、字符类别要求(大写、小写、数字、符号)、禁止包含用户名或字典词。
  • 生命周期要素:最大有效期、最小使用时长、到期前提醒窗口、历史密码不可复用数量。
  • 失败处理要素:连续失败锁定阈值、锁定时长、失败计数重置条件。
  • 适用范围要素:策略绑定的用户组、系统、认证方式(如本地登录、LDAP、SSO)。

每个要素都应具备唯一键名、数据类型、取值域和默认值。例如 min_length 为整数,取值域 8~64,默认 12;require_symbol 为布尔值,默认 true。只有要素被结构化,后续的版本比对才能落到字段级,而不是整段文本的模糊 diff。

二、参数模型:要素之间的关系与约束

要素不是孤立存在的。长度下限与字符类别要求共同决定理论密码空间;历史密码不可复用数量与最大有效期共同决定用户实际需要记忆的密码数量。参数模型要显式表达这些关系,至少包括三类约束:

  • 依赖约束:若 require_symbol=true,则符号集合 symbol_set 必须非空。
  • 数值约束:min_length ≤ max_length;min_age ≤ max_age。
  • 组合约束:history_count × max_age 不应超过用户可接受的管理负担阈值,否则策略虽安全却不可执行。

参数模型的价值在于:当某个字段被修改时,校验器能立即判断新组合是否合法,而不是等到策略下发后才在终端上暴露冲突。下面这张图展示了一个策略从要素到版本化表达的完整结构关系。

① 策略要素层 约束要素 min_length / max_length require_upper / symbol_set 生命周期要素 max_age / min_age history_count / remind_days 失败处理要素 lock_threshold / lock_duration reset_condition 适用范围要素 user_group / system auth_method 结构化 ② 参数模型层 参数模型:字段定义 + 约束校验 + 默认值 依赖约束:require_symbol=true → symbol_set ≠ ∅ 数值约束:min_length ≤ max_length;min_age ≤ max_age 组合约束:history_count × max_age ≤ 管理负担阈值 类型约束:整数 / 布尔 / 枚举 / 字符串集合 固化 ③ 策略模板层 模板 A:高安全基线 min_length=16, max_age=60d, history=12 适用:特权账户 / 核心系统 模板 B:普通用户基线 min_length=12, max_age=90d, history=5 适用:普通员工 / 一般业务系统 标识 ④ 版本标识与元数据层 version: 2.3.0(语义化版本) metadata: 生效时间 / 变更人 / 变更单号 / 校验和

三、策略模板:把参数模型变成可复用资产

参数模型解决“字段怎么定义”,模板解决“一组字段值怎么复用”。模板不是简单复制,而是把参数模型中的字段按场景预设为具名组合。例如高安全基线模板与普通用户基线模板共享同一套字段定义,但取值不同。模板应满足三个条件:

  • 可继承:子模板可覆盖父模板的个别字段,未覆盖字段自动继承。
  • 可校验:模板实例化时必须通过参数模型的全部约束。
  • 可追溯:模板本身有版本,模板实例化后的策略也有版本,两者通过引用关系关联。

下面给出一个可直接参考的策略模板 YAML 示例,字段名与参数模型一一对应:

template_id: pwd-baseline-normal
template_version: 1.4.0
extends: pwd-baseline-common
params:
  min_length: 12
  max_length: 64
  require_upper: true
  require_lower: true
  require_digit: true
  require_symbol: true
  symbol_set: "!@#$%^&*"
  max_age_days: 90
  min_age_days: 1
  history_count: 5
  lock_threshold: 5
  lock_duration_min: 30
  scope:
    user_group: "employees"
    system: "portal"
    auth_method: "ldap"

模板实例化后生成一条具体策略记录,该记录携带模板引用和自身版本号。当模板升级时,已实例化的策略不会自动漂移,而是通过“模板版本 + 策略版本”双标识明确其来源与当前状态。

四、版本标识:语义化版本与变更粒度

版本标识不能只是一个递增整数,否则无法从版本号判断变更性质。推荐采用语义化版本 MAJOR.MINOR.PATCH,并约定变更粒度:

  • MAJOR:不兼容变更,如删除字段、改变字段语义、收紧约束导致旧策略无法通过校验。
  • MINOR:向后兼容的功能变更,如新增可选字段、放宽取值域、新增模板继承关系。
  • PATCH:修正性变更,如默认值调整、文案修正、校验逻辑修复,不改变策略语义。

例如将 min_length 从 12 改为 16,属于收紧约束,应升 MAJOR;将 remind_days 从 7 改为 10,属于兼容调整,升 MINOR;修正 symbol_set 中重复字符,升 PATCH。版本号一旦发布不可覆盖,只能新增。

五、元数据设计:让每次变更可审计、可回滚

版本标识回答“这是第几版”,元数据回答“谁、何时、为何、影响谁”。一条策略版本记录至少应包含以下元数据字段:

字段类型说明示例
versionstring语义化版本号2.3.0
effective_fromdatetime生效起始时间2025-04-01T00:00:00+08:00
effective_todatetime失效时间,空表示持续有效null
authorstring变更发起人security-admin-01
change_ticketstring变更单号,关联审批流程CHG-2025-0412
checksumstring策略内容哈希,用于完整性校验sha256:9f2c…
supersedesstring被替代的上一版本号2.2.1
scope_refstring适用范围引用group:employees;sys:portal

其中 checksum 尤为关键:它把策略内容与版本记录绑定,任何未走版本流程的篡改都会导致校验和不匹配。回滚时,只需将目标版本的 effective_from 重新激活,并生成一条新的 PATCH 版本记录,而不是删除历史版本。

可版本化策略描述规范的最小闭环是:要素有键名和类型 → 参数模型有约束校验 → 模板可继承可实例化 → 版本号按语义化规则递增 → 元数据记录生效时间、变更人和校验和。缺少任何一环,策略治理都会退化为“改完再说”的不可控状态。

把上述规范落地后,策略的每一次调整都变成一次可审查的版本事件:变更前能比对字段差异,变更中能校验约束冲突,变更后能按时间轴回放。这正是密码策略版本治理工程从“文档管理”走向“工程管理”的分界线。