跳转到主要内容

运行后访问权限是生命周期缺陷:Agent 凭证需要终态

运行结束后仍然存活的凭证会变成长期授权。修复之道是建立带终态的生命周期契约,而不是缩短有效期。

带有状态指示灯和网络布线的服务器机架特写,代表工作负载身份与访问基础设施。

报道中的模式

有效期窗口被设置得相当宽松,以避免运行中途失败。一个偶尔需要四十分钟的任务,会拿到一张二十四小时有效的凭证。当运行正常终止时,没有任何机制撤销该授权,因为正常终止不被视为安全事件。结果是休眠权限不断累积,而没有人把它当作风险面来跟踪。它不会出现在访问审查中,因为它从未作为一项权限被正式配置;它出现在日志里,表现为来自一个技术上仍然存活的工作负载身份的成功认证。

问题不在于 Agent 怀有恶意。问题在于生命周期没有终态。为某个任务签发、任务结束后却从未撤销的凭证,不是临时凭证。它是一张名字具有误导性的长期授权。

为什么仅靠有效期无法解决

足够长的运行总需要一条续期路径。任何执行多步骤工作的 Agent——获取数据、调用工具、等待人工审批、重试不稳定的依赖——最终都会超出较短的有效期。续期路径正是授权悄然变成永久授权的地方。如果续期是自动的且绑定身份,Agent 就能无限期地刷新自己的访问权限,有效期便沦为一种只产生日志噪音、而非实际控制的形式。

基于时间的有效期也与任务完成无关。危险的窗口是成功之后的那段时间,而不是之前。如果运行在五分钟内完成且授权在完成时被撤销,那么一小时后过期的凭证是安全的。如果运行在五分钟内完成而授权还存活五十五分钟,它就是不安全的。缩短有效期能缩小窗口,但无法关闭它,而且会引入一种新的失败模式:运行因凭证过期而在任务中途失败,这又会促使运维人员重新延长窗口。控制措施在过于宽松与过于脆弱之间来回摆动,因为它衡量的是错误的东西。

一个具体的机制能让这个缺口变得可见。设想一张以签名令牌形式签发的授权,其 subject 声明为 agent:researcher-07,scope 为 read:customer_records。该令牌的 exp 为二十四小时。需要它的那次运行在八分钟内就完成了。在剩下的二十三小时五十二分钟里,任何能够出示该令牌的进程——Agent 本身、被攻陷的工具、从日志中重放的请求——都拥有与原始运行相同的访问权限。令牌的 subject 是 Agent,而不是运行,因此凭证权威机构没有任何声明可用来判定工作已经结束。要撤销,就得按 Agent 身份枚举令牌,并猜测哪些已经失效。那是运维层面的猜测,不是契约。

Hands conducting a lab experiment with Erlenmeyer flasks of blue liquid

每张授权都应有终态

修复之道是生命周期契约,而不是更短的有效期。每张凭证都针对一个运行标识符签发,并带有一个强制的终态转换:已完成、失败或已放弃。运行标识符是授权的 subject,而不是 Agent 身份。Agent 身份可以作为属性出现,但它不是授权所绑定的对象。

编排器发出终态事件。它本来就知道运行何时结束,因为它是启动和停止运行的组件。当运行到达终态时,编排器向凭证权威机构发布一个事件——run.completed、run.failed、run.abandoned。凭证权威机构消费该事件,并撤销针对该运行标识符签发的每一张授权。撤销不是 Agent 的责任。一个崩溃、陷入循环或被终止的 Agent 无法被信任去自我清理,而依赖 Agent 配合的设计根本算不上控制措施。

续期是一张带有新标识符和明确理由的新授权。如果某次运行需要更多时间,编排器针对同一运行标识符请求一张新凭证,凭证权威机构记录该请求并附上原因:continuation: awaiting human approval。这样审计轨迹显示的是延续,而不是延长。审查历史的运维人员看到的是一系列授权,每张都有开始和结束,而不是一张被悄然刷新的授权。这一区别很重要,因为延长会隐藏临时授权变成永久授权的那一刻;而延续则让那一刻变得明确且可审查。

