介绍
助手已经只能使用 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,清空声明,再次回放:有用的共享读取必须成功。

保持 tools.json 的只读策略。检查点测试两个账号、两条路由、所有者/共享/私有情况以及未见过的可丢弃文档。硬编码文档 ID、全部允许、信任提案用户或全部拒绝都无法满足这组要求。若有输入错误,重新写入完整小函数并重试读取即可恢复。
总结
你使用认证身份及存储的所有权或共享关系实施了文档访问控制。伪造的提案字段不能变成权限依据。服务端仍提供有用的所有者、共享读取,同时拒绝私有对象和不必要操作。这演示的是确定性工具授权,而不是实时模型的可靠性。



