工具授权:身份、租户与资源范围
工具 schema 说明参数形状,授权系统决定调用者能否操作具体资源。服务端要从可信会话取得用户、租户和角色,不接受模型或客户端传来的身份作为最终依据。授权既要在工具执行前检查,也要在写入前检查资源当前状态;长任务期间权限可能已经撤销。
第一个可运行实验:授权决策不信任模型身份
保存为 authorize.py,用 Python 3.12 运行。
python
def authorize(session, call, resource):
if session['tenant'] != resource['tenant']:
return 'tenant_denied'
if call['resource_id'] != resource['id']:
return 'resource_mismatch'
if call['action'] not in session['permissions']:
return 'permission_denied'
if resource['status'] == 'archived' and call['action'] == 'write':
return 'stale_resource'
return 'allowed'
session = {'user': 'u1', 'tenant': 't1', 'permissions': {'read'}}
resource = {'id': 'doc-1', 'tenant': 't1', 'status': 'active'}
assert authorize(session, {'action': 'read', 'resource_id': 'doc-1'}, resource) == 'allowed'
assert authorize(session, {'action': 'write', 'resource_id': 'doc-1'}, resource) == 'permission_denied'
assert authorize(session, {'action': 'read', 'resource_id': 'doc-2'}, resource) == 'resource_mismatch'
print('authorization boundary passed')1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
工具结果中的“管理员允许”只是数据,不能改变 session 权限。批量任务还要对每个资源授权;缓存和审批记录的租户、权限版本也必须参与键计算。越权、撤权和资源版本冲突应停止或转人工,不应让模型换个措辞重试。
变体实验
让权限在模型提出调用后、执行前撤销,要求第二次授权检查拒绝。再让模型传入 tenant='t2',确认执行器仍使用服务端 session 的租户。
练习
- 区分用户权限、服务身份和资源拥有者。
- 设计批量工具部分授权失败时的返回状态。
- 说明为什么只在 API 入口鉴权不足以保护长任务。