☰
Deis 集群运营任务实战指南:用户管理、注册策略与认证令牌重新签发
2026/10/11 22:44:59 网站建设 项目流程
  • 后端
  • 云原生

【免费下载链接】deis

Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.

项目地址:https://gitcode.com/gh_mirrors/de/deis
点击查看免费下载

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 集群的用户运营可以沉淀为以下常用操作清单:

  1. 查看/晋升/撤销管理员:deis perms:list --admin、deis perms:create <user> --admin、deis perms:delete <user> --admin;
  2. 控制注册入口:deisctl config controller set registrationMode="enabled|admin_only|disabled",并通过 confd 渲染到 Django 设置后由HasRegistrationAuth强制执行;
  3. 令牌生命周期管理:deis auth:regenerate(重签自己)、deis auth:regenerate -u <user>(管理员重签指定用户)、deis auth:regenerate --all=true(管理员重签全员);
  4. 验证与恢复:旧令牌请求返回401 UNAUTHORIZED / Invalid token后,引导用户执行deis auth:login重新登录。

初次部署时请务必牢记:第一个注册的用户自动成为管理员,请妥善保护该账号及其令牌;一旦发生泄露,按上述令牌重签流程及时处置即可将影响面收敛到最小。

  • 后端
  • 云原生

【免费下载链接】deis

Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.

项目地址:https://gitcode.com/gh_mirrors/de/deis
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询