摘要

  • RFC 1447 的每条访问控制记录由目标参与方、主体参与方和资源上下文共同索引,允许的 PDU 类别另行编码。
  • 一条消息拥有已知来源、甚至通过认证,仍不等于它有权在任意上下文中执行任意操作;授权发生在接收端的本地关系里。
  • 后来的 VACM 更换了模型与词汇,却仍把安全身份、组、上下文、安全级别、读写通知视图和具体对象分开判断。

35 的含义必须被拆开

RFC 1447 是初版 SNMPv2 框架的一部分,名称是 Party MIB。这里的 party 不是自然人的简单别名,而是一个受到行政限制的概念执行环境。同一 SNMPv2 实体可以实现多个参与方,它们的操作集合可以重叠,也可以互不相交;某个远端参与方也可以只存在于本地认知里,并不由本机实际执行。

因此,参与方标识首先定位一份行政记录。它没有随身携带一张适用于所有设备、上下文与操作的“管理员证”。

这项限制在 aclTable 中变成了数据结构。表项的索引不是单一用户,而是 { aclTarget, aclSubject, aclResources }。aclTarget 指向被请求执行操作的目标参与方,aclSubject 指向提出请求的主体参与方,aclResources 指向操作涉及的 SNMPv2 上下文。

三项共同命中之后,aclPrivileges 才回答允许什么。Get 是 1,GetNext 是 2,Response 是 4,Set 是 8,GetBulk 是 32,Inform 是 64,SNMPv2-Trap 是 128。允许多种消息类别时就把对应值相加;零表示空集。

默认值 35 等于 Get、GetNext 与 GetBulk。它不是比 34 更有权,也不是比 36 更少权。43 是在同一读取组合上加入 Set;4 则只允许 Response。整数是一组动词的压缩表示,而不是人的级别。

一旦界面把它简化成“可信”或“管理员”,证据就发生了变化。“可信”无法说明谁向谁发出请求、访问哪个上下文,也无法说明允许读取、写入、响应还是通知。

请求方向也是政策的一部分

RFC 1447 的初始配置示例把方向差异写得很清楚。管理端主体可以被允许向代理端目标发出 Get、GetNext 与 GetBulk;反向表项则可以允许 Response 与 Trap。询问权并不会自动生成回答权,收到回答的权利也不会自动生成 Set 权限。

这不是重复记录,而是两条关系。发起方和接收方互换,政策含义也随之改变。同一个参与方既可以在一条记录中是主体,也可以在另一条记录中是目标,但两条记录的上下文和动词集合不必相同。

这里可以看到一种早期互联网设计习惯:把共同语法做得足够明确,同时把未来的授权决策留给本地。标准规定如何表达关系,却没有让一个中心身份为所有接收端决定权限。

发送成功没有替远端作出决定

RFC 1445 规定,访问控制在收到管理通信时应用,而不是在发送时应用。发送端可以组装来源参与方、目标参与方、上下文与 PDU,也可以把格式正确的消息交给传输层;这些动作都没有运行远端实体当前的本地访问政策。

接收后的处理是一串不可互换的检查。目标参与方是否在本地数据库中,而且是否由本实体实现?来源参与方是否已知?消息在双方配置的认证协议下是否成立?上下文是否存在?本地访问政策中是否有与来源、目标和上下文匹配的记录?该记录是否包含当前 PDU 类别?

每一步都可能给出不同事实。格式正确的消息可能指向未知目标;已知目标可能收到未知来源;通过认证的来源可能请求不存在的上下文;上下文存在时,ACL 仍可能缺失;ACL 命中时,也可能只允许读取而不允许 Set。

所以,“用户已登录”不能替代整条证据链。身份只是关系中的一个坐标。两个接收端可以认识同一个主体标识,却维护完全不同的目标、上下文、视图和权限表。

上下文把对象范围留在授权里

SNMPv2 上下文表示一组受管对象资源。若资源在本地,上下文指向一个 MIB 视图;若资源在远端,上下文还可以描述代理关系。同一个主体和目标,在不同上下文中可以拥有不同权限;同一个 Set 动词,也可能落到完全不同的对象表面。

这使“可以读取”保持为不完整句子,直到读者补上“在哪个上下文、由哪个目标、针对哪些对象”。访问表允许某类请求之后,MIB 视图仍限定操作实际可触及的对象。

拒绝的证明范围也因此很窄。某个主体通过一个上下文看不到对象,只能证明这一接收端在这一行政状态下对这一关系作出的结果。它不能证明对象物理不存在、别的上下文也排除它,或另一主体同样无权访问。

权限记录本身也是运行状态

aclEntry 不只保存权限值。它还有 aclStorageType 与 aclStatus。前者区分易失、非易失和永久存储;后者采用 RowStatus。读取到一行,不等于这行已经生效、将在重启后存在,或可由当前管理者修改。

这篇文章不重复 RowStatus 的通用生命周期史,但它在这里揭示了一个重要边界:授权政策本身也是可管理、可失效、可丢失的状态。管理流量甚至可以修改决定后续管理流量命运的政策对象。

成功写入 ACL 字段仍不足以证明下一条请求会按预期获准。操作者还需保存写入值、协议响应、行状态、依赖视图与上下文的活动状态,并以新的接收端请求验证实际决定。若要声称变更持久,还要跨重启或相应时间边界观察。

VACM 保留了“关系”,没有保留同一张表

初版 party 架构后来退出标准路线。RFC 2575 以及取代它的 RFC 3415 在模块化 SNMP 架构中定义了 VACM。它不是 Party MIB 的同名翻版:安全模型与 securityName 先映射到组;组、contextName、安全模型和安全级别共同选择访问表项;读、写或通知再选择一个视图;最后还要判断具体变量名是否在该视图中。

VACM 为不同断点给出不同结果:没有上下文、没有组映射、没有访问表项、没有视图,以及对象不在视图内。这些结果不应全部压成“凭据错误”。它们指向关系链中不同的缺项或排除项。

两代模型的结构和安全架构并不相同,不能互相替换。真正延续的是一种克制:回答“是谁”只完成了一部分工作。在哪里、以何种安全模型与级别、执行哪类动作、触及哪个对象,仍要进入本地决定。

声明、执行与结果属于不同现实层

Lu Heng 的运行代码原则把规范、实现、验证、部署和使用分开;现实层分析则反对让符号地位直接冒充可执行效果。RFC 1447 提供了一个尺寸很小、但结构清楚的历史样本。

参与方标识属于符号层,ACL 行表达本地政策,接收端处理执行政策,协议响应记录一次结果,而计数器、接口状态或路由行为是否真的改变,还需要另一种观察。

这些记录都是真实的,问题只在越权解释。已知身份不证明授权;存在的 ACL 行不证明处于活动状态;被接受的 Set 不证明受管系统发生了正确、持久的变化;返回值也不证明语义正确。

Party MIB 今天属于 Historic。它留下的证据纪律仍然锋利:权限最好保留为可以重建的关系,而不是附着在身份上的漂亮形容词。

来源