智能体面试准备(八十):智能体凭证治理与最小权限访问工程——密钥托管、临时凭证与全链路审计

智能体面试准备(八十):智能体凭证治理与最小权限访问工程------密钥托管、临时凭证与全链路审计

引言

本文是系列第 80 篇。前面讲过工具沙箱、人在回路、多租户权限,这一篇聚焦一个更细但后果极重的问题:Agent 调用外部系统时,凭证(Credential)怎么管

这件事一旦做错,后果是灾难性的:把数据库密码写进 prompt、把长期有效的 API Key 硬编码在镜像里、Agent 被提示词注入后拿着高权限 token 删库。而面试官考察"Agent 安全"时,凭证治理是绕不开的一环------因为它最能区分"知道要加锁"和"真的做过权限体系"。

本篇讲清四件事:凭证不能出现在模型可见的任何地方、要用短期凭证、要按任务最小授权、要能追溯每一次使用。

复制代码
凭证治理总览
==================================================
          用户 / 上游系统
                 │  1. 身份认证(OIDC/OAuth)
                 ▼
        ┌─────────────────────┐
        │  凭证颁发服务 STS    │
        │  签发短期、受限凭证  │
        └──────────┬──────────┘
                   │ 2. 短期凭证(分钟级、范围受限)
                   ▼
        ┌─────────────────────┐
        │  Agent 运行时        │
        │  ┌───────────────┐  │
        │  │ 凭证代理 Proxy │  │  <- 模型永远拿不到明文
        │  └───────┬───────┘  │
        └──────────┼──────────┘
                   │ 3. 代理注入到真实调用
                   ▼
        外部系统(DB / SaaS / 内部 API)
                   │
                   ▼ 4. 审计与回溯

一、铁律:凭证绝不进模型上下文

先看反面清单,这些都是真实事故:

反模式 后果
API Key 写进 system prompt 模型可能原样输出(注入/追问即泄露)
密钥硬编码在镜像/环境变量 镜像泄漏即全量泄露,轮换要重新发版
用同一个高权限账号跑所有任务 一次越权影响全部数据
凭证长期有效(不过期) 泄露后窗口无限大
把数据库 DSN(含密码)传给 LLM 让它"自己连" 完全失控

正确做法是凭证代理(Credential Proxy):模型只发出"我要调用 X 工具"的意图,真实凭证由旁路代理注入,模型全程接触不到明文。

复制代码
# 反例:凭证进入 prompt
bad_prompt = f"用这个 key 调接口:api_key={SECRET}"   # 严禁

# 正例:Agent 只声明意图,凭证由代理注入
def invoke_tool(tool_name, args, ctx):
    cred = sts.issue(                 # 向凭证服务申请短期、限范围凭证
        tool=tool_name,
        tenant=ctx.tenant,
        ttl_seconds=300,
        scope=f"{tool_name}:read",    # 最小权限
        reason=ctx.task_id,
    )
    headers = {"Authorization": f"Bearer {cred.token}"}
    return http_call(TOOLS[tool_name].endpoint, args, headers=headers)

二、短期凭证与最小权限

凭证设计三原则:短期、最小、可撤销

原则 做法 参数示例
短期 TTL 分钟级,用完即废 ttl=300s
最小权限 按工具+操作+资源范围授权 crm:order:read 而非 crm:*
可撤销 支持按 task_id 即时吊销 revoke(task_id)
绑定上下文 凭证绑定租户/会话/任务 换任务即失效
复制代码
class ScopedCredential:
    def __init__(self, token, scope, expires_at, task_id):
        self.token, self.scope = token, scope
        self.expires_at, self.task_id = expires_at, task_id

    def valid(self, required_scope, task_id):
        return (time.time() < self.expires_at
                and task_id == self.task_id
                and scope_allows(self.scope, required_scope))

def scope_allows(granted, required):
    """支持前缀通配的最小权限判定"""
    g, r = granted.split(":"), required.split(":")
    return len(g) == len(r) and all(a == b or a == "*" for a, b in zip(g, r))

三、按任务授权与人工升级

不同风险等级的任务,凭证获取方式不同:

风险等级 示例 授权方式
只读低风险 查询天气、检索文档 自动颁发,无需审批
有副作用 发消息、写工单 自动颁发 + 事后通知
高风险 转账、删数据、发外部邮件 人工审批后颁发,或人在回路确认
越权请求 超出该 Agent 权限范围 直接拒绝并告警

实现上给每个工具标注风险等级(注册在工具注册中心,见上篇 B79),凭证服务根据等级决定"自动发 / 需审批 / 拒绝"。风险分级 + 自动颁发 + 高风险人工升级 是标准三段式。

复制代码
RISK = {"read_only": "auto", "side_effect": "auto+notify",
        "high_risk": "require_approval"}

def issue_for(tool, ctx):
    level = TOOLS[tool].risk
    policy = RISK[level]
    if policy == "require_approval":
        if not approvals.granted(ctx.task_id, tool):
            raise PermissionError(f"{tool} 需人工审批")
    return sts.issue(tool=tool, tenant=ctx.tenant,
                     ttl_seconds=300 if level != "high_risk" else 600,
                     scope=TOOLS[tool].required_scope, reason=ctx.task_id)

