安全密钥审计


文档摘要

安全密钥审计 本节摘要:通过集中式密钥库(HashiCorp Vault、AWS Secrets Manager、Azure Key Vault)消灭密钥散落。绝不把凭证存进配置文件、版本控制里的 env 文件、电子表格。用 IAM 角色而非静态密钥;CI/CD 用 OIDC。AI 网关模式是 2026 的解法:应用 → 网关 → 模型 provider,网关在运行时从密钥库取凭证。在密钥库里轮换,所有应用几分钟内自动生效——无重新部署,无 Slack「谁有新 key」消息。轮换策略 ≤90 天;每次提交用 TruffleHog / GitGuardian / Gitleaks 扫描。零信任:MFA、SSO、RBAC/ABAC、短时令牌、设备姿态。

安全密钥审计

本节摘要:通过集中式密钥库(HashiCorp Vault、AWS Secrets Manager、Azure Key Vault)消灭密钥散落。绝不把凭证存进配置文件、版本控制里的 env 文件、电子表格。用 IAM 角色而非静态密钥;CI/CD 用 OIDC。AI 网关模式是 2026 的解法:应用 → 网关 → 模型 provider,网关在运行时从密钥库取凭证。在密钥库里轮换,所有应用几分钟内自动生效——无重新部署,无 Slack「谁有新 key」消息。轮换策略 ≤90 天;每次提交用 TruffleHog / GitGuardian / Gitleaks 扫描。零信任:MFA、SSO、RBAC/ABAC、短时令牌、设备姿态。PII 清洗用实体识别在转发前掩码 PHI/PII;一致性分词(Mesh 方法)把敏感值映射到稳定占位符,让 LLM 保留代码/关系语义。网络出口:LLM 服务放专用 VPC/VNet 子网,只白名单 api.openai.comapi.anthropic.com 等;阻断其他所有出站。2026 的事故驱动:Vercel 供应链攻击,通过被攻陷的 CI/CD 凭证窃取了数千客户部署的环境变量。

对应原课程:Phase 17 · Lesson 25 · 25-security-secrets-audit(原英文 phases/17-infrastructure-and-production/25-security-secrets-audit/docs/en.md)。

学习目标

阅读完本节,你应当能够:

  1. 列出四种密钥管理反模式(VCS 里的配置文件、硬编码 env、电子表格、静态密钥),并说出各自的替代。
  2. 解释「AI 网关从密钥库取凭证」模式作为 2026 生产标准。
  3. 实现一个带一致性分词(同值→同占位符)的 PII 清洗器,使语义得以保留。
  4. 说出 2026 年 Vercel 供应链事故及其对 CI/CD 凭证卫生的教训。

一、问题与直觉

实习生把带 API key 的 .env 提交了。很快删掉。key 已经进了 git 历史——GitGuardian 扫描抓到,你的轮换流程是「Slack 全员、改 40 个配置文件、重部署所有服务」。8 小时后,一半服务在线、一半在等部署窗口。

另一边,用户提示里有「我的 SSN 是 123-45-6789」。提示发去 OpenAI。你有 BAA 但内部策略是转发前掩码 PII。你没掩。

另一边,你的 EKS 集群里 LLM Pod 能到达任意互联网主机。有人通过 DNS 查询攻击者控制的域名外泄数据。没人拦。

LLM 服务的安全必须同时处理三个向量:密钥库背书的凭证、PII 清洗、网络出口过滤、审计日志。

二、核心概念

集中密钥库 + IAM 角色拉取

密钥库:HashiCorp Vault、AWS Secrets Manager、Azure Key Vault、GCP Secret Manager。单一真相源。

IAM 角色:应用/网关用 IAM 身份认证,而非静态密钥。密钥库在令牌生命周期内返回密钥。

AI 网关模式:网关在请求时从密钥库拉 OPENAI_API_KEY。在密钥库轮换;下一次请求拿到新 key。无重新部署。

轮换策略 ≤90 天

所有 API key、密钥库 root token、CI/CD 凭证。能自动轮换的就自动。手动轮换要记录与追踪。

