# SOC 2 证据表能证明代理操作吗？

代理活动带来了普通应用日志无法解决的审计问题。服务账户日志可以告诉你某个凭据调用了某个端点，但通常无法说明当时是否有特定代理进程获得授权、是否有人批准了这次操作、权限后来是否被撤销，或交给审计人员的记录是否与当时生成的记录相同。

一份可用的 SOC 2 证据包必须重建一次决策，而不只是展示时间线。对于每项重要操作，审计人员都应该能从执行者和授权一路追踪到调用、结果以及保留记录的完整性。如果其中任何关联依赖管理员的记忆或手工编辑的电子表格，这项控制就没有看上去那么可靠。

Sallyport 围绕这条链路构建：代理接收操作结果，凭据留在本地加密凭据库中，应用记录代理运行过程和每次单独调用。只有把这些记录转化为可测试的证据，而不是把日志当作合规装饰，这种设计才真正有用。

## 控制必须能够重建决策

AICPA 的 2017 年信托服务标准是评估标准，不是一份截图菜单。安全通用标准要求管理层建立并运行控制，限制逻辑访问、监控系统运行、响应已发现的问题，并管理变更。审计人员会测试你描述的控制、控制总体，以及它在检查期间是否有效运行。

这一区别对代理操作很重要。“代理需要审批”描述的是产品行为。“每个新启动的代理进程在使用受保护的操作通道前，都必须获得可归属的授权，公司还保留了能将授权与后续调用关联起来的记录”才是一项可以测试的控制声明。

先写风险，再提出证据要求。一个实用的风险声明可以这样写：

> 未经批准或曾经获批的代理进程可能使用组织凭据调用外部 API 或执行 SSH 命令，从而导致未经授权的访问或运营变更。

控制应当用清晰的语言回应风险，证据则应回答五个更具体的问题：

1. 哪个进程尝试执行了这项操作？
2. 当时它拥有什么权限？
3. 谁授予了这项权限？
4. 随后具体执行了什么外部操作？
5. 是否能发现有人尝试改写历史记录？

团队经常把这些问题混在一起。他们把目标允许列表称为审批控制，把成功的 API 响应称为授权记录，或者因为日志导出只能读取，就称其为不可变。每种说法其实描述的是不同的事。

目标限制了进程可以在哪里操作。授权记录说明谁允许进程操作。调用记录说明它尝试做了什么，以及结果如何。完整性验证回答保留的顺序是否被修改。应在系统说明和证据表中把这些声明分开。审计人员不需要流行术语，他们需要一位能够提出明确范围的控制负责人，并提供相应记录。

## 审计人员可以测试的 SOC 2 证据表

用一张证据表作为工程、安全和审计人员之间的工作协议。不要把它做成产品功能清单。每一行都应说明风险、控制活动、证据总体、测试方法和失败信号。

| 控制领域 | 控制活动 | 证据总体 | 可能对应的标准 | 审计测试 | 失败信号 |
|---|---|---|---|---|---|
| 新代理会话 | 新代理进程必须在执行受保护操作前获得会话授权 | 检查期间的会话日志 | CC6.1、CC6.2 | 抽取会话样本，追踪审批到第一次受保护调用 | 存在调用但此前没有审批，或凭据库拒绝了操作 |
| 敏感的单次操作 | 标记为需要审批的凭据每次使用都必须经过人工决定 | 标记凭据的活动日志条目 | CC6.1、CC7.2 | 抽取调用样本，检查每次调用对应的决定 | 标记凭据在没有审批记录的情况下被使用 |
| 会话撤销 | 审核人员可以终止活动会话，之后该会话的调用会被拒绝 | 撤销事件及之后的尝试 | CC6.2、CC7.3 | 重新执行撤销，并测试之后的一次操作尝试 | 会话在撤销后仍执行了操作 |
| 调用问责 | 每次完成或被拒绝的调用都记录会话、目标、操作、结果和时间 | 活动日志 | CC7.2 | 将抽取的调用与会话和结果记录进行核对 | 字段缺失、标识重复，或调用无法追踪 |
| 审计完整性 | 保留的加密审计序列可以在不访问凭据库的情况下独立验证 | 归档日志范围和验证记录 | CC7.2、CC7.4 | 对抽取的保留范围执行离线验证 | 验证报告显示链断裂，或无法取得该范围 |
| 系统变更 | 影响网关的代码、配置和部署变更遵循公司的变更流程 | 拉取请求、工单、测试结果、部署记录 | CC8.1 | 从审批追踪抽样的生产变更直到部署 | 未经批准或未测试的系统变更进入生产环境 |

