将每个用户限制在自己的文档边界内

网络安全Beginner
立即练习

介绍

助手已经只能使用 documents.read,但允许的工具仍可能请求禁止访问的文档。你维护一个全新的教学实例,其对象策略目前允许所有读取。

分两阶段添加小型 Python 规则:先保护所有权,再保留显式共享。服务端从认证会话获取身份,而不是提案参数。文档均为合成数据,提案均明确标注为回放;读取和授权真实执行。只需要上一实验的终端技能,Python 语法会在这里讲解。

将读取绑定到认证所有者

本步骤阻止允许的工具越界读取其他用户的私有文档。

在实验界面选择 Test Client 标签页,开始本步骤。

使用以下访问表。owner 和 shared_with 是存储的文档字段,不是提案提供的值。

文档 所有者 共享对象 Alice 可读 Bob 可读
alice-notes alice 无 是 否
bob-notes bob 无 否 是
team-plan bob alice 是 是

在 Test Client 中,--as bob 选择 Bob 预置的认证凭据;省略则选择 Alice。先确认正常的所有者读取:

运行以下命令前,请切换到 Test Client 标签页。

assistant call documents.read alice-notes

预期为 HTTP 200 和 Alice 的内容。现在复现缺失对象检查的问题:

assistant call documents.read bob-notes

它错误地返回 HTTP 200 和 Synthetic Bob private budget。这里没有使用真实私密信息。仅靠工具允许列表未能保护对象。

切换到 Policy Editor 标签页,查看小型策略:

运行以下命令前,请切换到 Policy Editor 标签页。

cat /home/labex/project/policy.py

def can_read(principal, doc): 定义一个接收两个输入的函数。缩进的 return True 目前允许所有人。Python 字典保存具名字段:principal["id"] 读取认证身份,doc["owner"] 读取存储的所有者。== 比较值并返回真或假的布尔值。行首四个空格让 return 留在函数内部。

将函数替换为所有者比较。继续使用上一实验的字面 here-document 方法写入整个文件:

cat > /home/labex/project/policy.py <<'EOF'
def can_read(principal, doc):
    return doc["owner"] == principal["id"]
EOF

切换到 Test Client 标签页,重复对他人私有文档的请求:

运行以下命令前,请切换到 Test Client 标签页。

assistant call documents.read bob-notes

预期为 HTTP 403 和 document_denied。这与 tool_denied 不同:读取操作本身允许,但 Alice 无权访问该对象。测试反向情况:

assistant --as bob call documents.read alice-notes

也必须被拒绝。Bob 自己的文档必须仍可读取:

assistant --as bob call documents.read bob-notes

预期为 HTTP 200。若所有读取都以 policy_error 失败,切换到 Policy Editor 标签页,保留缩进和引号重新编辑;切回 Test Client 后再重试读取。服务端每次请求都会重新加载函数。这个中间所有者规则有意尚未恢复共享,下一步再完成。

恢复共享且不信任声明的用户

本步骤允许存储的共享关系,同时拒绝提案中伪造的身份。

在实验界面选择 Policy Editor 标签页,开始本步骤。

虽然 Bob 显式授予了访问权,所有者规则仍会阻止 Alice 读取共享的 team-plan。Python 的 in 检查是否属于列表,or 表示任一条件成立即可。将所有权与存储共享列表中的成员关系组合。在 Policy Editor:

运行以下命令前,请切换到 Policy Editor 标签页。

cat > /home/labex/project/policy.py <<'EOF'
def can_read(principal, doc):
    return doc["owner"] == principal["id"] or principal["id"] in doc["shared_with"]
EOF

切换到 Test Client 标签页,检查合法共享:

运行以下命令前,请切换到 Test Client 标签页。

assistant call documents.read team-plan

预期为 HTTP 200 和 Synthetic shared project plan。现在提交伪造身份。--claim bob 向不可信的工具参数添加 user_id: bob,并不会选择 Bob 的认证凭据:

assistant replay documents.read bob-notes --claim bob

预期为 HTTP 403、主体 alice 和 document_denied。服务端在调用策略前将真实凭据映射为 Alice,并忽略参数中的身份声明。也尝试直接处理器:

assistant call documents.read bob-notes --claim bob

它必须以相同方式拒绝。--as bob 和 --claim bob 的含义有意不同:前者使用预置的 Bob 凭据,后者仅是提案中的文本。

切换到 Assistant Tool Lab 标签页,使用 alice 和 training-alice 登录,选择 documents.read,输入 bob-notes,在 Untrusted user_id (optional) 填入 bob,点击 Replay proposal。确认服务端结果仍将用户识别为 alice,并拒绝私有文档。把文档改为 team-plan,清空声明,再次回放:有用的共享读取必须成功。

Assistant Tool Lab 拒绝使用伪造身份参数读取其他用户的私有文档

保持 tools.json 的只读策略。检查点测试两个账号、两条路由、所有者/共享/私有情况以及未见过的可丢弃文档。硬编码文档 ID、全部允许、信任提案用户或全部拒绝都无法满足这组要求。若有输入错误,重新写入完整小函数并重试读取即可恢复。

总结

你使用认证身份及存储的所有权或共享关系实施了文档访问控制。伪造的提案字段不能变成权限依据。服务端仍提供有用的所有者、共享读取,同时拒绝私有对象和不必要操作。这演示的是确定性工具授权,而不是实时模型的可靠性。