跳到主要内容

角色与权限

SupKube 用 admin、editor、viewer 三个角色配合命名空间范围,把备份与恢复权限下放到应用团队。

前置条件​

  • 已配置好认证,且身份提供方会下发用户组声明,参见 认证配置。
  • 修改绑定需要重新执行 helm upgrade,绑定关系不能在界面里编辑。

三个角色能做什么​

能力admineditorviewer
浏览全集群资源是是是
创建与删除备份全集群仅授权命名空间否
创建与删除恢复全集群仅授权命名空间否
创建与编辑策略全集群仅授权命名空间否
运行冲突预检与一键修复是是否
管理存储位置与快照位置是否否
管理变换规则与变换集是否否
创建与删除命名空间是否否
查看审计日志是否否

默认状态​

auth.rbac.enabled 默认为 false,此时所有通过认证的用户都是 admin。

危险

生产部署必须显式开启 auth.rbac.enabled=true。保持默认值意味着任何能登录的人都能删除任意还原点。

启用并配置绑定​

下面是一份贴近真实生产用法的配置:

auth:
rbac:
enabled: true
# 不能写 "",原因见下节「兜底角色」
defaultRole: "none"
bindings:
# 按身份提供方的用户组绑定
- { group: platform-admins, role: admin }
- { group: sre, role: admin }
- { group: developers, role: viewer }
# 按邮箱直绑几位管理员,作为用户组声明未送达时的兜底
- { user: alice@example.com, role: admin }
- { user: bob@example.com, role: admin }
# 按命名空间限定的写权限
- { group: app-team-my-app, role: editor, namespaces: [my-app, my-app-staging] }

每条绑定二选一:用 group 匹配用户组声明,或用 user 匹配邮箱与用户名。

namespaces 只对 role: editor 生效。admin 天然是全集群范围,viewer 全集群只读。

注意

role: editor 且没有写 namespaces 等于没有任何写权限。界面的「我的权限」页会明确提示该用户联系管理员补充命名空间。

务必事先准备两条自救通道​

上面那两条 user: 绑定不是冗余,而是防止把自己锁在门外的必要措施。

组绑定依赖身份提供方把用户组声明传到 SupKube。这条链路很容易断:

Keycloak(用户组在这里)
│ 需要 client 配置 groups 映射器
▼
Dex(中转)
│ 需要 connector 打开组透传与用户信息读取
▼
SupKube(按 groups 匹配 bindings)

链路中任何一环没配好,用户组声明就是空的——此时所有 group: 绑定全部落空,所有人回落到兜底角色。如果兜底角色按上节建议设成了 none,结果就是包括管理员在内没有人能登录做事。

三条认证通道,只有一条不受 RBAC 约束​

通道是否查 RBAC 绑定表组声明断链且 defaultRole: none 时
OIDC(Keycloak → Dex)是进不去,除非有 user: 邮箱直绑
HTTP Basic(htpasswd)是同样进不去
静态 API 令牌否可用,完全不依赖 Dex 与 Keycloak
htpasswd 不是逃生门

想配应急入口时,很自然会想到"再开一个 HTTP Basic 账号兜底"。这条路不通。

Basic Auth 用户会按用户名去查同一张 RBAC 绑定表——这是刻意设计(管理员可以直接调整权限而不必改 htpasswd 文件),但也意味着它和 OIDC 一起被同一个 defaultRole: none 挡在门外。

要让某个 htpasswd 账号真能当后路,必须同时在 bindings 里为它加一条 user: 绑定(user 同时匹配邮箱和用户名)。

两条通道各自的作用​

邮箱直绑 → 界面自救。 不经过用户组这条链路,组声明断了照样能登录界面。

预置一条 admin 静态令牌 → API 自救。 静态令牌的角色直接写在令牌条目上,不查绑定表,因此与组声明、兜底角色都无关。代价是它只能走 API(Authorization: Bearer <令牌>),用不了界面。

auth:
staticTokens:
enabled: true
tokens:
- name: break-glass
role: admin
hash: "<明文的 sha256 十六进制>"

明文在您自己的机器上生成,集群只保存哈希:

PLAIN=$(openssl rand -hex 32) && echo "明文: $PLAIN"
echo -n "$PLAIN" | shasum -a 256 # 取这个哈希填进 values

明文交给应急负责人单独保管,不要提交到版本库。

两条都必须事先配好

锁死之后再想加令牌或加绑定,同样要改 values 重新 helm upgrade——那就失去应急的意义了。

