MinIO 自定义 Token 身份认证:AssumeRoleWithCustomToken STS API 完全指南
2026/9/8 23:29:33 网站建设 项目流程

MinIO 自定义 Token 身份认证:AssumeRoleWithCustomToken STS API 完全指南

【免费下载链接】minioMinIO is a high-performance, S3 compatible object store, open sourced under GNU AGPLv3 license.项目地址: https://gitcode.com/GitHub_Trending/mi/minio

MinIO 通过扩展 STS API 提供AssumeRoleWithCustomToken接口,配合 Identity Management Plugin(身份管理插件)Webhook,可让自建认证体系为对象存储签发临时凭证。本文以 custom-token-identity.md 为核心,完整讲解该接口的请求/响应契约、Role ARN 的生成原理,并结合仓库源码展示一个可运行的插件参考实现,帮助你打通"自有认证 Token → MinIO 临时凭据"的完整链路。

一、什么是 AssumeRoleWithCustomToken

MinIO 原生的身份认证体系支持静态用户、LDAP、OpenID Connect 等。但当业务系统希望接入自有的认证方式(如自建 SSO、内部统一登录、游戏/物联网设备 Token 体系)时,可以启用 MinIO 的 Identity Management Plugin(身份管理插件)Webhook 扩展。

启用插件后,MinIO 服务器就暴露一个额外的 STS API 扩展接口AssumeRoleWithCustomToken。用户或应用只需持有一个对 MinIO 完全不透明(opaque)的 Token,即可调用该接口换取访问对象存储的临时凭证。MinIO 本身不解析这个 Token,而是将其原样转发给配置好的插件端点做校验。

该流程与 OpenID 认证思路相近,区别在于:OpenID 下 MinIO 需要理解 JWT 结构,而自定义 Token 模式下 MinIO 只需"搬运"Token,一切验证逻辑都收敛在外部插件中,集成自由度更高。有一点需要特别注意:该认证方式没有控制台 UI 集成,主要面向机器间认证(machine-to-machine)场景。

整体架构

┌──────────────┐ AssumeRoleWithCustomToken ┌────────────────┐ POST token ┌─────────────────────┐ │ 客户端/应用 │ ────────(opaque Token)──────▶ │ MinIO Server │ ──────────────▶ │ Identity Plugin │ └──────────────┘ ◀─────── 临时 STS 凭证 ────── │ (STS API 扩展) │ ◀── user/claims ─ │ (自定义认证 Webhook) │ └────────────────┘ └─────────────────────┘

二、前置条件:配置 Identity Management Plugin

AssumeRoleWithCustomToken只有在配置了身份管理插件后才会生效。从 STS 处理逻辑 的源码可以看到,如果未初始化认证插件(newGlobalAuthNPluginFn()返回nil),接口会直接拒绝请求并返回错误STS API 'AssumeRoleWithCustomToken' is disabled

插件可通过 MinIO 标准配置 API(mc admin config set/get)或环境变量两种方式配置。配置子系统的完整实现位于 internal/config/identity/plugin/config.go,以下是各配置项的环境变量形式及含义:

环境变量类型必填说明
MINIO_IDENTITY_PLUGIN_URLurl插件 hook 端点(HTTP/HTTPS),如http://localhost:8181/path/to/endpoint
MINIO_IDENTITY_PLUGIN_AUTH_TOKENstring调用插件端点时附带的授权 Token(作为 Authorization 请求头发送)
MINIO_IDENTITY_PLUGIN_ROLE_POLICYstring为插件授权用户应用的一组策略名(多个用逗号分隔)
MINIO_IDENTITY_PLUGIN_ROLE_IDstring用于生成 Role ARN 的唯一 ID
MINIO_IDENTITY_PLUGIN_COMMENTsentence对该配置项的注释说明

从源码 LookupConfig 可以确认几个关键行为:

  • MINIO_IDENTITY_PLUGIN_ROLE_POLICY为必填项,缺失时启动配置会直接报错A role policy must be specified for Identity Management Plugin
  • 若设置了AUTH_TOKEN,MinIO 在向插件发起认证请求时会将Authorization请求头设置为该值;
  • 配置载入阶段会以POST空请求对插件端点做一次连通性Validate探测,无法连通时配置会被拒绝;
  • 插件启用后,MinIO 还会每分钟发起一次HEAD健康检查(doPeriodicHealthCheck),并持续统计可达性、RTT 等指标(见 Metrics 实现)。

