Skip to content

[authz] examples contract 测试在 contract 层未触发 owner-scoped 授权门(403 覆盖) #2496

Description

@ghbvf

现状

examples(devicecell/ordercell)的 slice 级 contract 测试把生成 handler 直接挂载执行
(mux.Handle(method+path, h) 或 h.ServeHTTP(rec, req)),而生成 handler 的 ServeHTTP
直接调 handle、绕过 auth.Mount 注入的 route gate(gate 仅在 RegisterRoutes 经
auth.Mount 生效)。因此 owner-scoped 端点(order:read/order:update/device:read/
device:consume,resource: id)的 403 / owner-deny 授权边界在 contract 测试层不被触发。

证据(#2486 迁移后,以 orderquery 为例):

// examples/todoorder/cells/ordercell/slices/orderquery/contract_test.go:51-57
h := getv1.NewHandler(svc, testResolver())
mux := http.NewServeMux()
mux.Handle(c.HTTP.Method+" "+c.HTTP.Path, h) // h.ServeHTTP→handle,不经 auth.Mount gate
...
mux.ServeHTTP(rec, req)                        // 无 auth context 也得 200
c.ValidateHTTPResponseRecorder(t, rec)

三维根因:

影响范围:

  • 直接:examples 作为外部 Cell 作者范本,未在 contract 测试层示范 owner-scoped 授权测试,
    孤立看 contract 测试会误以为这些端点无鉴权要求。
  • 间接:无功能/安全缺口——授权等价性已由 [authz] examples(devicecell/ordercell)HTTP 授权 contract-derived 迁移(#2355 续波 PR-A) #2486 验证、403 由集成测试覆盖。
  • 同类:orderquery / ordercreate / orderconfirm / orderprojection / devicestatus / devicelist /
    devicecommand 的 contract 测试均同款绕过(Grep ServeHTTP + testResolver ≈ 7 slice)。

修复方向

三级方案种子:

  • 最小:在各 examples contract 测试补一行注释说明「直挂 handler、gate 见 listener_auth_test」
    (部分已在 [authz] examples(devicecell/ordercell)HTTP 授权 contract-derived 迁移(#2355 续波 PR-A) #2486 内置 review 补,剩余 slice 补齐)。
  • 彻底:把 examples contract 测试改为经 RegisterRoutes(auth.Mount) 挂载 + 注入 test
    Authorizer,新增「owner self → 200 / 非 owner → 403」用例,使 examples 在 contract 层
    示范 owner-scoped 授权测试(照搬 corecells/accesscore 的 contract 测试范式)。
  • 重构:抽 examples/*/.../*test 共享的 contract-gate 测试 harness(mount via auth.Mount +
    允许/拒绝 Authorizer 注入),统一两个 example cell 的授权测试样板。

附带小项(同批可做,范本打磨):

  • examples/iotdevice/cells/devicecell/slices/devicestatus/handler_test.go:34
    testStatusAuthorizer 用字面量 "role:operator",应改 dto.RoleOperator 常量与 authorizer.go 统一。
  • examples/iotdevice/contracts/http/device/command/{enqueue,enqueue-async}/v1/contract.yaml
    可加注释说明 path {id} 是 target device、非 caller,故 coarse device:command(admin/operator-only)
    不声明 resource(设计正确,仅澄清意图)。

Files

  • examples/todoorder/cells/ordercell/slices/orderquery/contract_test.go:47
  • examples/todoorder/cells/ordercell/slices/ordercreate/contract_test.go:40
  • examples/todoorder/cells/ordercell/slices/orderconfirm/contract_test.go:39
  • examples/todoorder/cells/ordercell/slices/orderprojection/contract_test.go:34
  • examples/iotdevice/cells/devicecell/slices/devicestatus/contract_test.go:49
  • examples/iotdevice/cells/devicecell/slices/devicelist/contract_test.go:65
  • examples/iotdevice/cells/devicecell/slices/devicecommand/contract_test.go:52

Source

PR #2493 finding F4(测试 / 安全 / DX 三维度同源);Discovered via /ship #2486

Activity

  1. added
    area-auth认证 Authn + 授权 Authz
    backlogBacklog item — automation trigger 入 project
    cx-2Cx2 改动量:同包 ≤5 文件
    on Jun 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-auth认证 Authn + 授权 AuthzbacklogBacklog item — automation trigger 入 projectcx-2Cx2 改动量:同包 ≤5 文件pri-p2Priority P2type-test测试补充

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions