news 2026/9/17 12:53:34

ZenML Service Account API Keys 完全指南:REST API 端点、轮换机制与 CLI 实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ZenML Service Account API Keys 完全指南:REST API 端点、轮换机制与 CLI 实战

ZenML Service Account API Keys 完全指南:REST API 端点、轮换机制与 CLI 实战

【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml

ZenML 通过「服务账户(Service Account)+ API Key」机制为自动化工作流(CI/CD 流水线、定时任务、远程 Agent)提供机器身份认证。本文基于开源仓库中 API Keys 参考文档 与其配套的 Rotate 参考文档,结合服务端端点实现、数据模型与 CLI 源码,完整讲解 API Key 的创建、查询、更新、删除与轮换(Rotation)五个核心操作,以及底层模型字段、权限校验与密钥存储细节。读完本文,你将能够通过curlzenmlCLI 独立完成服务账户 API Key 的全生命周期管理。

一、背景:为什么需要服务账户与 API Key

ZenML 是一个面向 MLOps 的端到端平台,其 ZenML Server 通过 REST API 暴露所有功能。当 CI/CD 流水线、定时任务或远程 Agent 需要以机器身份(而非交互式用户身份)访问 ZenML Server 时,服务账户(Service Account)与 API Key 就是标准认证方案:

  • 服务账户:一种机器身份实体,隶属于服务账户体系(见 Service Accounts 参考文档);
  • API Key:绑定在某个服务账户之下的密钥凭据,用于通过Authorization头或zenml login --api-key方式完成认证。

从服务端路由定义看,API Key 的全部端点都挂在服务账户资源之下,路由前缀为/api/v1/service_accounts,且APIRouter同时使用service_accountsapi_keys两个标签(见 service_accounts_endpoints.py),路径常量定义在 constants.py 与 constants.py:

API_KEYS = "/api_keys" API_KEY_ROTATE = "/rotate" SERVICE_ACCOUNTS = "/service_accounts"

二、API 端点总览

API Key 管理共包含6 个端点(5 个位于主文档,1 个轮换端点在配套文档中),全部以/api/v1/service_accounts/{service_account_id}/api_keys为基路径:

方法路径用途
GET/api/v1/service_accounts/{service_account_id}/api_keys列出某服务账户下的所有 API Key
POST/api/v1/service_accounts/{service_account_id}/api_keys为服务账户创建新的 API Key
GET/api/v1/service_accounts/{service_account_id}/api_keys/{api_key_name_or_id}获取单个 API Key 详情
PUT/api/v1/service_accounts/{service_account_id}/api_keys/{api_key_name_or_id}更新 API Key(改名、改描述、启停用)
DELETE/api/v1/service_accounts/{service_account_id}/api_keys/{api_key_name_or_id}删除 API Key
PUT/api/v1/service_accounts/{service_account_id}/api_keys/{api_key_name_or_id}/rotate轮换(重新生成)API Key

其中{service_account_id}为服务账户 UUID,{api_key_name_or_id}既可以传 API Key 的名称,也可以传其 UUID——从端点签名api_key_name_or_id: Union[str, UUID]可以看出二者皆被接受(见 service_accounts_endpoints.py)。

所有端点均要求通过认证,未认证请求统一返回401;根据操作类型还可能返回404(资源不存在)、409(冲突)、422(参数校验失败)等错误码,路由层通过responses={...}声明了这些错误响应(同文件 L89-L95、L272-L275)。

三、核心数据模型:请求、响应与内部编码

在 api_key.py 中定义了整套 API Key 的 Pydantic 模型,理解这些模型是正确调用 REST API 的前提。

3.1 请求模型

创建 API Key 的请求体APIKeyRequest仅有两个可选填字段(见 api_key.py):

字段类型说明
namestrAPI Key 名称,必填,最大长度受STR_FIELD_MAX_LENGTH限制
descriptionOptional[str]描述信息,可选,最大长度受TEXT_FIELD_MAX_LENGTH限制

更新 API Key 的请求体APIKeyUpdate支持三个可空字段(见 api_key.py):

字段类型说明
nameOptional[str]新的名称
descriptionOptional[str]新的描述
activeOptional[bool]是否启用;设为false可立即吊销该 Key 的登录能力,但保留记录

3.2 响应模型的关键字段

APIKeyResponse将字段拆分为 body、metadata、resources 三部分,其中 body 与 metadata 暴露给 API 调用方:

  • body 部分(见 api_key.py):
    • key明文 API Key 值,仅在创建或轮换后的响应中返回一次,其余查询返回null——这与 CLI 提示「Please store it safely as it will not be shown again」完全一致;
    • active:是否启用,默认true
    • service_account:该 Key 所属的服务账户对象。
  • metadata 部分(见 api_key.py):
    • description:描述;
    • retain_period_minutes:轮换后旧 Key 的保留时长(分钟);
    • last_login:最近一次使用该 Key 登录的时间戳;
    • last_rotated:最近一次轮换的时间戳。

