[2/3] feat(memory): 角色感知授权与 Agent 代操作 - #59
Open
openjiuwen-sync-bot[bot] wants to merge 42 commits into
Open
Conversation
身份此前由请求体的 actor_* 字段提供(handler._actor_scope 的 docstring 自称 "Claimed"),调用方填什么就是什么,13 个动词全部可冒充任意主体。授权层本身是 对的——诚实身份读别人的 scope 正确返回 403——洞在于认证层根本不存在。 新增 src/security/: - Authenticator 三实现(DEV / TRUSTED / API_KEY),模式在装配期选定而非每请求 分流;错误消息一律笼统,避免主体枚举侧信道 - PrincipalKeyStore(Argon2id,OWASP 2024+ 参数),三条 resolve 路径各恰好一次 verify 以消除 timing 侧信道;缺 argon2-cffi 时装配期抛错,不回退明文 - RateLimiter 令牌桶,挂在认证之前——Argon2 的 128MiB×4 单次成本在无限制调用下 是放大器;桶按 peer 分并 LRU 有界,否则这个防耗尽的组件自己成为耗尽入口 - check_dev_binding 纯函数,DEV 模式绑非 loopback 时由进程入口 exit(1) common/type_def/auth.py 提供 AuthContext(frozen,actor 与 role 均无默认值—— 漏传会得到空 Scope() 即 platform-admin 全局权限)与 ContextVar 传播。 handler 改从认证上下文取身份,payload 里的 actor_* 一律 400 而非静默忽略: 静默忽略会让运维以为"我加了 actor_scope 限制"仍然生效。audit verb 的 actor_agent/actor_session 是查询谓词,语义不同,对该 verb 放行。 storage/fs_impl/encrypted_fs_store.py 补齐静态加密的 FS 侧(KV 侧上游已有): 与 EncryptedKVStore 逐条同构,不自带任何密码学,AAD 绑满五维 scope + ref。 明文兼容开关只在 provider 的 allow_plaintext 上,装饰器不重复提供。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
test_identity_forgery_rejected.py 按 CLAUDE.md §5 先写后修:在改动前的 HEAD 上
跑一遍看它全红(证明漏洞真实存在),再做改动看它全绿。其中
test_identity_comes_from_context_not_payload 比"伪造被拒"更重要——前者证明堵上
之后认证与授权确实串起来了,后者只证明洞堵上了。
关键断言:
- 限流跑在认证之前(认证器一次都没被调到),429 与 401 可分
- 审计 detail 恰好只有 mode 与 peer 两个键,用 set(detail) == {...} 精确断言:
桶余量能用来反推限流参数,然后贴着阈值发请求
- resolve 的 timing pad 取 5 次中位数,比值须在 [0.5, 2.0]。这条实测抓到过真实
缺陷:初版"前缀有候选但 key 错"跑两次 verify、"前缀无候选"跑一次,ratio=0.49;
修的是实现(加 verified_any 标志)不是断言
- AuthContext 的 ContextVar 线程隔离与 reset 保证
- FS 加密:AAD 绑满五维 scope + ref;换 scope 搬密文解不开;明文兼容开着时写
路径仍然加密
两个既有测试随实现改写:身份改由上下文提供后,每条用例都必须显式声明"谁在发这个
请求"——这正是要的效果,签名上就不给"不指定身份也能调"留位置。原先断言
actor_space 能覆盖 identity 的那条用例被删除,它断言的正是要堵的洞。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
新增 docs/features/security/F01-authentication-kernel.md:认证内核的 11 条决策、 8 条拒绝方案与 13 条已知遗留。速率限制写在同一份而不单开——它唯一的存在目的是 保护认证,且这个可用性风险是引入 Argon2 时一并带进来的,不是一件独立的事。把 "留了个洞"和"补上了"记在一起,比拆成两份让读者去两处对照要诚实。 F04(安全基线)就地加 9 条实现注记,标出主干与文档的偏离。这些不是文档笔误, 是照抄会出问题的地方:ROOT actor 用 Scope(org="*") 会先撞上"跨 org 一律拒绝" 反而寸步难行;compare_digest 传 str 在非 ASCII 输入下抛 TypeError,把 401 变成 500;异步 KeyProvider 在已有事件循环的进程里必炸;信封头实际 11 字节且没有 key_id——后者意味着轮换根密钥会让全部历史密文永久不可解,是个真实缺口。 storage/F02 从"加密 KV"扩为"加密存储",补入 FS 侧的 8 条决策与 13 条断言。两个 装饰器同构,合在一份里读者才看得出"明文兼容开关只在 provider 上"是一条贯穿两侧 的约束,而不是各自的实现选择。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
解决四个预期冲突: - test_dispatch_management_compat.py: 合并身份上下文与新版list API - F02-encrypted-storage.md: 合并KV和FS加密特性文档 - S07-common.md: 合并公共层接口与安全特性 - src/storage/AGENTS.md: 合并KV/FS加密装饰器规约 自动合并的关键文件已复核: - handler.py: list返回MemoryListResult.count,身份从上下文来 - LocalMemoryAPI.list: 授权目标与filters一致,审计count/page_count - KVSpaceManager: 原始枚举改用scan() Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
应用代码格式化到合并后的文件。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
修复审查报告指出的格式化问题。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
5 tasks
- G.LOG.02: __main__.py 和 mcp_server 使用 logging.error 替代 print - G.FMT.08: Protocol 方法定义使用多行格式 - G.FMT.07: test_http_slow_upload.py import 顺序调整(importlib 放到标准库区) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
| @@ -0,0 +1,51 @@ | |||
| """Authenticator — 认证契约(security.md §2.1 / §2.2)。 | |||
There was a problem hiding this comment.
head_sha: ac70f3210aec41aac20b7efad789c822c0c827d2
安全相关的都放在src/common/security/security_impl吧
F01、F02 已迁移到 common/F07、F08 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 迁移 security/F01 → common/F07(认证内核) - 迁移 security/F02 → common/F08(授权上下文) - 更新 S09-security.md 标题和关联特性文档路径 - 将 F04/F07/F08 中的 S08 引用统一改为 S09 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 添加术语说明部分,定义「认证与加密期」和「授权与上下文期」 - 更新元信息:添加关联特性文档和规范契约引用 - 更新当前落地状态,详细列出 security 子模块结构 - 更新文档末尾的特性文档引用路径 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Paired: GitHub #59 ↔ GitCode !166
/kind feature
变更概述
这是安全模块三阶段交付的第 2 个 PR,建立在 PR① 的认证上下文之上。
主要增加:
AuthContext。Scope形状推断。acting_user委托语义,支持 Agent 代表同组织、同空间用户执行受限操作。安全属性
auth.actor与请求 actor 不一致时 fail closed。acting_user不能跨组织或跨空间扩权。验证
ruff check通过。ruff format --check通过。git diff --check及冲突标记扫描通过。Self-checklist
合并信息
Merge-Order: 2/3
Depends-On: #165(#58)
Do-Not-Merge-Before: #165
Merge-Method: merge commit(禁止 Squash)
本 PR 保持 Draft/WIP。PR① 合入后需刷新 diff,确认只剩角色感知授权与 Agent 代操作增量,再取消 Draft。