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

配置CloudFront触发Lambda遇503错误,求Terraform代码修复方案

CloudFront关联Lambda@Edge触发503错误的修复方案

问题现象

访问CloudFront分发域名时出现503错误:

503 ERROR
The request could not be satisfied.
The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.

现有Terraform代码

import { Construct } from 'constructs';
import { App, TerraformStack } from 'cdktf';
import { AwsProvider } from '@cdktf/provider-aws/lib/provider';
import { LambdaFunction } from '@cdktf/provider-aws/lib/lambda-function';
import { IamRole } from '@cdktf/provider-aws/lib/iam-role';
import { IamRolePolicyAttachment } from '@cdktf/provider-aws/lib/iam-role-policy-attachment';
import { S3Object } from '@cdktf/provider-aws/lib/s3-object';
import { CloudfrontDistribution } from '@cdktf/provider-aws/lib/cloudfront-distribution';

class MyStack extends TerraformStack {
    constructor(scope: Construct, id: string) {
        super(scope, id);

        new AwsProvider(this, 'AWS', {
            region: 'us-east-1',
            accessKey: '',
            secretKey: '',
        });

        const lambdaBucketName = '';
        const lambdaBucketKey = 'test.zip';

        const lambdaS3Object = new S3Object(this, 'LambdaS3Object', {
            bucket: lambdaBucketName,
            key: lambdaBucketKey,
            source: 'test.zip',
        });

        const lambdaRole = new IamRole(this, 'LambdaRole', {
            name: 'lambda-execution-role',
            assumeRolePolicy: JSON.stringify({
                Version: '2012-10-17',
                Statement: [
                    {
                        Action: 'sts:AssumeRole',
                        Effect: 'Allow',
                        Principal: {
                            Service: [
                                'lambda.amazonaws.com',
                                'edgelambda.amazonaws.com'
                            ]
                        },
                    },
                ],
            }),
        });

        new IamRolePolicyAttachment(this, 'LambdaBasicExecutionRole', {
            role: lambdaRole.name,
            policyArn: 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole',
        });

        const lambdaFunction = new LambdaFunction(this, 'LambdaFunction', {
            functionName: 'testing-la-lambda',
            role: lambdaRole.arn,
            handler: 'index.handler',
            runtime: 'nodejs18.x',
            s3Bucket: lambdaBucketName,
            s3Key: lambdaS3Object.key,
            publish: true,
        });

        new CloudfrontDistribution(this, 'CloudFrontDistribution', {
            origin: [{
                domainName: '',
                originId: 'test',
            }],
            defaultCacheBehavior: {
                allowedMethods: ['GET', 'HEAD', 'OPTIONS'],
                cachedMethods: ['GET', 'HEAD'],
                targetOriginId: 'test',
                viewerProtocolPolicy: 'redirect-to-https',
                lambdaFunctionAssociation: [{
                    eventType: 'viewer-request',
                    lambdaArn: lambdaFunction.qualifiedArn,
                }],
                forwardedValues: {
                    queryString: false,
                    cookies: {
                        forward: 'none',
                    },
                },
            },
            enabled: true,
            isIpv6Enabled: true,
            defaultRootObject: 'index.html',
            priceClass: 'PriceClass_100',
            restrictions: {
                geoRestriction: {
                    restrictionType: 'none',
                },
            },
            viewerCertificate: {
                cloudfrontDefaultCertificate: true,
            },
        });
    }
}

const app = new App();
new MyStack(app, 'my-app');
app.synth();

缺失的配置与修复方法

1. Lambda函数缺少资源策略(核心问题)

Lambda@Edge要求函数必须配置资源策略,允许CloudFront服务主体调用该函数。需要添加LambdaPermission资源,并通过DataAwsCallerIdentity获取当前AWS账号ID:

// 引入缺失的资源类型
import { LambdaPermission } from '@cdktf/provider-aws/lib/lambda-permission';
import { DataAwsCallerIdentity } from '@cdktf/provider-aws/lib/data-aws-caller-identity';

// 在AwsProvider后添加账号ID数据资源
const callerIdentity = new DataAwsCallerIdentity(this, 'CallerIdentity');

// 在lambdaFunction定义后添加权限配置
new LambdaPermission(this, 'LambdaEdgeInvokePermission', {
  action: 'lambda:InvokeFunction',
  functionName: lambdaFunction.functionName,
  principal: 'cloudfront.amazonaws.com',
  sourceArn: `arn:aws:cloudfront::${callerIdentity.accountId}:distribution/${cloudfrontDistribution.id}`,
  qualifier: lambdaFunction.version,
});

2. CloudFront Origin配置为空

代码中origin的domainName字段为空,这会导致CloudFront无法定位源站,必须填写有效的源站域名(如S3桶域名、自定义源站域名):

origin: [{
  domainName: 'your-actual-origin-domain.example.com', // 替换为真实源站域名
  originId: 'test',
}],

3. 验证Lambda包有效性

确认test.zip包含正确的代码结构,index.handler入口函数存在且能正常执行,避免因代码逻辑错误导致Lambda触发失败。

修复后的关键代码片段

// 添加账号ID数据资源
const callerIdentity = new DataAwsCallerIdentity(this, 'CallerIdentity');

// ... 其他原有代码不变 ...

const lambdaFunction = new LambdaFunction(this, 'LambdaFunction', {
  functionName: 'testing-la-lambda',
  role: lambdaRole.arn,
  handler: 'index.handler',
  runtime: 'nodejs18.x',
  s3Bucket: lambdaBucketName,
  s3Key: lambdaS3Object.key,
  publish: true,
});

// 添加Lambda@Edge调用权限
new LambdaPermission(this, 'LambdaEdgeInvokePermission', {
  action: 'lambda:InvokeFunction',
  functionName: lambdaFunction.functionName,
  principal: 'cloudfront.amazonaws.com',
  sourceArn: `arn:aws:cloudfront::${callerIdentity.accountId}:distribution/${cloudfrontDistribution.id}`,
  qualifier: lambdaFunction.version,
});

// 修复Origin配置
const cloudfrontDistribution = new CloudfrontDistribution(this, 'CloudFrontDistribution', {
  origin: [{
    domainName: 'your-actual-origin-domain', // 替换为真实源站
    originId: 'test',
  }],
  // ... 其他原有配置不变 ...
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:57:01