SAM模板报错:authorizerUri中FunctionArn为null,请求协助排查
我在创建关联Lambda的API Gateway并附加JWT授权器时,API和Lambda创建流程均正常,但添加授权器配置后触发如下报错:
Error: Failed to create changeset for the stack: dev-device-management-api-stack, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: [/Resources/DeviceManagementApi/Type/Body/securityDefinitions/JwtAuthorizer/x-amazon-apigateway-authorizer/authorizerUri/Fn::Sub/1/FunctionArn] 'null' values are not allowed in templates
附带的SAM模板代码:
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Parameters: EnvironmentStackName: Type: String AllowedValues: - dev - prod Resources: DeviceManagementApi: Type: AWS::Serverless::Api Properties: Name: !Sub "${EnvironmentStackName}-device-management" StageName: "api" EndpointConfiguration: REGIONAL Auth: Authorizers: JwtAuthorizer: AuthorizationScopes: - scope IdentitySource: $request.header.Authorization JwtConfiguration: audience: - "my-audience" issuer: "https://issuer.clerk.accounts.dev" GetAllLocationsLambda: Type: AWS::Serverless::Function Properties: FunctionName: !Sub "${EnvironmentStackName}-lambda-locations-get-all" Handler: app.lambda_handler Runtime: python3.12 CodeUri: src/location/get-all/ MemorySize: 128 Timeout: 10 Role: !GetAtt DeviceApiLambdaExecutionRole.Arn Environment: Variables: STACK_NAME: !Ref EnvironmentStackName Events: GetAllLocationsApiEvent: Type: Api Properties: Path: /locations Method: GET RestApiId: !Ref DeviceManagementApi # Auth: # Authorizer: MyOauth2Authorizer DeviceApiLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${EnvironmentStackName}-lambda-device-api-execution-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: "sts:AssumeRole" ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: LambdaDynamoDBReadAccess PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - dynamodb:Scan - dynamodb:GetItem - dynamodb:PutItem - dynamodb:BatchGetItem - dynamodb:BatchWriteItem - dynamodb:ConditionCheckItem - dynamodb:PutItem - dynamodb:DescribeTable - dynamodb:DeleteItem - dynamodb:GetItem - dynamodb:Scan - dynamodb:Query - dynamodb:UpdateItem Resource: "*"
错误原因
该报错是因为你定义的JWT授权器缺少关键配置:SAM默认会尝试绑定Lambda授权器处理JWT验证,但你既没有指定自定义Lambda函数的ARN,也没有明确声明使用API Gateway托管式JWT授权器,导致模板生成时出现null值占位符,违反CloudFormation模板规则。
修复方案
有两种可行的修复方式,根据你的需求选择:
方式1:使用API Gateway托管式JWT授权器(推荐)
无需编写自定义Lambda,让API Gateway直接处理JWT签名、issuer和audience验证,只需在授权器配置中添加Type: JWT声明:
Auth: Authorizers: JwtAuthorizer: Type: JWT # 必须添加该声明,明确使用托管式JWT授权器 AuthorizationScopes: - scope IdentitySource: $request.header.Authorization JwtConfiguration: audience: - "my-audience" issuer: "https://issuer.clerk.accounts.dev"
方式2:绑定自定义Lambda授权器
如果你确实需要通过Lambda处理JWT验证逻辑,需在授权器配置中添加FunctionArn字段,指向你的授权器Lambda函数ARN:
Auth: Authorizers: JwtAuthorizer: AuthorizationScopes: - scope IdentitySource: $request.header.Authorization FunctionArn: !GetAtt YourJwtAuthorizerLambda.Arn # 替换为你的授权器Lambda ARN JwtConfiguration: audience: - "my-audience" issuer: "https://issuer.clerk.accounts.dev"
额外注意事项
- 使用托管式JWT授权器时,需确保
JwtConfiguration中的issuer和audience与身份提供商(如Clerk)的配置完全一致,否则会导致授权验证失败。 - 若启用了
AuthorizationScopes,需确保JWT令牌中包含对应的scope声明。
内容的提问来源于stack exchange,提问作者Eduard Grinberg