Role ARN 是如何生成的

Role ARN 是整个认证流程的关键标识。在 LookupConfig 中可以看到 ARN 的完整生成逻辑:

  • ARN 的 resource 部分以idmp-前缀开始;
  • 若未配置MINIO_IDENTITY_PLUGIN_ROLE_ID,MinIO 会对插件 URL 计算 SHA-1,再以 Base64 URL 安全编码追加到idmp-之后,这样生成的 ARN 在服务重启后保持不变;
  • 若配置了ROLE_ID,则会校验其只包含[A-Za-z0-9_-]字符(正则^[A-Za-z0-9_-]+$),随后拼接为idmp-<ROLE_ID>
  • 最终通过arn.NewIAMRoleARN生成形如arn:minio:iam:::role/idmp-...的 ARN。

插件配置完成后,MinIO 服务启动日志会打印该 Role ARN(参考示例中的arn:minio:iam:::role/idmp-vGxBdLkOc8mQPU1-UQbBh-yWWVQ)。若想使用更可控的固定值,就通过MINIO_IDENTITY_PLUGIN_ROLE_ID指定。同时,插件与 Role ARN → 策略的映射关系会通过 GetRoleInfo 注入 IAM 系统的 rolesMap(见 cmd/iam.go),供后续鉴权使用。

三、STS API 请求参数

配置好插件并取得 Role ARN 后,即可向 MinIO 端点发送 POST 请求来获取临时凭证。请求方法在 STS 路由注册中被绑定为POST,携带以下 Query 参数:

参数类型必填说明
ActionString值必须为AssumeRoleWithCustomToken
VersionString值必须为2011-06-15
TokenString交由身份插件验证的自定义 Token
RoleArnString必须与身份插件生成的 Role ARN 完全匹配
DurationSecondsInteger生成的临时凭证有效期,最小为 900 秒

从 AssumeRoleWithCustomToken 处理器 的源码可以印证以下细节:

  • Token为空会直接返回Invalid empty 'Token' parameter provided
  • RoleArn通过globalIAMSys.GetRolePolicy解析,必须能匹配到插件映射的 Role 与策略,否则请求被拒绝;
  • 若未启用独立的授权插件(AuthZ Plugin),MinIO 会校验 Role 关联的策略确实存在,否则报None of the given policies are defined
  • 有效期取两者的较小值:最终凭证的过期时间 =min(客户端传入的 DurationSeconds, 插件返回的 maxValiditySeconds)。代码中的实现是:expiry先取插件返回值,当客户端传了DurationSeconds且更小时则覆盖(见 cmd/sts-handlers.go)。

使用 curl 发起请求

主文档中给出的示例请求如下:

curl -XPOST 'http://localhost:9001/?Action=AssumeRoleWithCustomToken&Version=2011-06-15&Token=aaa&RoleArn=arn:minio:iam:::role/idmp-vGxBdLkOc8mQPU1-UQbBh-yWWVQ'

实际使用时请将主机与端口替换为你部署环境中对外暴露的 MinIO API/STS 端点,并将TokenRoleArn换成插件真实签发的 Token 与启动日志中打印的 ARN。也可以额外追加&DurationSeconds=3600来显式限制凭证有效期。

四、响应格式与字段解析

AssumeRoleWithCustomToken的 XML 响应结构与 AWS STSAssumeRoleWithWebIdentity类似。主文档给出的格式化响应如下:

