CDK使用CustomResource调用Lambda报无InvokeFunction权限如何解决
报错根因
该错误是AwsCustomResource自身的执行IAM角色缺少目标Lambda函数的lambda:InvokeFunction权限,你当前写法里指定ANY_RESOURCE未生效通常是因为FunctionName仅用了短名称,导致自动生成的权限策略和实际资源ARN匹配失败。
解决方案
根据Lambda是否在当前CDK栈内创建,分两种场景处理:
场景1:目标Lambda是当前栈内创建的资源
直接调用Lambda实例的grantInvoke方法为CustomResource角色授权即可,代码示例:
import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as cr from '@aws-cdk/custom-resources'; // 你栈内定义的Lambda资源示例 const myLambda = new lambda.Function(this, 'MyFunction', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromAsset('lambda'), functionName: 'my-function' }); const callLambda = new cr.AwsCustomResource(this, 'MyCustomResource', { onCreate: { service: 'Lambda', action: 'invoke', region: 'us-east-1', // 注意修正Date.now的调用写法,原代码未加括号会导致物理ID固定 physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString()), parameters: { FunctionName: myLambda.functionArn, // 优先用ARN而非短名,避免匹配问题 Payload: '{}' }, }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: [myLambda.functionArn] }) }); // 手动授权,确保权限生效 myLambda.grantInvoke(callLambda.getRole()!);
场景2:目标Lambda是已存在的外部资源
先导入Lambda引用,再配置权限,代码示例:
import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as cr from '@aws-cdk/custom-resources'; import * as iam from 'aws-cdk-lib/aws-iam'; // 导入已存在的Lambda,替换为你实际的Lambda ARN const existingLambda = lambda.Function.fromFunctionArn(this, 'ImportedLambda', 'arn:aws:lambda:us-east-1:<你的账号ID>:function:my-function' ); const callLambda = new cr.AwsCustomResource(this, 'MyCustomResource', { onCreate: { service: 'Lambda', action: 'invoke', region: 'us-east-1', physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString()), parameters: { FunctionName: existingLambda.functionArn, Payload: '{}' }, }, // 直接手动指定策略,不依赖自动生成,避免匹配问题 policy: cr.AwsCustomResourcePolicy.fromStatements([ new iam.PolicyStatement({ actions: ['lambda:InvokeFunction'], resources: [existingLambda.functionArn], effect: iam.Effect.ALLOW }) ]) }); existingLambda.grantInvoke(callLambda.getRole()!);
注意事项
- 原代码中
Date.now.toString()未调用Date.now(),会导致物理资源ID固定为函数本身的序列化字符串,栈更新时不会重新触发Lambda调用,需要修正为Date.now().toString() - 非必要不要使用
ANY_RESOURCE或者*作为资源范围,会导致权限过度开放,存在安全风险
内容的提问来源于stack exchange,提问作者Pharmakon
相关产品推荐
相关产品推荐

