ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Dozzle 简单认证(Simple Auth)完全指南:users.yml 用户管理、角色权限与安全配置

Dozzle 简单认证(Simple Auth)完全指南:users.yml 用户管理、角色权限与安全配置 Dozzle 简单认证Simple Auth完全指南users.yml 用户管理、角色权限与安全配置【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzle导读本指南以 Dozzle 官方文档 docs/fr/guide/authentication/simple.md 为骨架结合仓库源码深入讲解内置的 Simple 认证模式如何用--auth-provider simple启用、如何通过users.yml管理多用户、如何利用 bcrypt 密码、过滤器filter与角色roles实现细粒度访问控制。读完本文你将能独立完成 Dozzle 的本地用户体系搭建包括 CLI / Docker Compose / Docker Secrets 三种部署方式、会话有效期调优以及从源码层面理解认证令牌JWT、签名密钥与热重载机制。一、Simple 认证是什么Dozzzle 对容器拥有完整的控制能力它需要访问docker.sock因此官方强烈建议任何可从互联网访问的部署都必须开启认证。Dozzle 的认证体系分为两类自带认证由 Dozzle 自己管理用户与登录页用户存储在users.yml中外部认证由你的身份提供方GitHub / OIDC / 反向代理接管参见 OAuth 与 OIDC 登录、Forward Proxy 认证。本文的主角——Simple 认证——属于第一类它由 Dozzle 原生实现用户在users.yml中维护登录页也由 Dozzle 自身提供。启用方式只有一个参数--auth-provider simple对应的环境变量为DOZZLE_AUTH_PROVIDERsimple命令行参数定义见 internal/support/cli/args.go。密码只是证明你是某个用户的方式之一。Simple 模式还支持让同一批users.yml用户通过 GitHub 或 OIDC 登录这是另一种证明身份的方式两者读取同一个users.yml详见 OAuth 登录文档。当未配置任何 OAuth provider 时登录页只显示用户名/密码表单。在 internal/web/routes.go 中可以看到simpleprovider 会注册POST /api/token密码登录换取令牌以及DELETE /api/token登出路由users.yml中的密码哈希可为空——当一个账号只绑定 OAuth 身份时密码表单会被自动隐藏PasswordLoginEnabled判断见 internal/auth/simple.go。二、users.yml用户数据库文件启用 Simple 认证后Dozzle 会在/data/目录下寻找用户文件。读取优先级如下users.yml优先users.yaml仅当users.yml不存在时使用如果两个文件都不存在Dozzle 会在启动时直接报错退出No users.yaml or users.yml file found.见 main.go。启动日志会打印实际读取的文件名例如Reading users.yml file——这可以帮助你确认容器内最终加载的是哪个文件。典型文件路径/data/users.yml/data/users.yaml2.1 文件结构users: # admin 在这里是用户名username admin: email: meemail.net name: Admin # 用 docker run -it --rm amir20/dozzle generate admin --password password --email meemail.net --name Admin 生成 password: $2a$11$9ho4vY2LdJ/WBopFcsAS0uORC0x2vuFHQgT/yBqZyzclhHsoaIkzK filter: roles:字段说明字段必填说明用户名YAML key是登录时使用的用户名password视情况bcrypt 哈希。若该用户走 OAuth 登录无密码可以为空但若某用户既无密码又无 GitHub/Email 绑定加载会失败email否用于通过 Gravatar 生成头像可选但推荐name否显示名称留空时回退为用户名filter否用户级容器过滤器见第五节roles否用户角色列表见第六节留空等价于all在 internal/auth/users.go 的User结构体中可以看到email、name、password、github、filter、roles均由 YAML 反序列化而来而username则取自 YAML 的键名。2.2 关键实现事实从源码确认密码必须为 bcrypt 哈希加载时校验哈希长度必须为 60 字符否则报错internal/auth/users.go。旧版曾支持的 sha256 哈希64 字符在 v10.0.1 之后被彻底拒绝加载即报错并提示用dozzle generate重新生成而非等到登录时才失败——这样避免了在未认证请求路径上处理不可比较的哈希。邮箱 / GitHub 登录名不可重复两个用户共用同一个 email 或 GitHub login 会在加载时报错防止登录时映射到错误的用户internal/auth/users.go。邮箱与 GitHub 登录名比较时忽略大小写与首尾空格normalizeEmail/normalizeGithub。无密码、无 GitHub、无 Email 的用户无法登录加载阶段即报错因为这样的条目是配置笔误而非有效账号internal/auth/users.go。过滤器在读取时即解析为容器标签container.ParseContainerFilter解析失败会让整个文件加载失败internal/auth/users.go测试见 internal/auth/simple_test.go。三、用 generate 命令生成 users.yml手工编写 bcrypt 哈希极易出错官方推荐使用内置的generate子命令docker run -it --rm amir20/dozzle generate admin --password password --email testemail.net --name John Doe --user-filter namefoo --user-roles shell users.yml参数说明定义见 internal/support/cli/generate_command.go参数说明admin位置参数用户名必填--password, -p密码--name, -n显示名称--email, -e邮箱--user-filter用户过滤器可用逗号分隔多个--user-roles用户角色可用逗号分隔多个如果省略--password命令会在 stdin 上交互式询问密码readPassword终端模式不回显输入这样密码就不会出现在 shell 历史记录中。必须保留-it参数以获取交互式终端docker run -it --rm amir20/dozzle generate admin --email testemail.net --name John Doe users.yml提示信息写入 stderr因此将 stdout 重定向到users.yml依然有效。也支持管道传入密码echo $PASSWORD | docker run -i --rm amir20/dozzle generate admin users.yml从源码看generate使用 bcrypt cost 因子11生成哈希bcrypt.GenerateFromPassword(..., 11)见 internal/auth/users.go并输出一个只含单用户的users:YAML 文档。更多选项可用docker run -it --rm amir20/dozzle generate --help查看。四、三种部署方式你需要把users.yml挂载进容器让 Dozzle 在/data下能找到它。官方文档给出三种方式4.1 CLIdocker rundocker run -v /var/run/docker.sock:/var/run/docker.sock -v /path/to/dozzle/data:/data -p 8080:8080 amir20/dozzle --auth-provider simple4.2 Docker Composeservices: dozzle: image: amir20/dozzle:latest volumes: - /var/run/docker.sock:/var/run/docker.sock - /path/to/dozzle/data:/data ports: - 8080:8080 environment: DOZZLE_AUTH_PROVIDER: simple4.3 Docker Secrets如果不希望把用户文件作为卷暴露可以使用 Docker Secrets将users.yml以 secret 的形式挂载到目标路径/data/users.ymlservices: dozzle: image: amir20/dozzle:latest environment: - DOZZLE_AUTH_PROVIDERsimple secrets: - source: users target: /data/users.yml volumes: - /var/run/docker.sock:/var/run/docker.sock - dozzle:/data secrets: users: file: users.yml volumes: dozzle:注意/data目录还承担着另一个重要职责——保存会话签名密钥见下节因此即使使用 Secrets 挂载users.yml也建议保留一个持久化的/data卷。五、会话令牌与签名密钥源码原理从源码层面理解 Simple 认证的完整链路能帮助你更好地评估安全性与排障登录用户在登录页提交用户名/密码前端调用POST /api/tokenCreateToken用bcrypt.CompareHashAndPassword校验密码internal/auth/simple.go比对成本因子为 11。签发 JWT校验通过后签发 HS256 JWTclaims 只包含username与签发/过期时间——角色、过滤器等权限信息不写进令牌internal/auth/simple.go。写入 Cookie令牌写入名为jwt的 Cookie属性为HttpOnly、SameSiteLax、HTTPS 下自动附加Secureinternal/auth/http.go。ttl为 0 时是关闭浏览器即失效的会话 Cookie。每次请求实时解析权限中间件校验令牌后仅凭令牌中的username回查users.yml从中解析出当前的角色与过滤器internal/auth/simple.go。这意味着在users.yml中收紧某用户的角色后其已登录的现有会话会立即失效对应权限无需重新登录登录时冻结在令牌里的旧角色位掩码不会造成权限残留对应测试 internal/auth/simple_test.go。从users.yml中删除的用户其令牌立即变为无效测试见 internal/auth/simple_test.go。5.1 session_secret 签名密钥会话令牌的签名密钥并非写死在代码里而是持久化在/data/session_secret文件中internal/auth/secret.go首次启动时生成 32 字节随机密钥crypto/rand以O_EXCL方式创建文件多副本共享卷时先到者胜出避免互相覆盖导致对方会话全部失效密钥与users.yml中每个用户的密码、角色、邮箱、GitHub 绑定共同参与 SHA-256 摘要派生最终的 HS256 签名密钥internal/auth/simple.go因此修改某用户的密码/角色/邮箱/GitHub 绑定会整体更换签名密钥从而使所有已签发的会话失效——这是刻意的安全设计而纯新增/删除用户其他字段不变不会影响签名密钥已有会话保持有效密钥派生按用户名排序进行避免 Go map 随机迭代顺序导致多用户部署每次重启都更换密钥、把所有人踢下线对应测试 internal/auth/simple_test.go若/data只读导致密钥无法持久化Dozzle 会记录警告并临时使用内存密钥代价是重启后会话全部失效fail-soft 设计避免只读挂载的部署无法启动。六、延长认证 Cookie 的生命周期默认情况下Dozzle 使用会话 Cookie浏览器关闭即失效。可以通过--auth-ttl指定有效期docker run -v /var/run/docker.sock:/var/run/docker.sock -v /path/to/dozzle/data:/data -p 8080:8080 amir20/dozzle --auth-provider simple --auth-ttl 48hDocker Compose 等价写法services: dozzle: image: amir20/dozzle:latest volumes: - /var/run/docker.sock:/var/run/docker.sock - /path/to/dozzle/data:/data ports: - 8080:8080 environment: DOZZLE_AUTH_PROVIDER: simple DOZZLE_AUTH_TTL: 48h参数约束从 internal/support/cli/args.go 与 main.go 确认默认值为session表示会话 Cookie不持久化其他取值必须是合法的 Go duration 字符串只接受s秒、m分钟、h小时三个单位例如12h、30m、90s解析失败会在启动时报错退出设置--auth-ttl后Cookie 会带上Expires同时 JWT 的exp声明也会被设置见 internal/auth/simple.go。七、为用户设置专属过滤器filter过滤器用于限制某用户能看到哪些容器。它定义在users.yml的每个用户条目下users: admin: email: name: Admin password: $2a$11$9ho4vY2LdJ/WBopFcsAS0uORC0x2vuFHQgT/yBqZyzclhHsoaIkzK filter: guest: email: name: Guest password: $2a$11$9ho4vY2LdJ/WBopFcsAS0uORC0x2vuFHQgT/yBqZyzclhHsoaIkzK filter: labelcom.example.app上例中admin的filter为空 → 可以看到全部容器guest的filter为labelcom.example.app→ 只能看到带该 label 的容器。这种机制非常适合为外部用户/合作方提供受限的日志查看权限。注意过滤器也可以全局定义即--filter参数对所有用户生效详见 过滤器文档。当某用户自身定义了 filter它优先于全局 filter。从源码看用户过滤器在加载users.yml时被解析成容器标签container.ContainerLabels见 internal/auth/users.go并用于容器列表、日志流等所有 API 的过滤。八、为用户设置专属角色roles角色决定用户能对容器执行哪些操作。配置同样位于users.ymlusers: admin: email: name: Admin password: $2a$11$9ho4vY2LdJ/WBopFcsAS0uORC0x2vuFHQgT/yBqZyzclhHsoaIkzK roles: guest: email: name: Guest password: $2a$11$9ho4vY2LdJ/WBopFcsAS0uORC0x2vuFHQgT/yBqZyzclhHsoaIkzK roles: shell上例中admin未指定角色 → 拥有全部操作权限guest只有shell角色 → 只能在容器内打开 shell。角色是实现最小权限的核心工具。8.1 支持的角色一览角色等价别名授予的权限shelldozzle_shell附加attach到容器并打开 exec 会话。实例还需开启--enable-shellactionsdozzle_actions启动、停止、重启容器。实例还需开启--enable-actionsdownloaddozzle_download将容器日志下载为文件notificationsdozzle_notifications创建和修改通知规则与目的地clouddozzle_cloud绑定、解绑与配置 Dozzle Cloudalldozzle_all以上所有角色。roles为空时的默认值nonedozzle_none无任何角色。仍可按用户过滤器查看日志。优先级高于其他一切几点语法细节源码见 internal/auth/roles.go分隔符逗号、竖线均可也支持 JSON 数组——shell,actions、shell|actions、[shell, actions]都合法大小写不敏感Shell、SHELL均可dozzle_前缀别名为了在 forward proxy 模式下让身份提供方返回的组名可以原样透传角色在内部是位掩码Role按位或组合roles留空时解析为All即all。8.2 用^前缀排除角色任何角色都可以用^前缀标记为排除。排除在最后统一应用因此顺序无关紧要roles: all,^shell # 除 shell 外的所有权限^shell与shell,^all等写法等价。实现上先累加授予位再累加排除位最后roles ^ excludedinternal/auth/roles.go。8.3 none 角色none是唯一不能被取反的角色^none会被忽略只要列表中出现一个none其他所有角色都会被丢弃直接返回None。8.4 两个重要安全警告通知规则作用于整个实例通知规则通过表达式选择容器而不是按用户过滤器选择。因此拥有notifications角色的用户可以为其过滤器本来看不到的容器创建规则并把日志行投递到自己控制的目的地。只应把该角色授予你信任其访问实例全部容器的用户。Dozzle Cloud 同样作用于整个实例绑定操作只会注册一把 API 密钥这把密钥把告警推送、日志流和工具执行都指向一个云端账号。拥有cloud角色的用户可以把实例绑定到自己的云端账号从而透过云看到全部容器也可以删除已有绑定。只应把该角色授予你信任其访问实例全部容器的用户。关于云角色还需要澄清两点该角色管的是绑定不是读取。任何已登录用户都可以在自己的过滤器范围内搜索云日志、查看云告警云端自身触发的工具调用例如在 Telegram 或 Discord 里提出的问题以实例过滤器执行因为背后没有具体的 Dozzle 用户。九、用户文件的动态重载Simple 认证支持免重启热更新UserDatabase.Find在每次查找时都会用os.Stat检查users.yml的修改时间若文件被修改mtime 晚于上次读取时间则重新加载整个数据库internal/auth/users.go并在日志中打印Reloading user database。这意味着修改某个用户的 filter 或 roles →实时生效新请求立即使用新权限见 internal/auth/simple_test.go新增/删除用户 → 立即生效修改密码/角色/邮箱/GitHub 绑定 → 同时导致签名密钥更换所有已登录会话立即失效需要重新登录安全设计使然。因此日常运维中增删用户通常无需重启容器修改密码后让旧会话全部下线也是符合预期的行为。十、部署前的安全自查清单结合官方 认证总览文档 与本文内容Simple 模式上线前请确认Dozzle 必须始终置于认证之后——--auth-providersimple是公网部署的最低要求默认关闭--enable-actions与--enable-shell它们允许启动/停止/重建容器并在容器内执行任意命令仅在需要时开启多用户场景下务必为普通用户配置 roles 与 filter——没有显式角色时用户可看到实例能访问的全部容器绝不直接暴露 forward proxy 模式下的 Dozzle 端口本模式仅信任代理头任何人都可伪造身份只用expose将 Dozzle 置于内网TLS 由反向代理终结参考 反向代理与基础路径 中的 Nginx / Traefik / Caddy 示例不要把 docker.sock 以写权限暴露给不可信用户。注意:ro只标记文件为只读并不能限制 Docker API 操作——如需真正限制应在 docker.sock 前放置 socket 代理。十一、常见问题排查现象原因与处理启动报No users.yaml or users.yml file found./data下没有用户文件检查挂载路径与文件名启动报 password hash 长度错误 / sha256 不支持哈希不是 60 字符 bcrypt用dozzle generate重新生成登录提示 Invalid credentials密码错误确认users.yml中该用户有password字段改了用户文件但权限没变化检查 mtime 是否更新热重载按修改时间触发确认修改的是 filter/roles 字段修改密码后所有用户被踢下线预期行为签名密钥随凭据变化而轮换--auth-ttl启动报错只接受s/m/h单位例如48h、30m更多部署方式Swarm、K8s、远程主机与 agent可参考 Docker Swarm 模式 与 Kubernetes完整的命令行与环境变量清单见 受支持的环境变量。【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表