密钥扫描

  • TruffleHog —— 提交上的正则 + 熵。
  • GitGuardian —— 商业,精度高。
  • Gitleaks —— 开源,跑在 CI。

每次提交都跑。检测到新密钥即阻断 PR。

零信任姿态

  • 所有账号强制 MFA。
  • 经 SAML/OIDC 的 SSO。
  • RBAC(基于角色)或 ABAC(基于属性)细粒度访问。
  • 短时令牌(小时级,非天)。
  • 设备姿态——只有带磁盘加密的公司设备。

PII / PHI 清洗

在提示离开你的基础设施前:

  1. 实体识别(spaCy NER、Presidio、商业方案)。
  2. 掩码匹配实体:"我的 SSN 是 123-45-6789""我的 SSN 是 [SSN_TOKEN_A3F]"
  3. 一致性分词(Mesh 方法):同值映射到同占位符,让 LLM 保留关系。
  4. 可选的 LLM 响应反向映射。

静态正则过滤抓基础模式;NER 抓更多。两者都用。

输入 + 输出护栏

输入:阻断已知越狱、违禁话题;按用户限流。

输出:正则清洗泄漏的密钥(API key 模式、拒绝上下文里的邮箱模式),分类器检测策略违规。

网络出口白名单

LLM 服务放专用子网:

  • 白名单:api.openai.comapi.anthropic.com、向量库端点、密钥库端点。
  • 其他全部:丢弃。
  • DNS 走只允许列表的解析器(防 DNS 隧道外泄)。

审计日志

每次 LLM 调用的不可变日志:

  • 时间戳。
  • 用户 / 租户。
  • 提示哈希(为隐私不存原始提示)。
  • 模型 + 版本。
  • token 计数。
  • 成本。
  • 响应哈希。
  • 任何护栏触发。

按法规要求留存(SOC 2 一年、HIPAA 六年)。

2026 年 Vercel 事故

供应链攻击:被攻陷的 CI/CD 凭证窃取了数千客户部署的环境变量。教训:CI/CD 凭证等同生产。存进密钥库。窄授权。激进轮换。

你该记住的数字

  • 轮换策略:≤90 天。
  • 每次提交扫描:TruffleHog / GitGuardian / Gitleaks。
  • Vercel 2026:CI/CD 凭证被攻陷 → 数千客户 env 泄漏。
  • 审计日志留存:SOC 2 = 1 年,HIPAA = 6 年。

三、从零实现:PII 清洗器 + 审计日志

原课程 code/main.py 实现带一致性分词的 PII 清洗器与只追加审计日志。下面给最小可读的一致性分词骨架。

import hashlib import time class PIIScrubber: """带一致性分词的 PII 清洗器:同一敏感值→同一占位符,保留语义。""" def __init__(self): self._map = {} # 真实值 → 占位符 def _token_for(self, entity_type, value): """同一值始终映射到同一占位符(Mesh 方法)。""" if value not in self._map: digest = hashlib.sha256(value.encode()).hexdigest()[:3].upper() self._map[value] = f"[{entity_type}_TOKEN_{digest}]" return self._map[value] def scrub(self, text, patterns): """patterns: [(entity_type, regex)] 列表""" import re for entity_type, regex in patterns: for m in re.finditer(regex, text): text = text.replace(m.group(0), self._token_for(entity_type, m.group(0))) return text # 案例:两个提示引用同一个 SSN → 得到同一个占位符 ps = PIIScrubber() ssn_re = (r"SSN", r"\d{3}-\d{2}-\d{4}") p1 = ps.scrub("我的 SSN 是 123-45-6789", [ssn_re]) p2 = ps.scrub("再说一次,SSN 是 123-45-6789", [ssn_re]) print(p1); print(p2) # 两个占位符相同 → LLM 能识别两处指同一人 def write_audit_log(prompt_hash, model, tokens_in, tokens_out, cost, trip): """只追加的审计日志(为隐私只存提示哈希)。""" entry = {"ts": time.time(), "prompt_hash": prompt_hash, "model": model, "tokens_in": tokens_in, "tokens_out": tokens_out, "cost_usd": cost, "guardrail_trip": trip} # 实际写入不可变存储(WORM、带版本的对象锁) return entry

