🔒 补齐 cp 文件传输审批:upload_file/download_file 与 opsctl cp 不再绕过 - #251
Merged
Conversation
Merged
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.
背景
upload_file/download_file与opsctl cp在整条路径上没有任何审批检查——模型对同一台 SSH 资产,走exec需要审批,走upload_file不需要。而写文件足以等价于执行命令(~/.ssh/authorized_keys、/etc/cron.d/*、任何被 systemd/CI 引用的脚本路径)。cp其实早就是一等审批类型,只是从来没有调用点发起过:internal/approval/approval.go与internal/ai/permission/approval.go的 Type 枚举里都写着"cp"grant_entity.Grant.ToolName注释是"exec", "cp", "create", "update",opsctl grant的 CLI 帮助也允许用户建 type=cp 的授权——建了没人查requireApproval的离线分支专门处理cpopsctl help一直在写 "Write operations (exec, cp, create, update) require desktop app approval"cp.go里是一句// cp 不需要审批所以这个 PR 不是新增机制,是把那条没写完的分支补齐。
改动
policy.MatchPathRule— 路径 glob(*不跨/)的唯一实现,local_write/local_edit的门禁改调它,与 cp 共用同一套语义。SaveGrantPattern开始写入真实tool_name;匹配时 cp 与非 cp 互不可见。这是前置条件:否则用户在 cp 审批里把 pattern 编辑成*(很常见),这条路径授权会被命令匹配器看见,放行该资产上的任意命令。只在 cp/非 cp 之间划线而不按类型严格相等,是因为存量行的tool_name一律被旧版写死成"exec"(含 redis/sql),严格相等会让存量会话授权集体失效。cp权限类型 — 只查 grant,不查 CommandPolicy 的 allow/deny 规则(那些是命令形状的,拿路径去撞只会误判);审批项支持detail。ExecuteWithSFTP之前过审批,主体是远端路径,本地路径与方向进 detail。opsctl cp— 审批放在 proxy 与直连分支的共同上游(否则 proxy 路径会漏),资产间传输审两次(源端读 + 目的端写),审计从传nil改成传真实决策。cp图标 + detail 展开不再限定本地工具。验证
go test ./...全绿;改动包golangci-lint0 issue;前端 lint 0 erroropsctl cp,返回desktop app is not running,audit_logs留下tool_name=cp的拒绝记录,没有发生任何 SFTP 连接handleUploadFile报的是获取SSH配置失败: SSH配置为空——已经在拨 SSH,审批回调一次没调opsctl cp的用例补了"批准后照常传输"防止called=false是假绿遗留
存量 grant 行的
tool_name仍是"exec"。要收紧成按类型严格相等,需要配一次 backfill 迁移,而 group 级授权(可跨资产类型)本身没有唯一正确值——建议另开 issue。closes #248