Repository navigation
fix(auth): 全新部署零账号时放行首位注册,修复引导管理员死锁 (#1866) - #4460
Open
OldSlowDog wants to merge 1 commit into
Open
OldSlowDog wants to merge 1 commit into
OldSlowDog wants to merge 1 commit into
Conversation
问题:初部署设置了 DISABLE_REGISTRATION=true(或 invite_only/invite_register 模式)时,/auth/register 一律 403;而 WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL 按设计只提升已存在的用户、绝不创建账号,用户无从注册 → 无人可登录 → 无法配置首位系统管理员,部署直接卡死。 修复(保持 bootstrap「不创建用户」的原设计): - Register 门新增零用户例外:mode 非 self_serve 且部署内用户数为 0 时 放行首位公开注册;nil userService 或查询出错一律 fail closed(403)。 - GET /auth/config 新增 first_registration_open 标志(与 Register 门 lock-step),mode 本身保持运维配置值不变,前端据此显示注册入口。 - 前端 registrationPolicy.canRegister 增加第三参;AuthConfigResponse 补 该字段;Login.vue 接线。 首位账号落库后例外立即关闭,行为回到原模式矩阵;邀请注册 (register-by-invite)不受影响,仍有用户时继续 403。 测试: - 新增 TestRegister_FreshDeploymentAllowsFirstRegistration / TestRegister_InviteOnlyStillRejectsWithExistingUsers / TestRegister_UserCountErrorFailsClosed / TestGetAuthConfigExposesFirstRegistrationOpen 四个用例; - go test ./internal/handler/ -run 'TestRegister|TestGetAuthConfig|TestRegistrationMode' 通过; - 前端 registrationPolicy.test.ts 9 例通过; - Lite 单二进制实测(DISABLE_REGISTRATION=true + BOOTSTRAP 邮箱): 零用户 register 201 → flag 转 false → 第二用户 403 → 重启后 bootstrap 正常提拔首位用户为系统管理员(bootstrap 日志实锤)。
This branch has not been deployed
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.
closes #1866
问题
初部署设置
DISABLE_REGISTRATION=true(启动时合成registration_mode=invite_only)后:POST /auth/register一律 403(Public registration is disabled),登录页也不显示注册页签;WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL按设计只提升已存在的用户、绝不创建账号(bootstrap.go设计注释与configuration.md:241均有明文:"不会创建用户",该邮箱需先自行注册);结果:没有任何账号能注册 → 无人能登录 → 首位系统管理员永远配不了,部署直接卡死。这正是 #1866 描述的场景。
方案选择
没有改 bootstrap 的"不创建用户"语义(那不是维护者本意,也有安全隐患:凭 env 静默造号)。改为零用户例外:全新部署一个账号都没有时,放行首位用户走正常公开注册流程,注册完再按既有 bootstrap 流程提拔为首位系统管理员。流程与
firstboot.sh注释("注册后如需关闭后续注册再设 flag")一致。与 #4183 的关系
提交后注意到 #4183 已针对同一 issue 开路(撰写本 PR 时未检索到,抱歉),思路同源:都不新增 endpoint(规避 #2918 里中间件 401 的教训)、都在 Register 门放行零账号首注册。两点差异供维护者取舍:
WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL(大小写不敏感),且首位账号直接以系统管理员身份入库;本 PR 不依赖该 env 是否配置——部署内 0 账号即放行首注册,身份走正常用户创建,再交给既有 bootstrap 启动钩子按原语义提拔,不引入"凭一次公开注册直接赋予超管"的新语义。/auth/config的first_registration_open标志与前端注册入口联动;fix: allow bootstrap admin signup when registration is closed #4183 未涉及前端——invite_only下注册页签仍隐藏,只能靠调用方知道 API 其实可注册。若维护者更倾向 #4183 的方案或希望取舍合并,本 PR 的差异(零 env 依赖、register/promote 语义分离、前后端 lock-step、fail-closed 单测)可以互补,也乐意把改进合到任一边。
改动
后端(
internal/handler/auth.go)self_serve且ListAllUsers(ctx,0,1)返回 0 条时放行首届注册;userService为 nil 或查询出错一律 fail closed(403),不做乐观放行。GET /auth/config新增first_registration_open标志,与 Register 门 lock-step:mode 保持运维配置值(管理界面仍显示真实配置),前端另读该标志决定是否显示注册页签。前端
registrationPolicy.canRegister(mode, hasInvite, firstRegistrationOpen)增加第三参,仅零用户时放行;self_serve行为不变。AuthConfigResponse补first_registration_open字段;Login.vue接线。文档(website-docs)
03-features/01-tenant-auth.md:模式矩阵下新增"全新部署例外"小节;04-api/02-api-auth.md:/auth/config响应示例与字段说明;01-getting-started/04-configuration.md/03-quickstart.md:DISABLE_REGISTRATION、WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL行补充该行为。首位账号落库后例外立即关闭,行为回到原模式矩阵:已有用户时
invite_only继续 403;register-by-invite全程不受影响(仍按模式门控);OIDC、管理员建号通路不变。Validation
单测:
TestRegister_FreshDeploymentAllowsFirstRegistration(零用户→201)、TestRegister_InviteOnlyStillRejectsWithExistingUsers(有用户→403)、TestRegister_UserCountErrorFailsClosed(查数失败→403)、TestGetAuthConfigExposesFirstRegistrationOpen(flag 双态且 mode 不变);go test ./internal/handler/ -run 'TestRegister|TestGetAuthConfig|TestRegistrationMode'通过。registrationPolicy.test.ts补 2 例(零用户放行 / self_serve 不受影响),9/9 通过。Lite 单二进制实测(
DISABLE_REGISTRATION=true+WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL=admin@repro.local,干净数据目录):GET /auth/config(零用户)first_registration_open:true,registration_mode:invite_onlyPOST /auth/register(首位)GET /auth/configfirst_registration_open:falsePOST /auth/registerPublic registration is disabledPOST /auth/register-by-invite(全程)promoted user ... to system admin via WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL,登录 200 且is_system_admin:true升级兼容:只新增接口字段与一个受用户数约束的例外,不改任何既有配置语义;已有部署(哪怕真的 0 账号且开着
invite_only)也只是多了一次首注册机会,风险面等于一次正常注册。