3.3 密钥的编码与存储(底层原理)

API Key 并非明文存储。从源码看存在两套机制:

  1. 对外编码APIKey.encode(){id, key}JSON 做 Base64 编码并加上ZENML_API_KEY_PREFIX前缀,形成对外可见的密钥串;decode_api_key()负责反向解析(见 api_key.py)。
  2. 服务端存储APIKeyInternalResponse.verify_key()使用passlib的 bcrypt 方案(CryptContext(schemes=["bcrypt"]))校验密钥哈希,并刻意在哈希缺失时仍执行一次校验,以规避 CWE-204 响应差异攻击(见 api_key.py)。

这也解释了为什么 API 文档反复强调:明文 Key 只在创建/轮换时出现一次,服务端只保留其哈希。

四、端点逐个详解

4.1 列出 API Key:GET .../api_keys

  • 参数:路径参数service_account_id;查询参数支持分页、排序与过滤。APIKeyFilter提供namedescriptionactivelast_loginlast_rotated等过滤条件,并强制将查询范围限定在指定服务账户(见 api_key.py)。
  • 响应:分页对象Page[APIKeyResponse]。默认hydrate=false,即不包含 metadata 扩展字段。
  • 服务端逻辑(见 service_accounts_endpoints.py):先校验调用方对服务账户的READ权限,再调用zen_store().list_api_keys()返回结果。
  • 示例
curl -X GET "https://<ZENML_SERVER>/api/v1/service_accounts/<SA_ID>/api_keys" \ -H "Authorization: Bearer <ACCESS_TOKEN>"

4.2 创建 API Key:POST .../api_keys

  • 请求体APIKeyRequest,即{ "name": "...", "description": "..." }
  • 响应APIKeyResponse,且本次响应中的key字段包含完整的明文密钥串,必须立即保存。
  • 服务端逻辑(见 service_accounts_endpoints.py):创建前会检查服务账户是否由外部认证(external_user_id)创建,若是则抛出IllegalOperationError,禁止为其关联 API Key;同时要求调用方具备管理员权限(无 RBAC 模式)或相应 RBAC 权限。
  • 示例
curl -X POST "https://<ZENML_SERVER>/api/v1/service_accounts/<SA_ID>/api_keys" \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Content-Type: application/json" \ -d '{"name": "ci-runner-key", "description": "Key used by CI pipeline"}'

4.3 获取单个 API Key:GET .../api_keys/{api_key_name_or_id}

  • 参数api_key_name_or_id支持名称或 UUID;hydrate查询参数控制是否返回 metadata 扩展字段(默认true)。
  • 注意:该端点返回的key字段为null(明文只在创建/轮换时可见)。
  • 服务端逻辑(见 service_accounts_endpoints.py):先校验服务账户的READ权限,再通过zen_store().get_api_key()获取。

4.4 更新 API Key:PUT .../api_keys/{api_key_name_or_id}

  • 请求体APIKeyUpdate,可组合更新namedescriptionactive
  • 典型用途:将active设为false立即吊销某个泄露的 Key;或为 Key 重新命名以反映其用途。
  • 服务端逻辑(见 service_accounts_endpoints.py):与创建一样会拦截外部认证创建的服务账户,并校验服务账户的UPDATE权限。
  • 示例(吊销 Key):
curl -X PUT "https://<ZENML_SERVER>/api/v1/service_accounts/<SA_ID>/api_keys/my-key" \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Content-Type: application/json" \ -d '{"active": false}'

4.5 删除 API Key:DELETE .../api_keys/{api_key_name_or_id}

  • 参数api_key_name_or_id;无请求体,成功返回204
  • 服务端逻辑(见 service_accounts_endpoints.py):校验调用方为管理员(无 RBAC 模式)或具备服务账户UPDATE权限,随后从 ZenStore 删除。删除操作立即生效,使用该 Key 的客户端将立刻认证失败。

4.6 轮换 API Key:PUT .../api_keys/{api_key_name_or_id}/rotate

轮换是 API Key 管理的核心安全操作,配套文档 rotate.md 单独记录了该端点。

  • 请求体APIKeyRotateRequest:仅一个字段retain_period_minutes(默认0),表示轮换后旧 Key 继续有效的分钟数(见 api_key.py)。设为0表示立即作废旧 Key。
  • 响应APIKeyResponsekey字段为新生成的明文密钥,需立即保存。
  • 服务端逻辑(见 service_accounts_endpoints.py):同样拦截外部认证服务账户,并校验UPDATE权限后调用zen_store().rotate_api_key()

轮换的底层语义(见 api_key.py):内部模型维护key_generation(当前代次)与previous_key(上一代密钥哈希)。轮换后:

  • 新密钥成为当前代(key_generation + 1);
  • 旧密钥在retain_period_minutes窗口内仍可认证,实现零停机轮换(先轮换、再分批更新各客户端、最后等窗口过期);
  • is_previous_key_retained()判断旧代是否仍在保留窗口内;verify_key()会同时校验当前代与保留期内的上一代。

