AWS CDK跨栈Lambda与API Gateway权限配置报错求助
解决CDK跨栈授权时的Token构造ID错误
这个问题我之前踩过坑,根源是CDK自动生成IAM权限的构造ID时,引入了动态Token(跨栈引用的值属于Token类型),而CDK要求构造ID必须是静态字符串,不能包含Token,所以才会抛出Cannot use tokens in construct ID的错误。下面给你两种可行的解决方案:
方案一:在API Gateway栈中添加调用权限(推荐)
既然API Gateway需要调用Lambda,直接在API所在的栈里授权更合理,也能避开跨栈Token的问题。通常LambdaIntegration会自动创建调用权限,但如果跨栈导入Lambda时自动授权失效,手动添加即可:
import * as cdk from 'aws-cdk-lib'; import * as api from 'aws-cdk-lib/aws-apigateway'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as iam from 'aws-cdk-lib/aws-iam'; export class CustomerApiStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // 跨栈导入Service A的Lambda const queryTrackFunction = lambda.Function.import(this, 'TrackQueryServiceQueryTrackFunction', { functionArn: cdk.Fn.importValue('TrackQueryServiceStack:QueryTrackFunctionArn') }); const customerApi = new api.RestApi(this, 'CustomerAPI'); const tracks = customerApi.root.addResource('tracks'); // 创建Lambda集成 const lambdaIntegration = new api.LambdaIntegration(queryTrackFunction); tracks.addMethod('GET', lambdaIntegration); // 手动添加API Gateway调用Lambda的权限 queryTrackFunction.grantInvoke(new iam.ServicePrincipal('apigateway.amazonaws.com')); } }
这个方案的优势是不需要修改Service A的栈,权限逻辑和API放在一起,更符合单一职责。
方案二:在Service A栈中手动指定权限的构造ID
如果你一定要在Service A栈中提前授权给API Gateway,可以手动创建IAM Permission并指定静态构造ID,避免CDK自动生成带Token的ID:
import * as cdk from 'aws-cdk-lib'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as iam from 'aws-cdk-lib/aws-iam'; export class TrackQueryServiceStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // 定义你的Lambda函数 const queryTracksFunction = new lambda.Function(this, 'QueryTrackFunction', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromAsset('path/to/your/code'), // 其他配置... }); // 手动创建IAM权限,指定静态构造ID new iam.Permission(this, 'ApiGatewayInvokePermission', { action: 'lambda:InvokeFunction', principal: new iam.ServicePrincipal('apigateway.amazonaws.com'), function: queryTracksFunction, // 可选:限制仅特定API Gateway可以调用,更安全(需要从API栈导出ApiId并导入) // sourceArn: cdk.Arn.format({ // service: 'execute-api', // resource: cdk.Fn.importValue('CustomerApiStack:ApiId'), // resourceName: '*/*/*', // }, this) }); // 导出Lambda ARN给其他栈使用 new cdk.CfnOutput(this, 'QueryTrackFunctionArn', { value: queryTracksFunction.functionArn, exportName: 'TrackQueryServiceStack:QueryTrackFunctionArn' }); } }
这里关键是手动创建iam.Permission并指定了静态的构造ID(ApiGatewayInvokePermission),取代了grantInvoke自动生成的带Token的ID,从根源上解决了错误。
内容的提问来源于stack exchange,提问作者S73417H
相关产品推荐
相关产品推荐

