Terraform AWS Provider 中 aws_eks_cluster_auth 数据源的原理与实战:预签名 STS 请求生成 EKS 认证 Token
2026/9/18 20:03:29 网站建设 项目流程

Terraform AWS Provider 中 aws_eks_cluster_auth 数据源的原理与实战:预签名 STS 请求生成 EKS 认证 Token

【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws

在 Terraform 中管理 EKS 集群时,aws_eks_cluster_auth数据源负责利用当前 AWS 凭证生成一个与 AWS IAM Authenticator 兼容的临时认证 Token,供kuberneteshelm等 Provider 直接接入集群。读完本文,你将掌握该数据源的完整参数与属性、Token 背后的“预签名 STS GetCallerIdentity 请求”工作机制、15 分钟有效期的来源,以及它在 Terraform AWS Provider 仓库中的源码实现与测试验证方式。

数据源概述

aws_eks_cluster_auth用于获取一个可以与 EKS 集群通信的认证 Token。它使用 AWS Provider 中配置的 IAM 凭证生成临时 Token,该 Token 与 AWS IAM Authenticator 的认证机制兼容,因此既可以用于认证到 EKS 集群,也可以用于任何配置了 AWS IAM Authenticator 服务端的集群。

NOTE(原文档提示):通过数据源动态配置 Terraform Provider 在 Terraform 1.3.0 以下版本会对资源导入支持产生影响(对应上游 Terraform issue #13018)。在使用该数据源驱动provider "kubernetes"配置时需要注意这一版本前提。

示例用法

文档给出的标准用法是将aws_eks_clusteraws_eks_cluster_auth两个数据源组合,驱动kubernetesProvider:

data "aws_eks_cluster" "example" { name = "example" } data "aws_eks_cluster_auth" "example" { name = "example" } provider "kubernetes" { host = data.aws_eks_cluster.example.endpoint cluster_ca_certificate = base64decode(data.aws_eks_cluster.example.certificate_authority[0].data) token = data.aws_eks_cluster_auth.example.token }

要点说明:

  • data.aws_eks_cluster.example.endpoint提供 API Server 地址;
  • certificate_authority[0].data是 Base64 编码的 CA 证书,需用base64decode()解码;
  • token来自aws_eks_cluster_auth,作为 Bearer Token 注入kubernetesProvider 的请求头。

仓库中还有一个与数据源配套的 ephemeral resource 用法(ephemeral "aws_eks_cluster_auth"),示例同时接入了kuberneteshelm两个 Provider,可参考 ephemeral 资源文档。

参数与属性参考

参数(Argument Reference)

参数必填说明
name集群名称。源码中使用validation.NoZeroValues校验,即不允许空值
region该资源所在区域,默认继承 Provider 配置中的 Region

属性(Attribute Reference)

属性说明
id集群名称(d.SetId(name)
token用于向集群认证令牌的 Token。在 schema 中标记为Sensitive: true,Terraform 输出/日志中会遮蔽该值

底层实现:一次预签名的 STS GetCallerIdentity 调用

数据源读取逻辑

数据源实现位于 cluster_auth_data_source.go。其核心读取流程非常简短:

func dataSourceClusterAuthRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).STSClient(ctx) name := d.Get(names.AttrName).(string) generator, err := NewGenerator(false, false) // ... token, err := generator.GetWithSTS(ctx, name, conn) // ... d.SetId(name) d.Set("token", token.Token) return diags }

可以看到三步关键操作:

  1. 通过conns.AWSClientSTSClient(ctx)取得 STS 客户端——也就是复用 AWS Provider 已配置好的凭证链(静态凭证、环境变量、实例角色等均可);
  2. 调用NewGenerator(false, false)创建 Token 生成器,两个参数分别为forwardSessionNamecache,数据源场景下均关闭缓存,保证每次读取都签发新 Token;
  3. 调用generator.GetWithSTS(ctx, name, conn)生成 Token,并把集群名设为资源 ID。

Token 的实际形态

真正的生成逻辑在 token.go。该文件头部注释明确说明,它是 Kubernetes 官方 aws-iam-authenticator 项目pkg/token/token.go的硬拷贝(hard copy),并针对 AWS SDK for Go v2 做了适配,仅保留了GetWithSTS一条生成路径。

GetWithSTS的实现核心是:

presigner := sts.NewPresignClient(stsAPI, func(po *sts.PresignOptions) { po.ClientOptions = []func(*sts.Options){ func(o *sts.Options) { o.APIOptions = []func(*middleware.Stack) error{ addClusterIdHeaderSetterMiddleware(clusterID), addExpiryParamSetterMiddleware(requestPresignParam), } }, } }) request, err := presigner.PresignGetCallerIdentity(ctx, &sts.GetCallerIdentityInput{}) // ... return Token{v1Prefix + base64.RawURLEncoding.EncodeToString([]byte(request.URL))}, nil

也就是说,Token并不是一次真实的 API 调用返回的字符串,而是一个被预签名(presign)的GetCallerIdentityHTTPS URL 经 Base64 URL 编码后的产物,外加k8s-aws-v1.前缀。具体机制包括:

  • 集群绑定:中间件向请求头注入x-k8s-aws-id(常量clusterIDHeader),其值为集群名,并把该头加入签名头(signed headers)。AWS IAM Authenticator 校验时要求该头必须被签名,从而把 Token 与特定集群绑定;
  • 有效期:预签名的 STS URL 在X-Amz-Date时间戳起 15 分钟后过期(常量presignedURLExpiration = 15 * time.Minute)。而X-Amz-Expires参数被固定设为 60,注释中说明这是为了兼容 0.3.0 及更早版本 authenticator 的服务端检查(要求该值在 0 到 60 之间),实际过期由X-Amz-Date决定;
  • Token 上限:校验端要求 Token 长度不超过 4KB(maxTokenLenBytes = 1024 * 4)。

校验端(Verifier)

同一文件中保留了校验逻辑Verify(token),它正是接受测试和 AWS 服务端使用的同款校验流程,可作为 Token 格式规范的“活文档”:

  1. 长度不得超过 4KB,否则报token is too large
  2. 必须以k8s-aws-v1.前缀开头,否则报缺少前缀;
  3. Base64(RawURLEncoding)解码后解析 URL,要求 scheme 为https
  4. 主机名必须匹配^sts(\.[a-z1-9\-]+)?\.amazonaws\.com(\.cn)?$,即只接受全球/区域 STS 端点(含中国站点.amazonaws.com.cn);
  5. 路径必须为/
  6. 查询参数必须全部落在白名单内(ActionVersionx-amz-algorithmx-amz-credentialx-amz-datex-amz-expiresx-amz-security-tokenx-amz-signaturex-amz-signedheaders);
  7. Action必须为GetCallerIdentity,且x-k8s-aws-id头必须出现在签名头中;
  8. x-amz-expires必须在 0 到 900 秒之间,x-amz-date必须存在且尚未超过 15 分钟过期窗口。

校验通过后,验证器会真正发起该 GET 请求(携带集群名头),解析GetCallerIdentity响应,得到包含ARNCanonicalARN(将assumed-roleARN 归一化为 IAM 角色 ARN)、AccountIDUserIDSessionNameAccessKeyIDIdentity结构。

测试验证

验收测试:生成后回验 Token

数据源的验收测试位于 cluster_auth_data_source_test.go。测试配置只有三行:

data "aws_eks_cluster_auth" "test" { name = "foobar" }

检查逻辑testAccCheckClusterAuthToken并不只是断言token非空,而是从状态中取出nametoken,调用tfeks.NewVerifier(name)执行verifier.Verify(tok),真实地向 STS 端点发起校验并确认返回的身份 ARN 非空。也就是说,测试链路完整覆盖了“生成 → 校验 → 身份解析”的闭环。

单元测试:Token 格式的边界矩阵

token_test.go 同样是 aws-iam-authenticator 测试的硬拷贝,提供了非常细粒度的边界验证:

  • TestSTSEndpoints:枚举全球、美国、亚太、欧洲、中东、中国等 18 个 STS 端点主机名,验证verifyHost全部通过;
  • TestVerifyTokenPreSTSValidations:构造超长 Token、错误前缀(k8s-aws-v2.)、非法 Base64、httpscheme、非 STS 主机(如google.com)、非/路径、非白名单参数、多值参数、错误 Action、未签名x-k8s-aws-id头、x-amz-expires超限、x-amz-date格式错误、时间戳过期等失败用例,以及多个区域端点的成功用例;
  • TestVerifyNoSession/TestVerifySessionName/TestVerifyCanonicalARN:验证身份解析——无会话用户的 ARN/UserID、含会话名(UserID:SessionName)的拆分,以及arn:aws:sts::...assumed-role/Alice/extra归一化为arn:aws:iam::...role/Alice的行为;
  • HTTP 层错误路径:403 响应、连接错误、响应体读取失败、JSON 解析失败等均以STSError类型返回。

Ephemeral Resource 变体

仓库中还存在一个功能等价的 ephemeral resource(见 cluster_auth_ephemeral.go 与 其文档:

ephemeral "aws_eks_cluster_auth" "example" { name = data.aws_eks_cluster.example.id }

从源码结构看,其Open方法与数据源读取逻辑完全一致:NewGenerator(false, false)+GetWithSTS+ STS 客户端,属性同样是name(Required)与token(Computed、Sensitive),并支持region参数。使用 ephemeral 形态可以让 Token 在应用后即从内存中清除,避免像数据源那样停留在状态文件中,适合把 Token 传给kubernetes/helm等 Provider 的敏感场景。需注意官方文档同时提示:ephemeral resource 是 Terraform 的新特性,仍在演进中。

实践要点小结

  • 15 分钟有效期:Token 基于预签名 URL 的X-Amz-Date计算,15 分钟后失效。若长时任务(如 CI 流水线)中途 Token 过期,需要重新运行 plan/apply 或改用 IAM 角色等自动刷新凭证的方式;
  • 凭证来源透明:数据源不接收任何显式凭证参数,完全依赖 AWS Provider 配置的凭证链,region亦默认继承 Provider 区域;
  • Token 可移植性强:由于 Token 本质是带签名的 URL 编码串,任何实现了 AWS IAM Authenticator 服务端校验的集群(不仅是 AWS 托管 EKS)都可接受该 Token;
  • 敏感性token属性在数据源 schema 中标记为 Sensitive,且数据源文档明确提醒 Terraform < 1.3.0 下由数据源动态配置 Provider 会限制相关资源的导入支持。

相关源码路径索引

内容路径
数据源文档website/docs/d/eks_cluster_auth.html.markdown
Ephemeral 资源文档website/docs/ephemeral-resources/eks_cluster_auth.html.markdown
数据源实现internal/service/eks/cluster_auth_data_source.go
Ephemeral 资源实现internal/service/eks/cluster_auth_ephemeral.go
Token 生成与校验internal/service/eks/token.go
数据源验收测试internal/service/eks/cluster_auth_data_source_test.go
Token 单元测试internal/service/eks/token_test.go

【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws

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

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

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

立即咨询