You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AWS CDK配置带S3源与OAC的CloudFront分发失败

解决CloudFront + S3 OAC配置错误的CDK修改方案

问题根源

你碰到的Invalid request provided: Illegal configuration: The origin type and OAC origin type differ.错误,是因为当前CloudFront源用了S3静态网站端点(这个模式不支持OAC),而OAC要求源必须是S3的REST API端点。在CDK里,只要桶配置了websiteIndexDocument,默认的S3Origin会自动切换到网站端点,所以得手动调整源配置。

具体修改步骤

1. 调整S3桶定义(可选,但保持配置清晰)

不用删掉websiteIndexDocument,但要确保blockPublicAccess维持BLOCK_ALL,这和使用REST端点不冲突:

export class S3Bucket extends Bucket {
  constructor(scope: Construct) {
    super(scope, S3_BUCKET_NAME, {
      websiteIndexDocument: 'index.html', // 保留静态网站配置,不影响REST端点使用
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
      removalPolicy: RemovalPolicy.RETAIN, // 按需调整,生产环境建议RETAIN
    });
  }
};

2. 修改CloudFront分发的核心配置

重点是强制S3Origin使用REST API端点,同时修正OAC关联和桶策略:

export class CloudFrontDistribution extends cloudfront.Distribution {
  constructor(scope: Construct, bucket: Bucket) {
    // 强制指定S3 REST API作为源,禁用默认OAI
    const s3RestOrigin = new S3Origin(bucket, {
      originAccessIdentity: undefined, // 关闭OAI,改用OAC
      originDomainName: bucket.bucketRegionalDomainName, // 明确用S3区域REST域名
    });

    super(scope, CLOUD_FRONT_DISTRIBUTION_NAME, {
      defaultBehavior: {
        origin: s3RestOrigin,
        viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        compress: true,
      },
    });

    // 创建OAC配置
    const oac = new cloudfront.CfnOriginAccessControl(this, 'MyOriginAccessControl', {
      originAccessControlConfig: {
        name: 'MyOriginAccessControl',
        originAccessControlOriginType: 's3',
        signingBehavior: 'always',
        signingProtocol: 'sigv4',
      },
    });

    // 修正桶资源策略:允许CloudFront通过OAC访问桶内对象
    const cloudFrontAccessPolicy = new PolicyStatement({
      actions: ['s3:GetObject'],
      principals: [new ServicePrincipal('cloudfront.amazonaws.com')],
      effect: Effect.ALLOW,
      resources: [`${bucket.bucketArn}/*`], // 资源是桶内所有对象,之前写错成OAC ID了
      conditions: {
        'StringEquals': {
          // 要填完整的CloudFront分发ARN
          'AWS:SourceArn': `arn:aws:cloudfront::${Stack.of(this).account}:distribution/${this.distributionId}`,
        },
      },
    });

    bucket.addToResourcePolicy(cloudFrontAccessPolicy);

    // 把OAC绑定到CloudFront源,同时清空旧的OAI配置
    const cfnDistribution = this.node.defaultChild as cloudfront.CfnDistribution;
    cfnDistribution.addPropertyOverride(
      'DistributionConfig.Origins.0.OriginAccessControlId',
      oac.attrId
    );
    cfnDistribution.addPropertyOverride(
      'DistributionConfig.Origins.0.OriginAccessIdentity',
      ''
    );
  }
};

3. 关键修正点说明

  • 源域名切换:bucket.bucketRegionalDomainName是S3的REST API域名,而非网站端点域名,这是解决类型不匹配的核心。
  • 策略修正:之前的策略错误地把资源设为OAC的ID,应该是桶内所有对象的路径${bucket.bucketArn}/*;同时AWS:SourceArn需要完整的分发ARN格式,不能只填分发ID。
  • 清理OAI:确保CloudFront源没有绑定旧的OAI,通过清空OriginAccessIdentity字段避免冲突。

验证

修改后重新部署CDK栈,此时CloudFront源会正确指向S3 REST API端点,OAC关联正常,之前的错误就会消失。


内容的提问来源于stack exchange,提问作者jedi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 11:45:31