amazon-web-servicesaws-lambdaaws-cloudformation

AWS Lambda Function Trigger API Gateway Issue


I created a cloudformation yml file to create a stack. Steps I took.

I went to cloudformation -> stacks -> create new stack

I upload the yml file and leave everything as default and just hit create. After created successfully, I go to the lambda function and when I click on the api gateway under triggers it shows this. I've tried many attempts to do so but it still does not work as expected.

template.yml

AWSTemplateFormatVersion: "2010-09-09"
Description: "My API Gateway and Lambda function"

Resources:
  SampleApi:
    Type: "AWS::ApiGateway::RestApi"
    Properties:
      Name: Sample

  SampleApiMethod:
    Type: "AWS::ApiGateway::Method"
    Properties:
      AuthorizationType: "NONE"
      HttpMethod: "GET"
      Integration:
        IntegrationHttpMethod: "GET" 
        Type: "AWS_PROXY"
        Uri: !Sub
          - "arn:aws:apigateway:${AWS::Region}:lambda:path/2024-01-21/functions/${lambdaArn}/invocations"
          - lambdaArn: !GetAtt "SampleLambda.Arn"
      RequestParameters:
        "method.request.path.parameter": "method.request.path.parameter"
      ResourceId: !GetAtt "SampleApi.RootResourceId"
      RestApiId: !Ref "SampleApi"

  SampleApiDeployment:
    Type: "AWS::ApiGateway::Deployment"
    DependsOn: "SampleApiMethod"
    Properties:
      RestApiId: !Ref "SampleApi"
      StageName: test

  SampleLambda:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        ZipFile: |
          def handler(event,context):
            return {
              'body': 'Hello, world!',
              'headers': {
                'Content-Type': 'text/plain'
              },
              'statusCode': 200
            }
      Handler: "index.handler"
      Role: !GetAtt "SampleLambdaRole.Arn"
      Runtime: python3.10

  LambdaApiGatewayInvoke:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt "SampleLambda.Arn"
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SampleApi}/*/GET/"

  SampleLambdaRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Action: ["sts:AssumeRole"]
            Effect: "Allow"
            Principal:
              Service: ["lambda.amazonaws.com"]
      Policies:
        - PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Action: ["cloudwatch:*", "logs:*"]
                Effect: "Allow"
                Resource: "*"
          PolicyName: "lambdaLogPolicy"

  SampleLambdaLogGroup:
    DependsOn: SampleLambda
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Sub "/aws/lambda/${SampleLambda}"

Lambda.1 Lambda.2

what I have done was I went back to the template.yml file and changed this section

Uri: !Sub
          - "arn:aws:apigateway:${AWS::Region}:lambda:path/2024-01-21/functions/${lambdaArn}/invocations"
          - lambdaArn: !GetAtt "SampleLambda.Arn"

to reflect the lambdaArn from the lambda function and then updated the stack by uploading existing template and it still gave me the same error.

I have no idea what the issue or solution is, any ideas?

Thanks!


Solution

  • Try this updated CloudFormation YAML:

    AWSTemplateFormatVersion: "2010-09-09"
    Description: "My API Gateway and Lambda function"
    
    Resources:
      # API Gateway
      SampleApi:
        Type: "AWS::ApiGateway::RestApi"
        Properties:
          Name: "SampleAPI"
    
      SampleResource:
        Type: "AWS::ApiGateway::Resource"
        Properties:
          ParentId: !GetAtt SampleApi.RootResourceId
          PathPart: "sample"
          RestApiId: !Ref SampleApi
    
      SampleApiMethod:
        Type: "AWS::ApiGateway::Method"
        Properties:
          AuthorizationType: "NONE"
          HttpMethod: "GET"
          Integration:
            IntegrationHttpMethod: "POST"
            Type: "AWS_PROXY"
            Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SampleLambda.Arn}/invocations"
          ResourceId: !Ref SampleResource
          RestApiId: !Ref SampleApi
    
      SampleApiDeployment:
        Type: "AWS::ApiGateway::Deployment"
        DependsOn: SampleApiMethod
        Properties:
          RestApiId: !Ref SampleApi
          StageName: "test"
    
      # Lambda Function
      SampleLambda:
        Type: "AWS::Lambda::Function"
        Properties:
          Code:
            ZipFile: |
              def handler(event, context):
                  return {
                      'statusCode': 200,
                      'body': 'Hello, world!',
                      'headers': {
                          'Content-Type': 'text/plain'
                      }
                  }
          Handler: "index.handler"
          Role: !GetAtt SampleLambdaRole.Arn
          Runtime: "python3.10"
    
      # Lambda Permission for API Gateway
      LambdaApiGatewayInvoke:
        Type: "AWS::Lambda::Permission"
        Properties:
          Action: "lambda:InvokeFunction"
          FunctionName: !Ref SampleLambda
          Principal: "apigateway.amazonaws.com"
          SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SampleApi}/test/GET/sample"
    
      # Lambda IAM Role
      SampleLambdaRole:
        Type: "AWS::IAM::Role"
        Properties:
          AssumeRolePolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Principal:
                  Service: "lambda.amazonaws.com"
                Action: "sts:AssumeRole"
          Policies:
            - PolicyName: "LambdaExecutionPolicy"
              PolicyDocument:
                Version: "2012-10-17"
                Statement:
                  - Effect: "Allow"
                    Action: ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
                    Resource: "*"
    
      # CloudWatch Logs
      SampleLambdaLogGroup:
        Type: "AWS::Logs::LogGroup"
        Properties:
          LogGroupName: !Sub "/aws/lambda/${SampleLambda}"