API Gateway Stage Variable Rejected in IntegrationUri (Error: Invalid lambda function)

0

I am using CloudFormation to attempt to set up "stage" and "prod" API Gateway stages with Lambda integration (one lambda per stage to simplify deployment) to URLs as follows:

  • stage: https://<api_id>.execute-api.us-east-1.amazonaws.com/stage/mfl-scoring
  • prod: https://<api_id>.execute-api.us-east-1.amazonaws.com/prod/mfl-scoring

The relevant parts of my CF template are as follows:

  MflScoringStageFunction:
    Type: AWS::Lambda::Function
    Properties:
      Role: !GetAtt MflScoringStagedFunctionIamRole.Arn
      Code: 
        S3Bucket: !Sub ${BuildBucket}
        S3Key: builds/bootstrap.zip
        # S3ObjectVersion: TODO
      Handler: bootstrap
      Runtime: provided.al2
      MemorySize: 128
      Timeout: 5

  MflScoringProdFunction:
    Type: AWS::Lambda::Function
    Properties:
      Role: !GetAtt MflScoringStagedFunctionIamRole.Arn
      Code: 
        S3Bucket: !Sub ${BuildBucket}
        S3Key: builds/bootstrap.zip
        # S3ObjectVersion: TODO
      Handler: bootstrap
      Runtime: provided.al2
      MemorySize: 128
      Timeout: 5

  MflScoringFunctionStageAlias:
    Type: AWS::Lambda::Alias
    Properties:
      FunctionName:
        Ref: MflScoringStageFunction
      FunctionVersion: "$LATEST"
      Name: STAGE
      
  MflScoringFunctionProdAlias:
    Type: AWS::Lambda::Alias
    Properties:
      FunctionName:
        Ref: MflScoringProdFunction
      FunctionVersion: "$LATEST"
      Name: PROD

  MflScoringFunctionStagePermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      FunctionName: !Ref MflScoringFunctionStageAlias
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:MflScoringApi/*"

  MflScoringFunctionProdPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      FunctionName: !Ref MflScoringFunctionProdAlias
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:MflScoringApi/*"

  MflScoringStageFunctionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      FunctionName: !GetAtt MflScoringStageFunction.Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        !Sub 
          - "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MflScoringApi}/*"
          - MflScoringApi: !Ref MflScoringApi

  MflScoringProdFunctionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      FunctionName: !GetAtt MflScoringProdFunction.Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        !Sub 
          - "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MflScoringApi}/*"
          - MflScoringApi: !Ref MflScoringApi

  MflScoringApi:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Name: MFL Scoring API
      ProtocolType: HTTP

  MflScoringIntegration:
    Type: AWS::ApiGatewayV2::Integration
    DependsOn:
      - MflScoringStageFunction
      - MflScoringProdFunction
      - MflScoringApiStageStage
      - MflScoringApiStageProd
    Properties:
      ApiId: !Ref MflScoringApi
      Description: Lambda proxy integration
      IntegrationType: AWS_PROXY
      IntegrationMethod: POST
      PayloadFormatVersion: "2.0"
      IntegrationUri: !Sub 'arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${!stageVariables.LambdaFunction}:${!stageVariables.LambdaAlias}/invocations'

  MflScoringApiRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref MflScoringApi
      RouteKey: "GET /mfl-scoring"
      Target: !Join
        - /
        - - integrations
          - !Ref MflScoringIntegration

  MflScoringApiStageStage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      ApiId: !Ref MflScoringApi
      DefaultRouteSettings:
        DetailedMetricsEnabled: True
      StageName: stage
      StageVariables:
        LambdaAlias: STAGE
        LambdaFunction: !GetAtt MflScoringStageFunction.Arn
      AutoDeploy: true

  MflScoringApiStageProd:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      ApiId: !Ref MflScoringApi
      DefaultRouteSettings:
        DetailedMetricsEnabled: True
      StageName: prod
      StageVariables:
        LambdaAlias: PROD
        LambdaFunction: !GetAtt MflScoringProdFunction.Arn
      AutoDeploy: true

Stage variables appear in the console as follows:

Stage "stage":

  • Key | Value
  • LambdaAlias | STAGE
  • LambdaFunction | arn:aws:lambda:us-east-1:123412341234:function:mfl-scoring-http-MflScoringStageFunction-cgdT1EMOrMbd

Stage "prod":

  • Key | Value
  • LambdaAlias | PROD
  • LambdaFunction | arn:aws:lambda:us-east-1:123412341234:function:mfl-scoring-http-MflScoringProdFunction-vZajLTdguZE7

The CloudTrail record for the failure is as follows:

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "IAMUser",
        "principalId": "xxxx",
        "arn": "arn:aws:iam::xxxx:user/sam-user",
        "accountId": "xxxx",
        "accessKeyId": "xxxx",
        "userName": "sam-user",
        "sessionContext": {
            "sessionIssuer": {},
            "webIdFederationData": {},
            "attributes": {
                "creationDate": "2023-10-17T19:51:06Z",
                "mfaAuthenticated": "false"
            }
        },
        "invokedBy": "cloudformation.amazonaws.com"
    },
    "eventTime": "2023-10-17T19:51:11Z",
    "eventSource": "apigateway.amazonaws.com",
    "eventName": "UpdateIntegration",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "cloudformation.amazonaws.com",
    "userAgent": "cloudformation.amazonaws.com",
    "errorCode": "BadRequestException",
    "requestParameters": {
        "integrationMethod": "POST",
        "requestTemplates": {},
        "integrationType": "AWS_PROXY",
        "requestParameters": {},
        "integrationId": "xxxx",
        "description": "Lambda proxy integration",
        "payloadFormatVersion": "2.0",
        "integrationUri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${stageVariables.LambdaFunction}:${stageVariables.LambdaAlias}/invocations",
        "apiId": "xxxx"
    },
    "responseElements": {
        "message": "Invalid lambda function"
    },
    "requestID": "05af4104-df20-4916-a615-358084301c05",
    "eventID": "61184f3d-c578-45f9-b4b7-2ac71d8b5f8f",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "xxxx",
    "eventCategory": "Management"
}

The error in the CloudFormation console is:

Invalid lambda function (Service: AmazonApiGatewayV2; Status Code: 400; Error Code: BadRequestException; Request ID: fa527627-91b7-4e0e-900a-2ca4ae50e9f7; Proxy: null)

What do I need to do to make ApiGatewayV2 recognize that IntegrationURI as legitimate per the AWS docs (https://docs.aws.amazon.com/apigateway/latest/developerguide/aws-api-gateway-stage-variables-reference.html#stage-variables-in-integration-lambda-functions)?

1回答
0

Turns out it was a syntax issue with variable replacement. This fixed it:

        - ''
        - - 'arn:aws:apigateway:'
          - !Ref "AWS::Region"
          - ':lambda:path/2015-03-31/functions/arn:aws:lambda:'
          - !Ref "AWS::Region"
          - ':'
          - !Ref "AWS::AccountId"
          - ':function:${stageVariables.LambdaFunction}:${stageVariables.LambdaAlias}/invocations'

Of course now I get "message "Internal Server Error"" without the lambda being invoked and no way to effectively troubleshoot due to HTTP APIs having no internal tracing. Good times. (not)

回答済み 7ヶ月前

ログインしていません。 ログイン 回答を投稿する。

優れた回答とは、質問に明確に答え、建設的なフィードバックを提供し、質問者の専門分野におけるスキルの向上を促すものです。

質問に答えるためのガイドライン

関連するコンテンツ