Terraform AWS Provider 数据源实战:使用 aws_cloudfront_origin_access_identity 读取 CloudFront 源访问身份
2026/9/18 3:36:12 网站建设 项目流程

Terraform AWS Provider 数据源实战:使用 aws_cloudfront_origin_access_identity 读取 CloudFront 源访问身份

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

导读

在 terraform-provider-aws 中,aws_cloudfront_origin_access_identity数据源用于按 ID 读取已存在的 Amazon CloudFront Origin Access Identity(OAI)信息,从而在不重新创建资源的情况下复用其arniam_arncloudfront_access_identity_paths3_canonical_user_id等关键属性。本文以官方数据源文档为主体,结合仓库源码与配套资源文档,完整讲解其参数、导出属性、与aws_cloudfront_distribution及 S3 桶策略的组合用法,以及底层实现与测试验证。读完本文,你将掌握用一行数据源配置安全引用 OAI 并在 CloudFront 分发与 S3 私有内容授权场景中正确使用的完整方案。

数据源概述

数据源(Data Source)在 Terraform 中用于"读取"而非"管理"外部已有资源。aws_cloudfront_origin_access_identity即属于此类:你只需要提供 OAI 的 ID(形如E1ZAKK699EOLAL),Provider 就会调用 CloudFront 的GetCloudFrontOriginAccessIdentityAPI,把该 OAI 的 ARN、IAM ARN、S3 规范用户 ID、访问路径等信息一次性读回并暴露为可引用的导出属性。

从仓库源码看,该数据源在 internal/service/cloudfront/origin_access_identity_data_source.go 中通过@SDKDataSource("aws_cloudfront_origin_access_identity")注解注册,属于 SDK v2 风格的资源定义,核心读取逻辑由dataSourceOriginAccessIdentityRead实现(见 同文件 L63-L85)。

基本用法

官方文档给出的最小示例非常简洁:只需要传入id一个必填参数。

data "aws_cloudfront_origin_access_identity" "example" { id = "E1ZAKK699EOLAL" }

在实际项目中,更常见的做法是与aws_cloudfront_origin_access_identity资源配合使用:由资源创建 OAI,再用数据源读取其属性。仓库中的验收测试 origin_access_identity_data_source_test.go 就展示了这一模式:

resource "aws_cloudfront_origin_access_identity" "test" { comment = "some comment" } data "aws_cloudfront_origin_access_identity" "test" { id = aws_cloudfront_origin_access_identity.test.id }

这样既享受了资源的创建/更新/删除生命周期管理,又通过数据源拿到标准化的属性集合,便于在多个资源之间复用。

Argument Reference:参数说明

该数据源仅支持一个参数:

参数是否必填说明
idRequired源访问身份的标识符(identifier),例如E1ZAKK699EOLAL

在源码层面,id被定义为TypeStringRequired: true(见 origin_access_identity_data_source.go L50-L53)。读取时,Provider 会执行:

id := d.Get(names.AttrID).(string) output, err := findOriginAccessIdentityByID(ctx, conn, id)

findOriginAccessIdentityByID位于 internal/service/cloudfront/origin_access_identity.go L161-L183,其行为要点包括:

  • 构造GetCloudFrontOriginAccessIdentityInput{Id: ...}调用 AWS SDK;
  • 若服务返回NoSuchCloudFrontOriginAccessIdentity,会被包装为retry.NotFoundError,便于上层做"未找到"判断;
  • 若返回内容为空(outputCloudFrontOriginAccessIdentity或其CloudFrontOriginAccessIdentityConfig为 nil),则返回tfresource.NewEmptyResultError(),避免空指针访问。

从源码结构可以看出,该数据源对"ID 不存在"与"API 返回空"两类异常都做了显式处理,错误信息形如reading CloudFront Origin Access Identity (%s): %s

Attribute Reference:导出属性详解

id外,数据源会导出以下属性(与aws_cloudfront_origin_access_identity资源的导出属性一一对应,详见 origin_access_identity.go L38-L71):