标准引用只是起点，并不保证覆盖范围。最终映射取决于服务说明、风险评估、系统边界和审计人员的判断。尤其不要把每条代理记录都强行归入 CC8.1。AICPA 的示例和指南把变更管理视为对应用程序及相关技术变更的控制。修改客户账户、发送支持回复或重启远程进程的调用属于运营操作。只有当它是系统本身经过批准和测试的变更的一部分时，才属于变更管理证据。

这张表还可以避免审计周常见的失败：收集某一天的完美材料。Type 2 检查关注的是声明的控制在整个期间是否有效运行。“总体”一栏不是文书工作，它告诉你在审计人员抽样前，必须能够提供哪个完整的集合。

## 会话审批证明的是进程权限，不是身份治理

每次会话审批可以证明某次特定的代理运行获得了使用操作网关的许可。它不能证明公司正确管理了员工访问、正确配置了身份提供商账户，或审核了云管理员角色。这些都需要各自的控制和记录。

更准确的声明是：新进程第一次发起受保护调用前，会先获得审批决定。记录应保留会话标识、进程身份、可用时的代码签名权限、决定时间、审批人身份和终止状态。在 Sallyport 中，审批卡片首先显示进程的代码签名权限，因此人工决定针对的是实际请求访问的可执行文件，而不是代理提供的模糊名称。

这是一个重要区别。代理可以在提示词、终端标题或进程参数中随意称呼自己。批准自报名称的控制很容易被绕过。显示代码签名权限的控制为审核人员提供了一个稳定属性。它并不会消除对已签名软件的信任要求，但能诚实地说明信任边界。

进行会话审批测试时，可以让审计人员从会话总体中抽取样本，然后双向追踪每条记录：

- 从会话审批开始，找到紧随其后的第一次受保护调用。
- 从活动条目开始，找到授权该调用的会话。
- 确认调用时间晚于审批，并早于会话退出或撤销。
- 确认被拒绝的会话没有成功的受保护调用。
- 确认会话记录对进程的识别足以支持所声明的控制。

不要依赖审批对话框截图。截图适合记录控制设计，但不是总体证据。对话框关闭后，记录仍必须存在，能够按标识查询，并且无需某个人凭感觉挑选正确行，就能与活动记录关联起来。

也不要在实际并非如此时，声称会话审批实现了最小权限。会话决定可以控制进程是否能操作。最小权限取决于审批后可用的凭据、目标范围、操作和权限。如果一个获批代理可以使用拥有无限生产权限的凭据，那么审批只是门禁，并没有缩小权限范围。应如实描述。

## 每次调用审批适用于无法安全批量处理的操作

每次调用审批提供的保证与会话审批不同。它要求在某项具体凭据即将被使用时，重新取得人工决定。适用于风险来自单次调用，而不只是来自允许代理进程开始工作的操作。

合适的对象包括能够改变访问权限、删除数据、修改账单信息、发布部署，或在特别敏感主机上执行命令的生产凭据。目的不是让每项代理操作都变得繁琐，而是在单次误用会造成严重影响的交易边界进行审核。

证据必须将审批绑定到一次具体使用。可靠的活动记录至少包含：

- 唯一调用标识及关联的会话标识。
- 受保护的凭据引用，但不要把秘密值放进记录。
- 通道、目标、操作和时间戳。
- 对于需要审批的调用，记录决定状态和审批人。
- 结果，包括被拒绝、失败或完成。

不要接受一条只是出现在某次后续操作附近的审批记录。时间接近并不等于绑定。如果审核人员批准了调用 A，而代理使用同一凭据执行调用 B，证据必须说明 B 是否独立需要并获得了审批。

团队经常在这里反应过度。他们让人工审核介入普通读取操作，之后审核人员不经查看就连续批准几乎相同的卡片。控制仍然会生成记录，但审核已经变成形式。应把每次调用审批保留给真正值得审核的凭据或操作。普通工作使用会话审批，并另外缩小凭据范围。

审核人员需要足够的上下文来做决定。HTTP 操作通常需要方法、目标、凭据身份和对请求影响的安全描述。SSH 操作需要主机身份，以及命令或受约束的命令描述。不要为了让证据更丰富，就把秘密放进审批内容。通过审批卡片泄露的秘密仍然是泄露。