四、防注入:凭证在攻防中的位置

提示词注入的真实危害不是"模型说错话",而是攻击者借模型之手调用高权限工具。凭证治理正是对抗链的关键一环:

复制代码
防线叠加(缺一不可)
1. 凭证不进上下文   -> 注入者无法直接套出密钥
2. 最小权限 scope   -> 即使被诱导调用,影响范围受限
3. 高风险需审批     -> 关键动作有人工闸门
4. 短期 TTL         -> 泄露窗口极小
5. 全链路审计       -> 事后可追溯、可告警

注意:不要把"模型判断安全"当作唯一闸门。模型的判断可被诱导,真正的闸门必须是策略引擎(代码级、确定性),模型只能提供建议。

五、审计与轮换

能力 说明
审计日志 每次凭证颁发与使用记录:谁、何时、工具、参数摘要、结果
异常检测 频率异常、非常规时段、跨租户访问、权限提升尝试
密钥轮换 定期自动轮换;泄露时一键吊销
最小可见 日志中脱敏,绝不记录明文凭证
复制代码
def audit_log(tool, args, ctx, result):
    log.info({
        "ts": time.time(),
        "tenant": ctx.tenant,
        "task_id": ctx.task_id,
        "tool": tool,
        "args_digest": hashlib.sha256(
            json.dumps(args, sort_keys=True).encode()).hexdigest()[:16],
        "status": "ok" if result.ok else "fail",
        # 注意:不记录明文参数与凭证
    })

六、落地检查清单

  • 凭证是否 100% 不进入模型上下文(prompt / 工具返回值 / 日志)?
  • 是否全部使用短期凭证(TTL ≤ 分钟级)?
  • 是否按"工具+操作+资源"三维最小授权?
  • 高风险工具是否有人工审批闸门,且闸门在策略层而非模型层?
  • 是否能按 task_id 即时吊销?
  • 是否所有调用都有审计,且日志脱敏?
  • 密钥是否支持自动轮换与一键吊销?

面试速答

问:Agent 调用外部 API 的密钥怎么管?

答:凭证绝不进模型上下文。用凭证代理:模型只声明调用意图,真实凭证由旁路服务按"短期 TTL + 最小 scope + 绑定 task_id"签发并注入,模型全程接触不到明文。

问:短期凭证的具体参数怎么设?

答:TTL 分钟级(如 300s),scope 按工具+操作+资源三维最小授权(如 crm:order:read 而非 crm:*),绑定 task_id 与租户,支持按 task_id 即时吊销。

问:提示词注入怎么防?

答:五层叠加------凭证不进上下文、最小权限 scope、高风险人工审批、短期 TTL、全链路审计。关键是安全闸门必须在策略层(代码确定性),不能依赖模型判断。

问:高风险操作怎么控制?

答:工具在注册中心标注风险等级,凭证服务按等级决定自动颁发/需审批/拒绝。高风险(转账、删数据、外发邮件)走人工审批或人在回路确认,审批通过才发凭证。

高频追问清单

  1. 凭证代理挂了或被绕过,怎么保证 Agent 拿不到明文?
  2. 多租户场景下凭证怎么隔离?跨租户访问怎么检测?
  3. 短期凭证 TTL 设太短导致频繁申请,性能和可用性怎么权衡?
  4. 工具返回值里意外带了密钥(如接口返回 token),怎么清洗?
  5. Agent 需要代表用户操作(on-behalf-of),OAuth 委托授权怎么设计?
  6. 高风险审批流超时未响应,任务应该阻塞、降级还是中止?
  7. 凭证审计日志本身怎么防篡改?
  8. 密钥自动轮换时,在途请求怎么处理才不中断?
  9. 如何检测"凭证被异常使用"(频率、地理、时段异常)?
  10. 本地/私有化部署没有云厂商 STS,怎么自建短期凭证服务?
相关推荐
tachibana22 小时前
Embedding 有哪几种算法?
人工智能·算法·ai·大模型·llm·embedding·agent
W658034196 小时前
Meta Muse Glimmer 30B开源深度拆解:Apache 2.0+投机解码,24GB显卡跑本地Agent
ai·开源·大模型·apache·deepseek
console.log('npc')12 小时前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
腾视科技-AI12 小时前
腾视科技AIBOX双版本重磅发布!本地安全与全球适配,解锁视频智能新可能
大数据·人工智能·科技·安全·大模型·腾视科技·ai算力盒
猎头南楼14 小时前
VLA 模型落地端侧:从架构选型到量化部署的工程实践笔记
笔记·架构·大模型
夏文强15 小时前
DeepSeek Harness 权限与审批:给 Agent 上一把 human-in-the-loop 的安全阀
人工智能·开源·大模型·agent·deepseek
loong_XL15 小时前
生产级 Agent 开发方法论:速度、质量、价格与工程化
ai·大模型·agent·loop·智能体·vibe
甜辣uu18 小时前
智能体Agent性能优化从原理到实战
人工智能·性能优化·大模型·llm·agent·rag·智能体