属性类型说明
arnstring源访问身份的 ARN
caller_referencestringCloudFront 内部使用的调用者引用值,用于支持未来对 OAI 的更新
cloudfront_access_identity_pathstring供 CloudFront 使用的完整路径快捷写法(见下文)
commentstringOAI 的可选备注信息
etagstringOAI 信息的当前版本号,例如E2QWRUHAPOMQZL
iam_arnstring预生成的、可直接用于 S3 桶策略的 ARN
s3_canonical_user_idstringOAI 对应的 Amazon S3 规范用户 ID(canonical user ID)

各属性的生成逻辑(源码级)

dataSourceOriginAccessIdentityRead(origin_access_identity_data_source.go L63-L85)中,各导出属性并非全部来自 API 响应,部分是由 Provider 本地拼接生成的:

  • arn:调用originAccessIdentityARN(见 origin_access_identity.go L200-L203),生成形如arn:aws:cloudfront::<account>:origin-access-identity/<id>的全局 ARN;
  • cloudfront_access_identity_path:直接拼接为字符串常量"origin-access-identity/cloudfront/" + id。这正是 CloudFront 分发配置中s3_origin_config需要的特殊路径前缀;
  • iam_arn:调用originAccessIdentityIAMUserARN(见 origin_access_identity.go L205-L208),生成arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <id>,其中iam服务、账户段固定为cloudfront
  • caller_referencecomment:直接取自 API 返回的CloudFrontOriginAccessIdentityConfig
  • etag:取自GetCloudFrontOriginAccessIdentityOutput.ETag
  • s3_canonical_user_id:取自CloudFrontOriginAccessIdentity.S3CanonicalUserId

对应地,资源侧测试 origin_access_identity_test.go L36-L45 用正则验证了这些属性的格式,例如s3_canonical_user_id^[0-9a-z]+开头、cloudfront_access_identity_path匹配^origin-access-identity/cloudfront/[0-9A-Z]+iam_arn匹配^arn:<partition>:iam::cloudfront:user/CloudFront Origin Access Identity [0-9A-Z]+,可作为理解各字段格式的权威依据。

实战组合一:在 CloudFront 分发中引用 OAI

创建 OAI 的主要目的,是让 CloudFront 通过该身份访问 S3 桶中的私有内容。在aws_cloudfront_distribution资源的s3_origin_config结构中,origin_access_identity字段要求传入带origin-access-identity/cloudfront/前缀的完整路径——这正是cloudfront_access_identity_path属性存在的意义,省去了手动拼接的麻烦。

data "aws_cloudfront_origin_access_identity" "example" { id = "E1ZAKK699EOLAL" } resource "aws_cloudfront_distribution" "example" { # ... other configuration ... origin { domain_name = aws_s3_bucket.example.bucket_regional_domain_name origin_id = "myS3Origin" s3_origin_config { origin_access_identity = data.aws_cloudfront_origin_access_identity.example.cloudfront_access_identity_path } } # ... other configuration ... }

在 website/docs/r/cloudfront_distribution.html.markdown 的官方示例中,同一个 OAI 甚至可以同时被 origin group 的两个成员(primaryS3failoverS3)引用,可见cloudfront_access_identity_path是可多处复用的标准配置值。数据源化之后,即使 OAI 由其他流程(或另一个 Terraform 配置)创建,你也能安全地拿到这条路径。

实战组合二:用 iam_arn 配置 S3 桶策略(避免漂移)

拿到 OAI 后,还需要在 S3 桶策略中授予其读取权限,才能让 CloudFront 访问桶内对象。官方资源文档 website/docs/r/cloudfront_origin_access_identity.html.markdown 特别提醒了一个坑:AWS API 可能会把用s3_canonical_user_idCanonicalUser)主体验写的策略自动改写成AWSIAM ARN 主体系,导致 Terraform 反复出现无意义的 diff。因此推荐直接使用iam_arn

