lzf_0626
|
c32d3dbd06
|
chore: 开发专用 JWT 密钥、密钥生成脚本与轮换文档
背景:此前全环境共用一把 JWT 密钥(config/jwt/jwt-private.pem)。它相当于
"能冒充 9001/9002/9003 的万能钥匙"(实测边界:签名有效 + 用户存在且启用才通过,
伪造新用户与使用禁用账号都会被拒)。为避免同一把密钥将来又变成生产密钥,
本次引入开发专用密钥,并把签发侧收敛到配置。
改动:
1. 新增 tools/generate_jwt_keys.py:可复现地生成 RS256 密钥对(PKCS#8 / SPKI),
打印公钥 SHA-256 指纹便于核对服务端加载的是否同一把;密钥已存在时默认拒绝
覆盖,避免误操作导致所有已签发令牌立即失效。
2. 生成开发专用密钥到 config/jwt/dev/(该目录整体已被 .gitignore 忽略,不入库)。
3. 三个工具脚本不再硬编码私钥路径,改为读配置:acceptance_check 与 demo_agent_e2e
走 get_settings().jwt_private_key_path,smoke_check 因刻意不依赖 app 包而读
JWT_PRIVATE_KEY_PATH 环境变量。今后轮换密钥只需改 .env 一处。
4. .env、.env.example 与 Settings 默认值统一指向 config/jwt/dev/。
5. 新增 docs/21-JWT密钥管理与轮换.md:密钥分工(服务端只读公钥,
JWT_PRIVATE_KEY_PATH 在 app/ 中无任何读取点,故生产机可只挂公钥)、
克隆后必须自行生成、多人共用一个服务时必须共用同一把私钥、
轮换的影响面与生产部署要点、安全红线。
6. 记录一处易被忽略的问题:生产环境的 JWT_ISSUER / JWT_AUDIENCE 也应与开发不同,
否则开发环境签发的令牌在生产上依然有效——这比换密钥更容易漏。
说明:本次提交不含任何密钥文件(.env 与 config/jwt/ 均在 .gitignore 中)。
旧密钥 config/jwt/jwt-private.pem 已退役但保留未删,配置不再引用它,
用它签发的令牌会被拒绝。
验证:ruff 通过、mypy 103 文件无错、unit+contract 447 passed、integration 29 passed、
acceptance_check --production 7 PASS、demo_agent_e2e 9/9 PASS——均使用新密钥完成
签发与验签。
|
2026-09-10 18:14:03 +08:00 |
|