## 撤销必须产生可证明的拒绝

如果撤销证据只记录了用户界面事件，它就没有价值。控制真正生效的标志是权限终止，以及之后的尝试确实因此失败。

在审计人员要求之前先完成这项测试。启动一个有权执行非生产测试操作的会话，确认一次调用成功。在进程仍运行时撤销会话，然后让同一进程再次调用。保留四条关联记录：第一次成功调用、撤销事件、第二次被拒绝的调用以及会话状态。

测试工作表可以简单到这样：

```text
Test ID: AGT-REV-01
Session ID: ____________________
First call ID and result: ____________________
Revocation time and actor: ____________________
Second call ID and denial result: ____________________
Reason shown for denial: ____________________
Reviewer and date: ____________________
```

顺序本身就是控制。14:03 发生撤销，14:07 却出现成功调用，这要么是控制失败，要么是时钟问题，要么是会话标识的含义与你所声明的不一致。这些情况都不能用含糊的解释带过。

区分普通会话退出和明确撤销。退出是因为进程停止运行而结束会话。撤销是因为审核人员决定收回权限而终止授权。两者都应阻止之后的调用，但只有撤销能证明人在发现问题时可以终止正在运行的进程。在证据表中分别保留这两种事件类型。

这项控制也应纳入事件响应实践。如果审核人员发现可疑的调用序列，他们应知道谁能撤销运行、拒绝会在多快时间内生效，以及事件会出现在日志的什么位置。只写着“禁用代理”却没有说明实际操作的书面流程，在代理已经执行任务时是不够的。

## 离线验证可以在应用退出审计现场后检查历史

活动日志提供问责能力。可独立验证的哈希链则让你能够测试保留的序列是否仍然完整。这两者有关联，但不能互相替代。

Sallyport 从一个加密且可盲写的审计日志生成会话和活动视图。离线命令 `sp audit verify` 会检查密文上的链，不需要访问凭据库。这是一项有用的证据，因为验证器可以在不要求生成报告的系统解密凭据或开放凭据库的情况下，测试保留的历史记录。

不要夸大它能证明的范围。根据链的设计和保留材料，哈希链验证可以发现验证范围内缺失、顺序改变或被修改的记录。它不能证明应用已经发出了所有本应存在的事件，也不能证明时间源准确、审批人做出了正确决定，或底层外部 API 确实完成了它声称完成的操作。这些是不同的控制问题。

应为明确的保留范围保留验证记录。许多团队使用下面这样的工作底稿格式就足够了：

```json
{
  "verification_id": "audit-2026-07-15-01",
  "period_start": "2026-07-01T00:00:00Z",
  "period_end": "2026-07-14T23:59:59Z",
  "command": "sp audit verify",
  "verifier_version": "record the installed version",
  "source_archive": "encrypted audit export identifier",
  "result": "pass or fail",
  "performed_by": "reviewer identity",
  "exceptions": []
}
```

验证失败后不要伪造通过结果。记录失败，保留材料，确定失败来自导出处理、保留机制、软件缺陷还是疑似篡改，并通过事件处理流程跟进。完整性检查失败不一定代表发生了安全泄露，但它是必须调查的事件，因为你的证据链已经不再可信。

按照代理活动的数量和风险制定验证周期，并在整理证据前再次验证。小型环境每月运行一次可能足够。让代理整天操作生产系统的团队，不应等到季度末才发现完整性问题。周期本身不如持续执行和处理失败重要。

## 运营操作和系统变更需要不同的证据

这是最容易混淆的边界。代理操作可能会改变某些东西，但这并不意味着它属于 CC8.1 所说的受控系统变更。

看三个例子。代理通过 API 修改客户订阅状态，这是业务操作，需要授权、可追踪性，可能还需要审核。代理编辑源代码仓库中的基础设施文件，拉取请求经过审核、测试通过，部署流水线应用了变更，这是系统变更。代理运行 SSH 命令直接修改生产配置文件，这是高风险运营操作；如果政策要求经过审核的部署，它还很可能违反变更流程。

证据包应让这些路径清晰可见，而不是让审核人员从文字说明中自行推断。可以在活动记录或证据分析中加入操作分类：