data "aws_cloudfront_origin_access_identity" "example" { id = "E1ZAKK699EOLAL" } data "aws_iam_policy_document" "s3_policy" { statement { actions = ["s3:GetObject"] resources = ["${aws_s3_bucket.example.arn}/*"] principals { type = "AWS" identifiers = [data.aws_cloudfront_origin_access_identity.example.iam_arn] } } } resource "aws_s3_bucket_policy" "example" { bucket = aws_s3_bucket.example.id policy = data.aws_iam_policy_document.s3_policy.json }

要点解读:

  • actions使用s3:GetObject,仅开放对象读取;
  • resources限定为桶内全部对象(arn/*);
  • principalstype固定为"AWS"identifiers传入 OAI 的iam_arn,即arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <id>形式;
  • 策略通过aws_iam_policy_document生成 JSON 后交给aws_s3_bucket_policy挂载。

这一写法同时规避了s3_canonical_user_id被 API 规范化改写导致的漂移问题。若你确实需要s3_canonical_user_id(例如在非桶策略场景下按规范用户 ID 授权),数据源同样提供该属性,可配合CanonicalUser主体验证使用。

底层原理与注意事项

读取流程与错误处理

数据源的完整调用链为:dataSourceOriginAccessIdentityReadfindOriginAccessIdentityByIDGetCloudFrontOriginAccessIdentity(AWS SDK v2)。任何失败都会以diag.Diagnostics形式返回,错误文本包含 OAI 的 ID,便于排障。测试 origin_access_identity_data_source_test.go L21-L41 通过TestCheckResourceAttrPair逐一断言数据源与资源同名属性完全一致,覆盖了arniam_arncommentcaller_references3_canonical_user_idcloudfront_access_identity_path等字段,验证了数据源读取结果的正确性。

使用注意事项

  1. id一旦填错或对应 OAI 已被删除,plan/apply会直接报错(NoSuchCloudFrontOriginAccessIdentity会被识别为非 NotFound 的常规错误返回),因此在多配置复用场景下,优先从aws_cloudfront_origin_access_identity资源输出中引用id,避免硬编码;
  2. 若 OAI 由当前配置的aws_cloudfront_origin_access_identity资源创建,可直接使用资源属性(如aws_cloudfront_origin_access_identity.example.iam_arn),数据源更适用于"读取他人已建/存量 OAI"或需要统一数据接口的场景;
  3. arniam_arn是两类不同用途的 ARN:arn用于标识 CloudFront 资源本身,iam_arn是特制的 IAM 用户形式 ARN,专用于 S3 桶策略Principal,两者不可混用;
  4. 若需一次性枚举账户下所有 OAI 并批量获取其iam_arnss3_canonical_user_ids,可进一步查阅aws_cloudfront_origin_access_identities(复数)数据源,其实现见 internal/service/cloudfront/origin_access_identities_data_source.go,支持按comments过滤并分页遍历ListCloudFrontOriginAccessIdentities

总结

aws_cloudfront_origin_access_identity数据源以极低的配置成本(仅id一个必填参数)为 Terraform 配置提供了 OAI 的统一信息入口。结合源码可以确认:cloudfront_access_identity_patharniam_arn均由 Provider 按 CloudFront 约定格式本地生成,其余属性直接取自GetCloudFrontOriginAccessIdentityAPI 响应。把它与aws_cloudfront_distributions3_origin_config、以及基于iam_arn的 S3 桶策略配合使用,即可完整落地"CloudFront + 私有 S3 内容"的经典架构,同时规避桶策略漂移问题。相关文档与源码可继续查阅:

  • 数据源官方文档:website/docs/d/cloudfront_origin_access_identity.html.markdown
  • 配套资源文档:website/docs/r/cloudfront_origin_access_identity.html.markdown
  • 数据源实现:internal/service/cloudfront/origin_access_identity_data_source.go
  • 资源实现与 ARN 生成:internal/service/cloudfront/origin_access_identity.go
  • 数据源验收测试:internal/service/cloudfront/origin_access_identity_data_source_test.go
  • 分发配置示例:website/docs/r/cloudfront_distribution.html.markdown

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

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

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

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

立即咨询