- 后端
- 云原生
【免费下载链接】deis
Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.
Deis 是一个基于 CoreOS 与 Docker 构建的 PaaS 平台,其集群运营离不开对用户体系与认证凭证的精细管理。本文基于官方运营任务文档,结合 controller、client、deisctl 等模块源码,系统讲解 Deis 的两类用户模型、管理员晋升、注册开关(registrationMode)以及认证令牌的重新签发,帮助你掌握一套可落地、可验证的集群日常运维方案。
用户体系概览:普通用户与管理员
Deis 平台将用户划分为两个类别:
- 普通用户(normal users):可以使用 Deis 的大部分功能——创建和部署应用、添加/移除域名、管理应用配置等;
- 管理员(administrators):拥有普通用户的全部权限,此外对所有应用都拥有 owner 级访问权限,还能执行跨用户的令牌管理、注册控制等平台级操作。
一个重要的规则是:在 Deis 安装后创建的第一个用户会自动成为管理员。这意味着首次部署完成后,请妥善保管该初始账号的凭证,它是你管理整个平台的基础入口。
从源码层面看,管理员身份的判定基于 Django 用户模型中的is_superuser/is_staff标志。AdminPermsViewSet在授予管理员权限时将两者同时置为True,并在撤销时恢复为False(参见 controller/api/views.py):
def create(self, request, **kwargs): user = get_object_or_404(User, username=request.data['username']) user.is_superuser = user.is_staff = True user.save(update_fields=['is_superuser', 'is_staff']) return Response(status=status.HTTP_201_CREATED) def destroy(self, request, **kwargs): user = get_object_or_404(User, username=kwargs['username']) user.is_superuser = user.is_staff = False user.save(update_fields=['is_superuser', 'is_staff']) return Response(status=status.HTTP_204_NO_CONTENT)将普通用户提升为管理员
使用deis perms命令即可把用户提升为管理员:
$ deis perms:create john --admin Adding john to system administrators... done命令的完整语法在 client/parser/perms.go 中有明确定义:
Usage: deis perms:create <username> [-a --app=<app>|--admin] Arguments: <username> the name of the new user. Options: -a --app=<app> grants <username> permission to use <app>. --admin grants <username> system administrator privileges.其中--admin与--app是互斥选项:前者授予系统管理员权限,后者则是把用户添加为某个应用的协作者(collaborator)。底层的PermCreate逻辑在 client/cmd/perms.go 中分支处理:
if admin { fmt.Printf("Adding %s to system administrators... ", username) err = perms.NewAdmin(c, username) } else { fmt.Printf("Adding %s to %s collaborators... ", username, appID) err = perms.New(c, appID, username) }对应的 API 路径为POST /v1/admin/perms/(参见 controller/api/urls.py),服务端由AdminPermsViewSet.create完成身份标志的写入。如需撤销管理员权限,可使用:
$ deis perms:delete john --admin也可以使用deis perms:list --admin查看当前所有系统管理员列表(参见 client/parser/perms.go)。
禁用用户注册:registrationMode 的三种模式
当平台需要限制新用户注册时,可以通过deisctl config修改 controller 的注册模式。该配置项存放在 etcd 的/deis/controller/registrationMode键中(deisctl 的 config 后端实现见 deisctl/config/etcd/etcd.go)。
仅允许管理员注册
$ deisctl config controller set registrationMode="admin_only"完全禁用注册
$ deisctl config controller set registrationMode="disabled"恢复开放注册
$ deisctl config controller set registrationMode="enabled"enabled同时也是默认值——controller 的启动脚本通过etcd_set_default registrationMode "enabled"为集群初始化该键(参见 controller/bin/boot)。如果集群是从早期版本升级而来,存在/deis/controller/registrationEnabled旧键,数据迁移脚本会将其自动转换为新的registrationMode键(参见 controller/migrations/data/0002.sh)。
配置如何生效:从 etcd 到 Django 设置
deisctl config controller set key=value本质上是在 etcd 的/deis/controller/命名空间下写入键值。deisctl 的配置逻辑先把目标拼接为/deis/<component>/前缀,再用正则^(.+)=([\s\S]+)$解析key=val参数并写入后端(参见 deisctl/config/config.go):
rootPath := "/deis/" + target + "/" ... path := root + k val, err := valueForPath(path, v) ... ret, err := cb.Set(path, val)controller 容器内的 confd 会把该键渲染进 Django 设置文件:
{{ if exists "/deis/controller/registrationMode" }} REGISTRATION_MODE = '{{ getv "/deis/controller/registrationMode" }}' {{ end }}(参见 controller/templates/confd_settings.py)
随后注册接口由权限类HasRegistrationAuth把关(参见 controller/api/permissions.py):
def has_permission(self, request, view): try: if settings.REGISTRATION_MODE == 'disabled': raise exceptions.PermissionDenied('Registration is disabled') if settings.REGISTRATION_MODE == 'enabled': return True elif settings.REGISTRATION_MODE == 'admin_only': return request.user.is_superuser else: raise Exception("{} is not a valid registation mode" .format(settings.REGISTRATION_MODE)) except AttributeError: return True三种模式的最终行为可以归纳为:
| registrationMode | 行为 | 实现要点 |
|---|---|---|
enabled | 任何人均可注册 | 直接返回True |
admin_only | 仅管理员(is_superuser)可注册 | 返回request.user.is_superuser |
disabled | 完全禁止注册 | 抛出PermissionDenied('Registration is disabled') |
| 其他任意值 | 拒绝注册并报错 | 抛出异常,提示非法的注册模式 |
该逻辑有完整的单元测试覆盖,例如REGISTRATION_MODE="admin_only"时普通用户注册返回 403、超级用户注册成功,REGISTRATION_MODE="not_a_mode"时注册失败(参见 controller/api/tests/test_auth.py)。
认证令牌机制:token-based HTTP Authentication
controller API 采用基于令牌的简单 HTTP 认证方案(token-based HTTP Authentication),每个用户在其首次注册时会被签发一个认证令牌。令牌认证尤其适合客户端-服务器场景,例如桌面端与移动端 CLI 客户端。
客户端发出的每个 API 请求都会携带该令牌,底层实现在 client/controller/client/http.go:
req.Header.Add("Content-Type", "application/json") if c.Token != "" { req.Header.Add("Authorization", "token "+c.Token) }令牌与用户信息保存在本地配置文件(Linux/macOS 下位于$HOME/.deis/,Unix 实现见 client/controller/client/home_unix.go),写入时以 0600 权限保护(参见 client/controller/client/client.go)。
一旦令牌泄露,就必须立即重新签发。Deis 为此提供了三级粒度的令牌重签能力。
重新签发认证令牌:个体、指定用户与全员
场景一:用户重签自己的令牌
$ deis auth:regenerate Token Regenerated客户端会调用POST /v1/auth/tokens/(参见 client/controller/models/auth/auth.go)。当重签对象是当前用户自己时,客户端还会把返回的新令牌写回本地配置,确保后续请求继续可用(参见 client/cmd/auth.go):
if username == "" && all == false { c.Token = token err = c.Save() ... }场景二:管理员重签指定用户的令牌
$ deis auth:regenerate -u test-user这里-u/--username指定目标用户,需要管理员权限。其参数定义见 client/parser/auth.go:
Usage: deis auth:regenerate [options] Options: -u --username=<username> specify user to regenerate. Requires admin privilages. --all regenerate token for every user. Requires admin privilages.场景三:管理员重签所有人的令牌
集群发生大规模安全事件时,可以一次性重签所有用户的令牌:
$ deis auth:regenerate --all=true服务端实现与权限校验
TokenManagementViewSet.regenerate是这三个场景的服务端入口(参见 controller/api/views.py):
def regenerate(self, request, **kwargs): obj = self.get_object() if 'all' in request.data: for user in User.objects.all(): if not user.is_anonymous(): token = Token.objects.get(user=user) token.delete() Token.objects.create(user=user) return Response("") if 'username' in request.data: obj = get_object_or_404(User, username=request.data['username']) self.check_object_permissions(self.request, obj) token = Token.objects.get(user=obj) token.delete() token = Token.objects.create(user=obj) return Response({'token': token.key})关键点是:all与username两种请求必须由超级用户发起,否则请求会被拒绝。该权限由CanRegenerateToken强制(参见 controller/api/permissions.py):
def has_permission(self, request, view): if 'username' in request.data or 'all' in request.data: return request.user.is_superuser else: return True也就是说:不携带任何目标参数时(重签自己),任何登录用户都允许;一旦涉及他人或全员,只有is_superuser才能通过。
客户端的测试用例也印证了三种请求体的差异——{"all":true}与{"username":"test"},以及空请求体(重签自己)分别对应不同的响应处理(参见 client/controller/models/auth/auth_test.go 与TestRegenerate测试)。
令牌失效后的表现与恢复
令牌一旦被重新签发,旧令牌立即失效。用户继续使用旧令牌访问 API 时将收到401 UNAUTHORIZED:
$ deis apps 401 UNAUTHORIZED Detail: Invalid token出现该提示后,用户需要重新登录以获取并使用新的认证令牌:
$ deis auth:login http://deis.example.com登录成功后客户端会获取新令牌并写入本地配置(参见 client/cmd/auth.go),之后的 API 调用将自动携带新令牌。这一"重签令牌 → 旧令牌立即失效 → 重新登录"的闭环,就是 Deis 在令牌泄露场景下的标准恢复流程。
小结:一套完整的用户运营清单
综合以上内容,Deis 集群的用户运营可以沉淀为以下常用操作清单:
- 查看/晋升/撤销管理员:
deis perms:list --admin、deis perms:create <user> --admin、deis perms:delete <user> --admin; - 控制注册入口:
deisctl config controller set registrationMode="enabled|admin_only|disabled",并通过 confd 渲染到 Django 设置后由HasRegistrationAuth强制执行; - 令牌生命周期管理:
deis auth:regenerate(重签自己)、deis auth:regenerate -u <user>(管理员重签指定用户)、deis auth:regenerate --all=true(管理员重签全员); - 验证与恢复:旧令牌请求返回
401 UNAUTHORIZED / Invalid token后,引导用户执行deis auth:login重新登录。
初次部署时请务必牢记:第一个注册的用户自动成为管理员,请妥善保护该账号及其令牌;一旦发生泄露,按上述令牌重签流程及时处置即可将影响面收敛到最小。
- 后端
- 云原生
【免费下载链接】deis
Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.
相关推荐
Prisma 集群(Cluster)详解:集群注册表、认证机制与 CLI 管理命令实战
Prisma 集群(Cluster)详解:集群注册表、认证机制与 CLI 管理命令实战 导读 本文聚焦 Prisma 1.x 中的"集群(Cluster)"概念
后端数据库GraphQL33-js-concepts完整指南:掌握JavaScript开发必备的33个核心概念
33 js concepts完整指南:掌握JavaScript开发必备的33个核心概念 🚀 终极JavaScript学习指南 :作为一名JavaScript开
在 Instant 中集成 Clerk 认证:会话令牌配置、客户端注册与 `signInWithIdToken` 完整实战指南
在 Instant 中集成 Clerk 认证:会话令牌配置、客户端注册与 signInWithIdToken 完整实战指南 Instant 是一个面向 AI 编
后端数据库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考