使用AWS Amplify与CDK创建自定义资源时部署失败求助
问题
尝试使用AWS Amplify结合AWS CDK创建自定义资源,并将现有Lambda函数作为事件处理程序。执行amplify push时资源创建失败,错误信息如下:
CREATE_FAILED custommyCustomResourceXXXX AWS::CloudFormation::Stack Parameters: [AssetParametersXXXX, .....] must have values
相关CDK代码:
import * as cdk from '@aws-cdk/core'; import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper'; import * as cr from "@aws-cdk/custom-resources"; import * as logs from "@aws-cdk/aws-logs"; import * as lambda from '@aws-cdk/aws-lambda'; import { AmplifyDependentResourcesAttributes } from "../../types/amplify-dependent-resources-ref" export class cdkStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) { super(scope, id, props); /* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */ new cdk.CfnParameter(this, 'env', { type: 'String', description: 'Current Amplify CLI env name', }); const dependencies: AmplifyDependentResourcesAttributes = AmplifyHelpers.addResourceDependency(this, amplifyResourceProps.category, amplifyResourceProps.resourceName, [{ category: "function", resourceName: "myFunction" }] ); const myFunctionArn = cdk.Fn.ref(dependencies.function.myFunction.Arn); const importedLambda = lambda.Function.fromFunctionArn(this, "importedLambda", myFunctionArn); const provider = new cr.Provider(this, "MyCustomResourceProvider", { onEventHandler: importedLambda, logRetention: logs.RetentionDays.ONE_DAY, }) new cdk.CustomResource(this, "MyCustomResource", { serviceToken: provider.serviceToken }) } }
问题原因与排查修复
核心原因
cr.Provider默认会生成辅助资源(如日志处理的Lambda层、辅助函数),这些资源依赖Asset参数注入部署值,但在Amplify集成场景下,直接使用外部导入的Lambda作为onEventHandler时,CDK无法正确传递这些参数,导致CloudFormation报错。cr.Provider设计上更适配当前栈内定义的Lambda资源,而非外部导入的资源。
修复方案
方案1:直接使用现有Lambda作为自定义资源的服务令牌
如果现有Lambda已实现自定义资源的处理逻辑(能接收并响应CloudFormation事件格式),可跳过cr.Provider,直接将Lambda ARN作为自定义资源的serviceToken:
import * as cdk from '@aws-cdk/core'; import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper'; import * as cr from "@aws-cdk/custom-resources"; import { AmplifyDependentResourcesAttributes } from "../../types/amplify-dependent-resources-ref" export class cdkStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) { super(scope, id, props); new cdk.CfnParameter(this, 'env', { type: 'String', description: 'Current Amplify CLI env name', }); const dependencies: AmplifyDependentResourcesAttributes = AmplifyHelpers.addResourceDependency(this, amplifyResourceProps.category, amplifyResourceProps.resourceName, [{ category: "function", resourceName: "myFunction" }] ); const myFunctionArn = cdk.Fn.ref(dependencies.function.myFunction.Arn); new cdk.CustomResource(this, "MyCustomResource", { serviceToken: myFunctionArn, // 按需传递自定义资源所需参数 properties: { Env: cdk.Fn.ref('env') } }) } }
方案2:在当前栈内定义Lambda(保留cr.Provider能力)
若需要cr.Provider提供的重试、日志管理等能力,可将现有Lambda的代码迁移到当前CDK栈内定义:
import * as cdk from '@aws-cdk/core'; import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper'; import * as cr from "@aws-cdk/custom-resources"; import * as logs from "@aws-cdk/aws-logs"; import * as lambda from '@aws-cdk/aws-lambda'; import { AmplifyDependentResourcesAttributes } from "../../types/amplify-dependent-resources-ref" export class cdkStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) { super(scope, id, props); new cdk.CfnParameter(this, 'env', { type: 'String', description: 'Current Amplify CLI env name', }); // 直接在当前栈内定义Lambda,指向现有代码目录 const myFunction = new lambda.Function(this, "MyFunction", { runtime: lambda.Runtime.NODEJS_18_X, handler: "index.handler", code: lambda.Code.fromAsset("../functions/myFunction"), // 替换为你的Lambda代码路径 }); const provider = new cr.Provider(this, "MyCustomResourceProvider", { onEventHandler: myFunction, logRetention: logs.RetentionDays.ONE_DAY, }) new cdk.CustomResource(this, "MyCustomResource", { serviceToken: provider.serviceToken }) } }
排查方法
- 查看Amplify生成的CloudFormation模板:进入
.amplify/backend/custom/你的资源名称目录,检查模板中是否存在未赋值的AssetParameters参数。 - 验证Lambda逻辑:手动触发
myFunction,传入模拟的CloudFormation自定义资源事件,确认其能返回符合要求的响应格式。 - 检查权限配置:确保Amplify部署角色有权限访问该Lambda,且Lambda自身具备执行所需操作的IAM权限。
内容的提问来源于stack exchange,提问作者ataravati
相关产品推荐
相关产品推荐

