ClickHouse Cloud 推出 JWT 认证
DataHot 速览
ClickHouse Cloud 在 26.4 及以上版本引入 JWT 认证,允许使用来自 Okta、Microsoft Entra 等 OpenID Connect 身份提供商的短期令牌连接服务,替代数据库密码。客户端出示 JWT 后,ClickHouse 会校验签名与 claims,并在内存中创建临时用户,按令牌中的角色和授权执行查询。令牌过期后访问权限随之失效,从而减少长期数据库凭证的管理、轮换和撤销负担。该功能属于 ClickHouse Cloud 安全与治理能力的一部分。
为什么值得关注:数据库访问凭证治理是平台与安全团队的核心问题;该更新给出了 JWT 认证在 ClickHouse Cloud 中的具体机制、claims 结构与角色映射方式,对数据平台选型和权限治理有参考价值。
译文
AI 逐段翻译简而言之:使用来自你的身份提供商的短期令牌连接到 ClickHouse Cloud,而不是使用数据库密码。
长期有效的数据库凭据难以治理。每个人、每条流水线和每个应用都需要一个密码或证书,必须随着访问权限的变化进行存储、轮换和撤销。
ClickHouse Cloud 服务(26.4 或更高版本)的 JWT 认证用来自现有 OpenID Connect 提供商(包括 Okta 和 Microsoft Entra)的短期 JWT 令牌取代了该工作流程。身份和角色保留在提供商中,而 ClickHouse Cloud 接受该令牌,而不是单独的数据库密码。当令牌过期时,它所提供的访问权限也随之失效。
这减少了安全和平台团队必须管理的凭据数量,并消除了为每个人或工作负载配置持久数据库用户的需要。它是我们在 ClickHouse Cloud 中更广泛的安全和治理工作的一部分。
工作原理
当客户端出示 JWT 令牌时,ClickHouse 会根据配置的提供商验证其签名和必需的声明。然后它会创建一个临时用户,并在服务的权限限制内应用令牌中的角色和授权。
令牌携带标准的 JWT 声明,以及用于角色和授权的可选 ClickHouse 声明:
iss,即谁签发了令牌aud,即令牌面向哪个服务sub,即用户是谁iat和exp,即令牌的签发时间和过期时间clickhouse:roles,即可选的要激活的现有角色名称列表
如果你的身份提供商对角色使用不同的声明名称(例如 groups),你可以告诉 ClickHouse 读取哪一个。
1{2"iss":"https://your-tenant.okta.com",3"sub":"jane.doe",4"aud":"my-clickhouse-service",5"exp":1719504000,6"iat":1719500400,7"clickhouse:roles":["analyst","reader"]8}当有效令牌到达时,ClickHouse 会在内存中创建一个临时用户,赋予其令牌所请求的访问权限,并运行查询。用户名遵循固定模式,其中哈希涵盖签发者、主体、受众和角色声明:
1JWT::<subject>::<claims_hash>同一个人的两个具有不同角色的令牌会生成两个不同的用户,因此你可以在 system.users 中区分这些会话,即使它们属于同一身份。在多副本服务中,令牌随转发的查询一起传递,每个节点独立验证它。
不再需要用户配置
临时用户改变了数据库端管理用户的含义。对于密码或证书用户,有人会为每个新员工运行 CREATE USER 和一组 GRANT 语句,使其与身份提供商保持同步,并记得在他们离开时 DROP USER。大多数团队最终会将其脚本化,而脚本会逐渐偏离。
使用 JWT 认证则无需脚本化。用户首次出示有效令牌时会在内存中出现,携带该令牌中的角色,并在令牌的 exp 过后由后台任务移除。用户本身永远不会写入磁盘。没有 CREATE USER 步骤,而 CREATE USER ... IDENTIFIED WITH jwt 会故意抛出异常,因为令牌生命周期就是用户生命周期。ALTER USER 和 DROP USER 也不适用,并且 JWT 用户不会包含在备份中,因为没有什么可恢复的。
你在 ClickHouse 中管理的是角色。创建一次 analyst、pipeline_writer 或你的团队需要的任何角色,然后让身份提供商通过将角色名称放入令牌来决定谁获得它们。入职就是在你的提供商中进行一次组分配。离职就是移除它。而 system.users 显示的是当前活跃的用户,而不是所有曾经被授予过访问权限的人。
自带身份提供商
如果你的身份提供商支持 OpenID Connect,你就已经拥有 ClickHouse 所要求的一切。OIDC 提供商会在其发现文档中发布其签发者和 jwks_uri,并签发已经携带 iss、aud、sub、exp 和 iat 的令牌。这些就是 ClickHouse 检查的值。我们已经验证了与 Okta 和 Microsoft Entra 的设置,任何遵循该标准的提供商都以相同方式工作。对于自定义提供商,ClickHouse 本身不运行登录流程。你的提供商签发令牌,你的客户端出示它,ClickHouse 验证它。
在 Enterprise 计划中,对于运行 26.4 或更高版本的服务,在 Cloud 控制台中打开你的服务并转到设置 → 安全 → JWT 认证。每个提供商需要一个名称、你的提供商放入其令牌中的签发者和受众值,以及它发布其 JSON Web Key Set(JWKS)的 HTTPS URL。如果你的提供商将组成员身份放在 clickhouse:roles 之外的声明中,例如 groups 声明,请将 Roles claim 字段设置为该名称。这些值必须与服务上存在的角色名称匹配。ClickHouse 会在你保存时获取 JWKS URL,因此拼写错误会在配置时而不是在某人首次登录时失败。
JWKS 提供商接受 RSA 密钥(RS256)。从版本 26.8 起,P-256、P-384 和 P-521 曲线上的 EC 密钥(ES256、ES384、ES512)也可以使用。JWKS URL 必须是公共 HTTPS 端点。
连接
客户端可以持有两种令牌之一,值得将它们区分开来:由你自己的身份提供商签发的令牌,或由 ClickHouse Cloud 为你的 Cloud 账户签发的令牌。
来自你的身份提供商的令牌
对于自定义提供商,你的身份提供商签发令牌,ClickHouse 驱动程序出示它。获取令牌最简单的方法是使用你已经为你的提供商使用的 OAuth 客户端库。对于服务或流水线,这通常意味着通过你的提供商的 SDK 使用客户端凭据流程。对于个人,这意味着你的提供商提供的任何登录流程。一旦你持有令牌字符串,官方客户端会接受它来代替用户名和密码。
1// clickhouse-js2import { createClient } from'@clickhouse/client'34const client = createClient({5url: 'https://your-instance.clickhouse.cloud:8443',6access_token: token,7})1# clickhouse-connect2import clickhouse_connect34client = clickhouse_connect.get_client(5 host='your-instance.clickhouse.cloud',6 port=443,7 secure=True,8 access_token=token,9)令牌会过期,因此大多数客户端还允许你接入你的刷新逻辑。clickhouse-connect 接受一个 token_provider 可调用对象,它会在首次获取令牌时调用它,并在服务器拒绝过期令牌时再次调用。Go 客户端在其选项中接受一个 GetJWT 回调。Java 客户端在 builder 上有 useBearerTokenAuth,并可用 updateBearerToken 在实时客户端上替换令牌。对于临时查询,clickhouse-client 和纯 HTTP 也可以使用:
1clickhouse-client --host your-instance.clickhouse.cloud --secure --jwt "$TOKEN"23curl -H "Authorization: Bearer $TOKEN" \4'https://your-instance.clickhouse.cloud:8443/?query=SELECT+currentUser()'在每个客户端中,令牌都会替换用户名和密码,而不是作为它们的补充。同时传递两者是错误的。
来自 ClickHouse Cloud 的令牌
每个 Cloud 服务还都有一个内置的认证器,其令牌由 ClickHouse Cloud 为你的 Cloud 账户签发。你永远不需要自己处理这些令牌。SQL 控制台会自动使用它们,并且clickhouse-client --login 会针对你的 Cloud 登录运行 OAuth2 设备代码流程,将结果交换为 ClickHouse 令牌,在后台刷新它,并在新令牌到达时重新连接。
1clickhouse-client --host your-instance.clickhouse.cloud --login针对来去匆匆的用户的配额和行策略
如果 JWT 用户仅在其令牌有效期间存在,那么 ClickHouse 通常附加到用户上的所有内容会怎样?普通用户会锚定大量配置。设置配置文件限制分析师的查询可以使用多少内存。配额限制仪表板每小时可以运行多少查询。行策略确保某个区域团队只能看到其自己区域的行。所有这些都按名称分配给用户,而如果用户每隔几小时就消失,你会期望这些分配也随之消失。
它们不会消失,因为 JWT 用户有两个名称。你之前看到的可见用户名会随着令牌中的角色变化而变化。在其底层,ClickHouse 会为每个身份分配一个由颁发者、主体和受众声明计算得出的 UUID。只要同一个人通过同一个提供商登录,该 UUID 就始终相同,无论令牌携带哪些角色,也无论用户已过期并被重新创建过多少次。
设置配置文件、配额、行策略和列掩码策略都附加到该 UUID 上。你使用与普通用户相同的语句来分配它们,在用户处于活动状态时引用来自system.users 中的用户当前名称:
1ALTER SETTINGS PROFILE readonly_profile ADDTO'JWT::jane.doe::<claims_hash>';该分配记录在配置文件、配额或策略本身上,存放在与你的角色和其他 SQL 创建对象相同的复制访问存储中,在 ClickHouse Cloud 中由 Keeper 提供支持。不会向临时用户写入任何内容,临时用户保留在内存中。因此,该分配在令牌过期、用户被移除以及下一次登录创建新用户后仍然存在。在实践中,大多数团队根本不会按用户分配任何内容。配置文件、配额和行策略也可以附加到角色上,而由于令牌携带的就是角色,将控制项附加到analyst 角色上会自动覆盖每个分析师。
同样的问题也适用于视图。使用SQL SECURITY DEFINER 创建的视图,会以创建者的权限运行,而不是以查询者的权限运行。如果创建者是临时用户,那么该用户的令牌一过期,视图就会失效。因此,当 JWT 用户创建 definer 视图时,ClickHouse 会写入该用户的持久影子副本,其名称是在原始名称后加上:definer 后缀,持有创建者当时的权限,并且无法登录。此后该视图以影子用户身份运行,并在原始令牌消失后继续正常工作。
可用性
| 内置 ClickHouse 认证器 | 自定义身份提供商 | |
|---|---|---|
| 使用者 | SQL 控制台、clickhouse-client --login | 任何持有来自你的 OIDC 提供商的令牌的客户端 |
| 方案 | 全部 | 企业版 |
| 最低版本 | 任意 | 26.4(EC 密钥为 26.8) |
| 设置 | 无,随服务预置 | Cloud 控制台,设置 → 安全 |
一个可供构建的基础
JWT 认证归结为一个理念:只要该声明有效,ClickHouse 就信任一份关于你是谁以及你持有哪些角色的签名声明。你的身份提供商决定访问权限。数据库用户不再是你创建和删除的东西。令牌可以窄到一个角色,短到一项任务,适用于终端前的人、流水线或仅存活几分钟的代理。
我们将 JWT 认证视为一个可以持续构建的基础。签名声明是一种通用方式,用于向 ClickHouse 提供经过验证的身份,我们可以继续扩展令牌携带的内容、它来自哪里,以及该身份可以做什么。
《JWT 认证参考》详细介绍了声明、临时用户和客户端用法。
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