使用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
相关产品推荐
相关产品推荐