<?xml version="1.0" encoding="UTF-8"?> <AssumeRoleWithCustomTokenResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/"> <AssumeRoleWithCustomTokenResult> <Credentials> <AccessKeyId>24Y5H9VHE14H47GEOKCX</AccessKeyId> <SecretAccessKey>H+aBfQ9B1AeWWb++84hvp4tlFBo9aP+hUTdLFIeg</SecretAccessKey> <Expiration>2022-05-25T19:56:34Z</Expiration> <SessionToken>eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiIyNFk1SDlWSEUxNEg0N0dFT0tDWCIsImV4cCI6MTY1MzUwODU5NCwiZ3JvdXBzIjpbImRhdGEtc2NpZW5jZSJdLCJwYXJlbnQiOiJjdXN0b206QWxpY2UiLCJyb2xlQXJuIjoiYXJuOm1pbmlvOmlhbTo6OnJvbGUvaWRtcC14eHgiLCJzdWIiOiJjdXN0b206QWxpY2UifQ.1tO1LmlUNXiy-wl-ZbkJLWTpaPlhaGqHehsi21lNAmAGCImHHsPb-GA4lRq6GkvHAODN5ZYCf_S-OwpOOdxFwA</SessionToken> </Credentials> <AssumedUser>custom:Alice</AssumedUser> </AssumeRoleWithCustomTokenResult> <ResponseMetadata> <RequestId>16F26E081E36DE63</RequestId> </ResponseMetadata> </AssumeRoleWithCustomTokenResponse>

响应结构在 cmd/sts-datatypes.go 中定义为AssumeRoleWithCustomTokenResponse,包含三层核心信息:

  • Credentials:返回AccessKeyIdSecretAccessKeyExpirationSessionToken四元组。拿到后即可用标准的 S3 客户端(配合 session token)访问对象存储;
  • AssumedUser:被假定用户的标识。观察示例中custom:Alice可以看出 MinIO 会把插件返回的user加上custom:前缀构成"父用户"(parent user)。该拼接逻辑见 cmd/sts-handlers.go,parentUser := "custom" + getKeySeparator() + res.Success.User
  • ResponseMetadata.RequestId:请求 ID,用于问题排查与日志关联。

从实现看,生成的SessionToken本身就是携带声明信息(claims)的 JWT:处理器会把expsubroleArnparent以及插件返回的业务 claims 一并写入 token claims,再调用auth.GetNewCredentialsWithMetadata生成凭据(见 cmd/sts-handlers.go)。

五、身份插件的 REST 契约

了解完 STS 侧接口后,还需要理解 MinIO 调用插件的 HTTP 契约,这是自定义认证能否打通的关键。

请求:POST 到插件端点

当收到AssumeRoleWithCustomToken请求后,MinIO 会构造一个 POST 请求发送到配置的插件 URL:

参数(Query)值类型用途
tokenstring来自AssumeRoleWithCustomToken调用、待外部验证的 Token

实现细节见 Authenticate 方法:Token 以 Query 参数token附加到插件 URL,若配置了AUTH_TOKEN则同时附带Authorization头。该认证调用带 5 秒超时;只有当插件返回的 HTTP 状态码为200403时才会被处理,其他状态码统一报错Invalid status code %d from auth plugin

成功响应(200 OK)

Token 有效且授权通过时,插件必须返回 HTTP200,响应体Content-Typeapplication/json,结构如下:

{ "user": <string>, "maxValiditySeconds": <integer>, "claims": <key-value-pairs> }
字段值类型用途
userstring所请求临时凭证的属主标识(会构成 AssumedUser 的custom:前缀部分)
maxValiditySecondsinteger允许的最大过期时长,取值需在 900 秒(含)到 365 天(含)之间
claimskey-value 对需要关联到临时凭证上的附加声明

关于maxValiditySeconds,认证响应校验中定义了上下限常量:minValidityDurationSeconds = 900maxValidityDurationSeconds = 365 * 24 * 3600,超出该区间的返回值会导致认证失败。

关于claims,需要注意一个保留键规则:expparentsub三个键被 MinIO 保留,插件返回的这些键会被忽略。从处理器源码可以看到原因——MinIO 会先自行填充expsubroleArnparent等核心声明,随后在合并插件 claims 时跳过已存在的键(if _, ok := claims[k]; !ok),因此插件无法覆盖这些内部声明。其余自定义 claims(如业务分组groups)则会被原样写入凭证。

失败响应(403 Forbidden)

Token 无效或访问被拒绝时,插件必须返回 HTTP403,响应体Content-Typeapplication/json,结构如下:

{ "reason": <string> }

reason中的错误信息会原样回传给调用方(处理器中将该错误封装为 STSErrSTSUpstreamError,见 cmd/sts-handlers.go)。