💡 一致性分词是「清洗」与「保留语义」的平衡:若每次掩码都生成随机占位符,LLM 就看不出「这两处指同一个人」,在关系推理上会变弱;同值同占位让模型仍能做共指,又不外泄真值。

四、框架对比:密钥管理与 PII 清洗方案

维度 HashiCorp Vault AWS Secrets Manager Azure Key Vault GCP Secret Manager
部署 自托管或托管云 AWS 原生 Azure 原生 GCP 原生
IAM 集成 多云 AWS IAM Azure AD GCP IAM
动态密钥 强(数据库/云动态生成)
适合 多云、强动态密钥需求 AWS 全栈 Azure 全栈 GCP 全栈
维度 Microsoft Presidio spaCy NER 商业方案
检测 实体识别 + 可定制 命名实体 实体 + 上下文
集成 可管线化 Python 库 API/SDK
适合 想要开源且可定制 已用 spaCy 想要开箱精度

心法:密钥库选你的云栈(或 Vault 跨云);PII 清洗 Presidio 是开源默认,spaCy 补足,商业方案顶替。无论哪个,一致性分词是保留 LLM 语义的关键。

五、可复用产物

本节产出 outputs/skill-llm-security-plan.md(原课程目录)。给定法规范围与现状,它规划:

  1. 密钥库迁移:从散落到 Vault/Secrets Manager 的迁移路径与 IAM 角色接入。
  2. PII 清洗器:实体识别 + 一致性分词规则,以及可选的反向映射。
  3. 网络出口:专用子网 + 白名单(OpenAI/Anthropic/向量库/密钥库)+ DNS 解析器限制。
  4. 审计日志:不可变日志字段与留存分层(SOC 2 一年、HIPAA 六年)。

六、练习

  1. 跑通清洗器:运行 code/main.py。发两个引用同一 SSN 的提示,确认两者得到同一占位符。

  2. 设计出口策略:为 vLLM-on-EKS、调用 OpenAI + Anthropic + Weaviate 的部署设计网络出口策略。

  3. git 历史密钥:你在 git 历史里发现一个两年前的 key。正确响应——轮换、洗历史,还是两者?论证。

  4. 审计日志分层:你的审计日志每天涨 10GB。设计留存分层(热 30 天、温 12 个月、冷 6 年)。

  5. 反向分词值不值:论证反向分词(把真值替换回 LLM 响应)是否值得相对保留占位符可见的复杂度。

本节要点回顾

  1. 集中密钥库消灭散落:Vault/Secrets Manager/Key Vault,绝不存配置/env/电子表格。
  2. IAM 角色优于静态密钥:应用用身份认证,密钥库返回短时凭证。
  3. AI 网关模式:网关运行时从密钥库拉凭证,轮换几分钟全生效,无重新部署。
  4. 轮换 ≤90 天:所有 API key、root token、CI/CD 凭证。
  5. 每次提交扫描:TruffleHog/GitGuardian/Gitleaks 阻断含新密钥的 PR。
  6. 零信任:MFA、SSO、RBAC/ABAC、短时令牌、设备姿态。
  7. PII 清洗三步:实体识别→掩码→一致性分词(同值同占位符保留语义)。
  8. 网络出口白名单:专用子网,只放 provider/向量库/密钥库,DNS 走受限解析器防隧道外泄。
  9. 审计日志不可变:时间/用户/提示哈希/模型/token/成本/响应哈希/护栏触发,SOC 2 一年、HIPAA 六年。
  10. Vercel 2026 教训:CI/CD 凭证等同生产,被攻陷可窃取数千客户 env——窄授权、激进轮换、存密钥库。

下一节,我们把安全推进到合规——SOC 2、HIPAA、GDPR、PCI-DSS、EU AI Act、ISO 42001,以及跨框架控制映射如何减少审计疲劳。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U