You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
我们在自建部署里遇到一个卡点:反向代理已经用统一登录认证了用户,但 dsh 只认 owner,所有下游共享同一份权限。查下来不是配置缺失,是 host 端少了一个入口。
现状
packages/client/connection/src/rpc-host.ts里与 Principal 相关的只有三处:publishPeer()(:169)把 principal 写死成{ kind: 'owner' },它同时是唯一把 peer 登记进this.peers的位置;createPeer()(:140)能构造任意 principal 的 peer,但只return new Peer(...),不登记,所以admit()看不到它;admit()(:129)只有两条路:浏览器会话命中isAuthenticated时返回共享的browserPeer(owner),否则用 API token 查this.peers,而表里只有 owner。全仓没有读取请求头来决定 principal 的代码。判定层本身是完整的:
dsh-api-remote-access的 role/binding/condition、逐项allows()过滤、每个 peer 的访问快照都在,测试里也覆盖了非 owner kind(packages/api/gateway/tests/gateway-access.host.spec.ts:212注册test-guest),只是生产侧没有创建非 owner principal 的路径。结果是外部身份进不来。部署只能一人一个进程做隔离(每实例常驻约 300 到 400 MB),或者用猴子补丁。
现在的临时绕法,以及它的缺陷
我们写了一个 Cordis 插件包裹
ctx.connection.admit:校验共享密钥头后createPeer({ principal: { kind: 'user', id } })并直接返回。在 0.2.1-rc.5 上实测有效——同一端点,不带身份头拿到 owner 的正常结果,带身份头拿到remote-access/denied,reason 是插件自定义的,说明 principal 已经不是 owner。但这个绕法有三个缺陷:
this.peers,admitConnection的 socket 归属与dispose退化成空操作;第三条对依赖它的部署是安全问题,不只是代码整洁问题。
建议的入口
给 connection 加一个配置项,
admit()在 owner 判定之后、401 之前依次询问:命中时
publishPeer(principal)并登记进this.peers,让 socket 归属、dispose、访问快照与 owner peer 完全一致。前置条件三件事:共享密钥必填(明文头可被客户端伪造)、比较走常量时间、来源限定在
trustedHosts或回环。判权仍由registerPolicy的产品方决定,未注册即拒绝,保持 fail-closed。参考实现
改三个文件,约 40 行:
principal-source.ts:配置 schema、请求头读取(同时认 fetchHeaders与IncomingMessage)、常量时间比较、装载期校验(重复头、身份头与密钥头同名、空密钥);ConnectionConfig增加principalSources,apply()校验后传入服务;rpc-host.ts:publishPeer()接受 principal 参数,新增publishExternalPeer()负责登记,admit()在浏览器判定之前询问来源。不配置这个字段时,
admit()的路径与现在完全一致,没有行为变化。验证方式
三条判据,都能在单进程里跑:
{ kind: 'user', id };未注册策略时应得到remote-access/denied,注册并放行后应正常返回。不在这个提议范围内
会话归属。dsh 目前不记录「这个会话属于谁」,所以即使身份进来了,多用户隔离仍要产品侧维护
sessionId -> principal,并在bindings()里按归属返回 binding。我们打算自己建这张表,不认为它需要进内核。All reactions