轮换示例(保留 30 分钟旧 Key):

curl -X PUT "https://<ZENML_SERVER>/api/v1/service_accounts/<SA_ID>/api_keys/my-key/rotate" \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Content-Type: application/json" \ -d '{"retain_period_minutes": 30}'

五、权限与合规约束

调用上述端点时需注意两类约束(见 service_accounts_endpoints.py):

  1. 外部认证限制:当 ZenML Server 配置为外部认证(AuthScheme.EXTERNAL)时,工作区级服务账户的变更操作(创建/更新/删除 API Key、轮换)会被_ensure_workspace_service_account_mutation_allowed()直接拦截,提示改用组织级服务账户;外部认证创建的服务账户(external_user_id非空)也不能挂载 API Key。
  2. 权限要求:无 RBAC 模式下,创建、更新、删除、轮换均要求调用方为管理员(is_admin);RBAC 模式下则由verify_permissions_and_create_entityverify_permission_for_model等工具按资源类型(ResourceType.SERVICE_ACCOUNT)与动作(READ/UPDATE/DELETE)细粒度校验(见 service_accounts_endpoints.py)。

六、CLI 实战:更便捷的管理方式

REST API 之外,ZenML CLI 在 service_accounts.py 中提供了等价的命令组,适合日常运维。命令统一以zenml service-account api-key为前缀,服务账户名称或 ID 作为位置参数传入。

操作命令关键选项
创建zenml service-account api-key create <SA> <NAME>-d/--description--set-key将新 Key 直接配置到本地客户端;--output-file写入文件
查看zenml service-account api-key describe <SA> <NAME_OR_ID>输出会排除key字段,避免泄露明文
列表zenml service-account api-key list <SA>支持--columns与多种输出格式(table/json/yaml/csv/tsv)
更新zenml service-account api-key update <SA> <NAME_OR_ID>--name--description--active
轮换zenml service-account api-key rotate <SA> <NAME_OR_ID>--retain <分钟>--set-key--output-file
删除zenml service-account api-key delete <SA> <NAME_OR_ID>-y/--yes跳过确认

轮换并立即配置本地客户端(见 service_accounts.py):

zenml service-account api-key rotate my-sa my-key --retain 30 --set-key

执行后 CLI 会调用client.set_api_key()将新 Key 写入本地配置(仅当当前客户端连接的是 ZenML Server 的 REST Store 时可用);未使用--set-key/--output-file时,会在终端打印新 Key 值并提示使用zenml login <URL> --api-key完成登录(见 service_accounts.py)。

七、最佳实践小结

  • 一次性保存明文key明文只在创建与轮换响应中出现,务必通过--output-file写入安全存储或立即配置到密钥管理器;
  • 零停机轮换:轮换时设置合理的retain_period_minutes过渡窗口,先轮换再依次更新各消费方,最后等待旧 Key 自然过期;
  • 快速吊销:怀疑泄露时优先PUTactive置为false(保留审计记录),确认后彻底DELETE
  • 身份隔离:为不同 CI 任务、不同环境各建独立服务账户与 Key,配合APIKeyFilterlast_login字段审计使用情况。

以上全部端点行为均可通过 service_accounts_endpoints.py、api_key.py 与 service_accounts.py 三个源码文件逐一印证,API 参考文档本身位于 README.md 与 rotate.md。

【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 12:52:08

YOLOv10 Android端部署实战:模型压缩、NCNN加速与CameraX实时检测

简介&#xff1a;本资源是一份面向AI算法工程师与移动端开发者的YOLOv11模型轻量化与落地实践指南&#xff0c;聚焦解决深度学习模型在Android端部署时面临的体积大、推理慢、功耗高、兼容性差等核心难题。文档共38页PDF&#xff0c;结构完整、支持目录跳转与左侧大纲导航&…

作者头像 李华
网站建设 2026/9/17 12:52:06

Java var类型推断原理与安全使用指南

简介&#xff1a;本资源是一份面向Java开发者与进阶学习者的JDK 10新特性入门指南&#xff0c;聚焦局部变量类型推断机制——var关键字的原理、用法与实践边界。内容系统解析var的引入背景&#xff08;JDK 10于2018年3月发布&#xff09;、核心优势&#xff08;消除冗余类型声明…

作者头像 李华
网站建设 2026/9/17 12:51:12

AP射频调优实战指南:从现场勘察到信道规划与功率调优

1. 现场勘察是射频调优的前提&#xff0c;不是可选项做AP射频调优这些年&#xff0c;我最大的感受就是&#xff1a;很多人把调优理解成"在AC上把信道和功率改一改"&#xff0c;觉得只要面板上看着合理就行。这种思路搞小规模办公室可能凑合&#xff0c;一旦碰上多楼层…

作者头像 李华
网站建设 2026/9/17 12:49:17

AUTOSAR Dem模块实战配置:从DTC故障管理到NVM存储全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 12:48:08

AI时代的手搓教程:从代码生成到工程掌控

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华