事情本身不复杂,线索都在日志里。知识库文档启用了字段级加密,KMS 做季度轮换后新密钥成为默认,读取三个月前的文档时抛 InvalidCiphertextException,检索接口整片 500。

第一反应是「迁移脚本只重写了元数据没重写密文」,验证下来不成立。

这类报错背后常见的原因有几处,逐个排除就行。密文里没有记录加密所用的密钥版本。少数情况下是轮换后旧密钥被禁用而不是保留可解。

另外,多区域副本使用不同密钥,轮换只做了一半。

上来先确认密文头部是否带版本号

python -c "print(open('blob.bin','rb').read(32))"

再往下把旧密钥重新启用用于解密

aws kms enable-key --key-id alias/kb-old --region cn-north-1

随后写迁移脚本逐条解密再用新密钥加密

python rewrap.py --table documents --column body --new-key alias/kb-2026q4 --batch 500

校验迁移后能否正常读取与检索

python -c "print('read ok', len(open('doc_1.txt',encoding='utf-8').read()))"

恢复的判定其实很直接。旧文档全部读出正常,检索接口 5xx 归零,迁移脚本处理 12 万条耗时 40 分钟,抽查 200 条内容与原文一致。

容易忽略的是,密钥轮换要先保证旧密钥可解再谈替换,密文不带版本号的设计在轮换当天就会暴露,迁移要按批次可回退。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189