六、参考实现:一个可运行的插件端点

仓库中附带了一个可直接运行的玩具级 Go 示例 docs/iam/identity-manager-plugin.go,可用于本地验证上述契约。它的逻辑非常直观:

  • 在内存中维护了一个tokens映射表,将两个预置 Token 分别映射到用户与声明:
    • Tokenaaa→ 用户AlicemaxValiditySeconds = 3600,claims 含分组["data-science"]
    • Tokenbbb→ 用户BartmaxValiditySeconds = 3600,claims 含分组["databases"]
  • 处理器从请求中读取token参数:
    • 缺失时报token parameter not given(返回 400);
    • 未命中映射表时返回403 Forbidden
    • 命中时打印日志并返回200 OK+ 上述 JSON 结构;
  • 服务监听在:8081

注意该文件头部带有//go:build ignore构建约束,属于独立运行的示例程序,不会被编译进 MinIO 主程序。运行方式:

go run docs/iam/identity-manager-plugin.go

结合前文的配置,可用如下环境变量让 MinIO 指向该插件(仅为示意,实际需按你的策略名与端点调整):

export MINIO_IDENTITY_PLUGIN_URL=http://localhost:8081/ export MINIO_IDENTITY_PLUGIN_AUTH_TOKEN= export MINIO_IDENTITY_PLUGIN_ROLE_POLICY=consoleAdmin # 示例策略,可按需替换 export MINIO_IDENTITY_PLUGIN_ROLE_ID=test-plugin

随后使用第一节的 curl 命令携带 Tokenaaa与启动日志中打印的 Role ARN 即可换取临时凭证——这正是主文档示例请求中Token=aaa且返回custom:Alicegroups: ["data-science"]的由来,示例插件与文档请求完全对应。

七、端到端工作流程小结

整个自定义 Token 认证流程可归纳为以下步骤:

  1. 部署并注册插件:实现符合 REST 契约的身份插件端点(参考第六节示例),确保能正确处理tokenQuery 参数并返回约定的成功/失败 JSON;
  2. 配置 MinIO:通过环境变量或mc admin config set设置identity_plugin子系统的 URL、Role Policy 等参数,重启后从服务日志读取生成的 Role ARN;
  3. 客户端换取凭证:向 MinIO API 端点发起POST ?Action=AssumeRoleWithCustomToken&Version=2011-06-15&Token=xxx&RoleArn=arn:minio:iam:::role/idmp-...,获得临时AccessKeyId / SecretAccessKey / SessionToken
  4. 使用临时凭证访问对象存储:任意支持 S3 协议且支持 session token 的客户端均可使用这套凭据完成后续读写操作,凭据过期后需要重新走第 3 步。

八、注意事项

  • AssumeRoleWithCustomToken仅在配置了 Identity Management Plugin 后才可用,且没有控制台 UI 集成,设计初衷是机器认证场景;
  • Token 是"不透明"的,安全性完全取决于插件端点的验证质量,生产环境务必为插件端点启用 HTTPS 与鉴权;
  • 客户端请求的DurationSeconds与插件返回的maxValiditySeconds会取较小值作为最终有效期,插件返回的最大值必须落在 900 秒至 365 天区间内;
  • 插件 claims 中的expparentsub为保留键,会被 MinIO 内部生成的同名声明覆盖忽略;
  • 生成的临时凭证父用户统一以custom:前缀标识,便于与静态用户、LDAP 等其它认证来源在审计与策略管理上区分。

参考资料

  • AssumeRoleWithCustomToken 主文档:本指南的核心契约来源
  • Identity Management Plugin 配置指南:插件的配置项与 REST 契约详解
  • 插件参考实现:可直接运行的 Go 示例
  • STS 处理器实现:AssumeRoleWithCustomToken的完整处理逻辑
  • 插件配置解析:Role ARN 生成、认证请求与响应解析源码
  • STS 响应结构体定义:XML 响应对应的 Go 类型

【免费下载链接】minioMinIO is a high-performance, S3 compatible object store, open sourced under GNU AGPLv3 license.项目地址: https://gitcode.com/GitHub_Trending/mi/minio

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

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

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

立即咨询