| 操作类别 | 主要证据 | 不可替代的内容 |
|---|---|---|
| 读取或诊断操作 | 会话授权和调用记录 | 访问范围及监控规则审核 |
| 业务数据操作 | 会话或每次调用审批、调用记录、结果 | 必要时的客户支持流程或财务审批 |
| 生产系统操作 | 每次调用审批、主机或端点记录、事件或维护引用 | 如果操作改变受管理配置，则还需要正式变更控制 |
| 产品或基础设施变更 | 拉取请求、审批、测试、部署记录，以及代理活动记录（如果使用） | 发布控制本身 |

CC8.1 要求管理层对基础设施、数据、软件和流程的变更进行授权、设计、开发或配置、记录、测试、批准和实施。代理日志可以补充说明代理打开了拉取请求或调用了与部署有关的操作，但不能替代审核、测试证据和部署记录。

这点不受欢迎，是因为人们觉得一份审计日志应该回答所有问题。它做不到。把代理活动轨迹作为委派操作的记录，把工程变更记录作为系统变更遵循规定路径的证据。只有在代理参与了这条路径时，才将两者关联起来。

## 从总体而不是截图文件夹构建证据包

为每个检查期间建立一份可重复生成的证据包。第一步是定义总体。对于代理活动，这通常意味着期间内的所有会话、所有受保护调用、所有调用拒绝、所有撤销，以及所有日志验证运行。如果无法提供数量或完整导出，就不能可信地声称审计人员是从完整总体中抽样的。

接下来准备一份简短的证据清单，指向不可变或保留的源材料。不要上传一堆名为 final-final-audit 的文件。使用稳定标识、来源位置、期间、负责人，以及说明该材料证明什么的备注。

审核人员可以按以下顺序操作：

1. 获取该期间的会话和活动总体，以及完整性验证记录。
2. 将活动条目引用的会话标识数量与会话总体核对，然后调查未匹配的记录。
3. 从已批准会话、被拒绝尝试、敏感调用、撤销和不同时间范围中抽取样本。
4. 将每个抽取的调用追溯到授权，再追踪到结果，然后检查覆盖其保留范围的日志验证记录。
5. 对网关或相关生产控制的变更，单独追踪相关的拉取请求、测试、审批和部署记录。

这个顺序会很快暴露缺口。如果调用没有会话，授权关联就失败了。如果会话没有进程身份，就无法测试关于进程的声明。如果撤销没有后续拒绝测试，你只能知道有人点过按钮。如果验证记录覆盖的归档无法重现，完整性声明就很薄弱。

将审核备注与样本放在一起。一条简短备注，例如“调用 ID 54b 与会话 ID 12a 匹配；会话由员工 A 批准；需要且存在每次调用审批；活动结果为完成；审计范围验证通过”，比十张截图更有用。它说明了下一位审核人员测试了什么，也能在控制变化时留下轨迹。

## 负责人无法解释异常时，证据就会失败

即使证据表做得很好，如果没有人负责异常路径，它仍然会失败。代理操作会被拒绝，审批请求会过期，远程端点会导致调用失败，会话会被撤销，验证也可能报告问题。这些结果应出现在总体中，团队还应知道哪些结果需要处理。

定义一组适度的异常类别：未经授权的尝试、审批拒绝、远程操作失败、撤销后的尝试、缺失的记录关联，以及验证失败。为每类异常指定负责人、审核周期和预期记录。不要把每个被拒绝的 API 请求都强行当作安全事件。来自意外签名进程的重复拒绝，可能比工程师拒绝自己的实验命令更值得关注。

真正有用的测试是：某个人能否在不从聊天消息中拼凑故事的情况下，解释一项抽取的异常。活动记录应说明直接原因，会话记录应标识此次运行，后续记录应说明团队是接受结果、修正配置、撤销访问，还是启动事件处理。

控制发生变化时同样需要纪律。如果你修改了审批行为、凭据标记、日志字段，或验证保留日志的流程，应把它视为控制环境的变化。更新控制说明，测试新行为，并通过现有工程流程记录部署。否则你的证据表描述的是上季度的系统，而本季度的代理使用的是另一套系统。

不要等审计人员告诉你证据是否能关联起来。本周选取一个真实会话，从授权追踪到调用结果，在安全环境中撤销它，再离线验证保留的审计范围。如果团队无法使用已经存在的记录完成这项练习，就应先修好证据路径，再讨论控制措辞。
