@iasiv5/dsh-obmc-web 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/lib/index.js +36 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -121,8 +121,18 @@ bootstrap),地址仍会写入配置并提示下一步去点「安装并启
|
|
|
121
121
|
- 上游仅 `127.0.0.1`(SSH 隧道,端口默认 18443),不新增任何公网监听。
|
|
122
122
|
- 剥掉的响应头:`X-Frame-Options`、`Strict-Transport-Security`、
|
|
123
123
|
`WWW-Authenticate`(防止 bmcweb 的 401 Basic challenge 弹浏览器原生
|
|
124
|
-
凭据框;BMC SPA 走 POST /login JSON + cookie
|
|
124
|
+
凭据框;BMC SPA 走 POST /login JSON + cookie)、`Clear-Site-Data`
|
|
125
|
+
(bmcweb 登出会发 `Clear-Site-Data: "cache","cookies","storage"`,语义
|
|
126
|
+
是清空整个源的 Cookie 与存储——在同源代理下会连带清掉 GUI 自身的会话
|
|
127
|
+
Cookie,把 DSH 一起登出;BMC 侧登出不受影响:显式的 `SESSION=` 过期
|
|
128
|
+
Set-Cookie 照常透传,服务端会话照常销毁),CSP 仅移除
|
|
125
129
|
`frame-ancestors` 指令;其余(含 Cookie)原样透传。
|
|
130
|
+
- 非 `/login` 的上游 401 统一降级为 403:BMC SPA 的 axios 拦截器对其他
|
|
131
|
+
401 会执行 `window.location = "/login"`——根绝对路径的顶层导航,在
|
|
132
|
+
同源代理下会逃出 `/bmc` 前缀,落到 GUI 自己的 `/login` 并被认证门
|
|
133
|
+
重定向进 DSH 应用,把用户从 BMC 控制台拽走(首次打开最常见)。403
|
|
134
|
+
走 SPA 的原地「未授权」提示,不发生导航;`/login` 的真实 401 保留
|
|
135
|
+
(登录表单错误处理与 CSRF 探测依赖它)。
|
|
126
136
|
- 不在任何地方存储 BMC 凭据;登录在 BMC 自身页面完成。
|
|
127
137
|
- 信任围栏仿照 dsh-better-sidebar 的 trust-fence(Host 必须是 loopback
|
|
128
138
|
或部署信任的 authority、`Sec-Fetch-Site` 不得为 cross-site、Origin 若有
|
package/lib/index.js
CHANGED
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
* after its own exact table, so the GUI's own longer routes always win and
|
|
11
11
|
* a duplicate registration is skipped (never throws the plugin).
|
|
12
12
|
*
|
|
13
|
-
* Embed-hostile response headers are removed
|
|
14
|
-
* CSP frame-ancestors
|
|
15
|
-
* challenges can never pop the browser's native credential
|
|
16
|
-
* SPA logs in via POST /login JSON + cookie
|
|
17
|
-
*
|
|
13
|
+
* Embed-hostile and origin-hostile response headers are removed
|
|
14
|
+
* (X-Frame-Options, HSTS, CSP frame-ancestors, WWW-Authenticate so bmcweb's
|
|
15
|
+
* 401 Basic challenges can never pop the browser's native credential
|
|
16
|
+
* dialog — the BMC SPA logs in via POST /login JSON + cookie — and
|
|
17
|
+
* Clear-Site-Data, whose origin-wide wipe on BMC logout would otherwise
|
|
18
|
+
* destroy the GUI's session cookie). Non-/login 401s are degraded
|
|
19
|
+
* to 403: the BMC SPA redirects the whole tab to root-absolute /login on
|
|
20
|
+
* any other 401, which on this origin lands in the GUI's auth gate and
|
|
21
|
+
* bounces the browser into the DSH app. Everything else passes through
|
|
22
|
+
* untouched; no credentials are stored anywhere.
|
|
18
23
|
*
|
|
19
24
|
* BMC address discovery: the BMC's address is often DHCP-assigned by the
|
|
20
25
|
* jump host that links it (a small LAN of its own) and may change. When
|
|
@@ -86,7 +91,18 @@ const HOP = new Set([
|
|
|
86
91
|
// www-authenticate is dropped so bmcweb's 401 Basic challenges (e.g. on
|
|
87
92
|
// /login and unknown paths) can never pop the browser's native credential
|
|
88
93
|
// dialog — the BMC SPA logs in via POST /login JSON + cookie, not Basic.
|
|
89
|
-
|
|
94
|
+
// clear-site-data is dropped because bmcweb's logout answers
|
|
95
|
+
// Clear-Site-Data: "cache","cookies","storage" — an instruction to wipe
|
|
96
|
+
// EVERY cookie/cache/storage entry for the ORIGIN. Through this same-origin
|
|
97
|
+
// proxy that origin is the GUI's: one BMC logoff would otherwise destroy
|
|
98
|
+
// the DSH session cookie (and DSH's localStorage) too. BMC-side logout
|
|
99
|
+
// still works without it: bmcweb expires its SESSION cookie via an
|
|
100
|
+
// explicit Set-Cookie (passes through) and destroys the session
|
|
101
|
+
// server-side; only the origin-wide nuke is suppressed.
|
|
102
|
+
const DROP_RESPONSE = new Set([
|
|
103
|
+
...HOP, 'x-frame-options', 'strict-transport-security', 'www-authenticate',
|
|
104
|
+
'clear-site-data',
|
|
105
|
+
])
|
|
90
106
|
|
|
91
107
|
const agent = new https.Agent({ keepAlive: true, maxSockets: 8, rejectUnauthorized: false })
|
|
92
108
|
|
|
@@ -514,7 +530,20 @@ function proxyRequest(req, res, targetPath, log) {
|
|
|
514
530
|
}
|
|
515
531
|
raw.push(key, value)
|
|
516
532
|
}
|
|
517
|
-
|
|
533
|
+
// The BMC SPA's axios interceptor treats ANY 401 outside /login as
|
|
534
|
+
// "session lost" and answers with `window.location = "/login"` — a
|
|
535
|
+
// ROOT-ABSOLUTE navigation that escapes the /bmc prefix. On this
|
|
536
|
+
// origin /login belongs to the GUI's auth gate, which 307s such
|
|
537
|
+
// navigations into the DSH app, yanking the browser out of the BMC
|
|
538
|
+
// console entirely (seen on the first console open after a DSH
|
|
539
|
+
// restart: the SPA boots with stale localStorage login hints, probes
|
|
540
|
+
// /redfish/... while logged out, and the 401 bounce follows). Degrade
|
|
541
|
+
// every non-/login 401 to 403: the SPA's 403 path (setUnauthorized)
|
|
542
|
+
// is an in-place toast, never a navigation. /login keeps its true
|
|
543
|
+
// status so the login form's error handling and the CSRF probe keep
|
|
544
|
+
// working.
|
|
545
|
+
const status = up.statusCode === 401 && !/^\/login(\?|$)/.test(targetPath) ? 403 : up.statusCode
|
|
546
|
+
res.writeHead(status, raw)
|
|
518
547
|
up.pipe(res)
|
|
519
548
|
},
|
|
520
549
|
)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iasiv5/dsh-obmc-web",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "BMC Web UI
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "OpenBMC 控制台入口:设置一级菜单「BMC 控制台」面板一键在顶层标签页打开 BMC Web UI,同源代理经 SSH 本地转发 relay(obmc-web-relay)抵达 BMC,BMC IP 变化自动探测并重定向隧道;需 SSH 跳板机可达 BMC。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"exports": {
|