权衡是真实存在的。终态契约要求编排器成为运行生命周期的权威来源,并要求凭证权威机构在运行结束时可达。如果编排器在没有发出终态事件的情况下死亡,授权会一直保留,直到某个对账流程将其捕获。该对账是一次扫描,将活跃授权与活跃运行进行比对,并撤销其中的差集。它比事件驱动的撤销更慢,并引入了一个授权比其运行存活更久的窗口。契约并不能消除这个窗口;它只是限定了窗口的范围并使其可观测。一个连有界窗口都无法容忍的系统需要不同的架构——按步骤签发短时令牌,编排器是唯一持有者——但那种架构在延迟和复High voltage power line and insulators against a clear blue sky

枚举 Agent 身份持有的长期授权,并将其与活跃运行进行比对。差集就是暴露面。这是大多数团队已经拥有的两个数据集之间的连接:凭证权威机构已签发授权的列表,以及编排器正在运行的任务列表。这个查询并不复杂,但很少被执行,因为 Agent 凭证往往被当作基础设施而非权限来对待。

对超出其运行存活时间超过既定阈值的授权发出告警。该阈值是策略决策,不是技术常量。几分钟的阈值可以容纳对账延迟;数小时的阈值则表明终态事件没有被发出或消费。告警应针对授权触发,而不是针对 Agent,因为 Agent 不是风险单元。授权才是。

将孤立授权视为访问审查项,与人类权限采用相同的审查节奏。如果人类员工的访问权限每季度审查一次,Agent 的长期授权也应按同样的时间表、同样的证据要求进行审查。审查应提出一个具体问题:这些授权关联的是哪些运行,那些运行是否仍然活跃?无法关联到活跃运行的授权是一项发现,而不是误报。

更深层的要点是,Agent 凭证并非特例。它们是具有生命周期的权限,而生命周期需要终态。有效期是凭证的属性;终止是授权的属性。混淆两者,正是把一次已完成的运行变成长期授权的原因。修复之道不是更短的时钟。修复之道是一份契约,它规定:工作结束时,访问权限随之结束。

首先应埋点监测什么

从运行标识符开始。如果授权无法与运行关联,就不可能有生命周期契约。然后从编排器发出终态事件,即使凭证权威机构尚未消费它,这样事件流就已存在且可重放。接着构建对账扫描,因为它是事件路径未能覆盖的每一种失败模式的兜底。顺序很重要:身份第一,事件第二,对账第三。跳过第一步会产生无法采取行动的告警;跳过第三步会产生一个只有在其他一切正常时才正确的系统。

封面照片:panumas nikhomkhai / Pexels。

分享XLinkedIn永久链接6 分钟阅读

相关阅读

这能回答的问题

Why does shortening credential expiry not fix post-run access?

Short expiry reduces the window but does not close it, and long runs always need a renewal path. Renewal logic bound to agent identity is where temporary grants become permanent. The dangerous period is after success, not before, so time-based expiry is uncorrelated with task completion.

What is a terminal state for an agent credential?

A credential is issued against a run identifier and carries a mandatory terminal transition: completed, failed, or abandoned. The orchestrator emits the terminal event, the credential authority consumes it, and revocation is not the agent's responsibility.

How should renewal work under a lifecycle contract?

Renewal is a new grant with a new identifier and an explicit justification. The audit trail then shows continuation rather than extension, making the moment a temporary grant becomes permanent visible and reviewable.

What operational checks catch orphaned agent grants?

Enumerate standing grants held by agent identities and compare them against active runs; the difference is the exposure. Alert on grants that outlive their run by more than a defined margin, and treat orphaned grants as an access review item with the same cadence as human entitlements.