配完必须渲染验证,不能只看键名

键名写错时 Helm 不会报错:多余的顶层键会被静默忽略,令牌根本不会进到环境变量里。而您发现它没生效的时刻,正好就是真被锁在门外那一刻。

配完立刻自检,确认环境变量真的渲染出来了:

helm template t supkube \
--set eula.accept=true \
--set auth.dex.publicURL=http://example.invalid \
-f my-values.yaml | grep -A1 AUTH_STATIC_TOKENS_JSON

渲不出这个环境变量,或者值是 "[]",都说明键写错了或 enabled 没打开。

注意这条命令的两个前置:不加 --set eula.accept=true 会被许可检查挡下来、输出为空;charts/ 下缺少 Velero 子 Chart 时整条命令会报依赖错误。这两种情况下 grep 同样是空结果,别把它们误判成"环境变量没渲染出来"——先确认命令本身跑通了。

无论哪条通道,改绑定都只能靠 helm upgrade​

产品没有修改 RBAC 绑定的接口,只有一个只读的 GET /api/v1/auth/rbac/bindings。绑定来自环境变量,由 Chart 渲染。

所以要把两件事分开看:

锁死期间能做什么
修复配置本身三条通道都做不到,只能 helm upgrade
继续维持业务预置的 admin 令牌可以照常备份/还原/查状态;邮箱直绑可以用界面;htpasswd 不行
接入用户组时的安全顺序
  1. 先只配 user: 邮箱绑定,enabled: true 上线,确认能正常登录
  2. 再加 group: 绑定,在「我的权限」页确认自己被识别成了预期的组
  3. 确认组绑定生效后,保留那几条邮箱绑定不要删

兜底角色​

auth.rbac.defaultRole 决定没有命中任何绑定的用户拿到什么角色:

取值实际效果建议
viewer未绑定用户可读取全平台数据生产基线
admin未绑定用户拥有全部权限仅限演示
none(或任何不存在的角色名)未绑定用户所有操作返回 403最严格
空字符串 ""等同于 viewer,不是拒绝⚠ 不要用
空字符串不会拒绝任何人

把 defaultRole 设成 "" 并不会让未绑定用户拿到 403,实际效果是 viewer——realm 里任何能登录的人都能只读全平台的备份数据。

原因是 Chart 渲染这个值时带了兜底:空字符串被视为"未设置",于是回落到 viewer。

更极端的情况:如果绕过 Chart 直接部署、或用 kustomize 覆盖时把这个环境变量删掉了,后端自身的兜底是 admin。两条路都到不了 403。

真正要拒绝未绑定用户时怎么配​

填一个不存在的角色名:

auth:
rbac:
enabled: true
defaultRole: "none" # 任何不在 admin/editor/viewer 里的字符串均可

权限判定是按角色等级比较的(admin > editor > viewer),未知角色的等级为 0,低于最低档 viewer,因此任何需要 viewer 及以上的接口都会返回 403。这不是取巧,而是这套等级模型的既定行为。

配置后务必实测

这一项配错的两种方向都是"看起来更严格、实际更宽松",且不会有任何报错提示。改完后请用一个未绑定的测试账号实际登录验证:

curl -s -o /dev/null -w '%{http_code}\n' \
https://supkube.example.com/api/v1/backups \
-H "Authorization: Bearer $UNBOUND_USER_TOKEN"

期望返回 403。若返回 200,说明兜底角色并没有按您以为的方式生效。

从关闭切换到开启​

开启 RBAC 前先把管理员用户组绑定好,否则升级完成后可能没有人能做写操作。建议顺序是:先补齐 bindings 再开 enabled,两次 helm upgrade 分开执行。

helm upgrade supkube supkube/supkube --reset-values -n supkube \
-f values.yaml
备注

带过 --set 的安装在后续升级时如果不加 --reset-values,旧的取值会粘住。修改 RBAC 配置时建议统一改用 values 文件加 --reset-values。

验证方法​

界面路径「系统设置」的「我的权限」标签会显示当前用户的邮箱、所属用户组、解析出的角色、允许访问的命名空间,以及集群里全部绑定的只读列表。

命令行侧:

kubectl -n supkube get cm supkube-config -o yaml | grep -i rbac
kubectl -n supkube exec deploy/supkube-backend -- \
wget -qO- http://127.0.0.1:8080/api/v1/auth/rbac/bindings

用一个仅绑定为 viewer 的账号登录,尝试创建备份应当被拒绝,即为生效。

相关文档​