0

I am setting up an API HTTP Gateway (V2) with lambda integrations via Cloudformation, and everything has been working so far. I have 2 working integrations, but my third integration is not working: Everything looks fine from the API Gateway side (it lists the correct route with a link to the Lambda), but the API endpoint in the lambda is listed as "https://c59boisn2k.execute-api.eu-central-1.amazonaws.com/productionnull". When I try to call the route, it says "Not Found". The odd thing is that I am using the same template for all three integrations.

I was thinking it could be a "dependsOn" issue, but I think I have all the correct dependencies. I tried re-creating the stack from scratch and now two of the three functions say "null" in their URL while the API Gateway still states the correct routes. Can this be a 'dependsOn' problem?

Here's my template for a single integration:

{
  "Resources": {
    "api": {
      "Type": "AWS::ApiGatewayV2::Api",
      "Properties": {
        "Name": { "Ref": "AWS::StackName" },
        "ProtocolType": "HTTP",
        "CorsConfiguration": {
          "AllowMethods": ["*"],
          "AllowOrigins": ["*"]
        }
      }
    },

    "stage": {
      "Type": "AWS::ApiGatewayV2::Stage",
      "Properties": {
        "Description": { "Ref": "AWS::StackName" },
        "StageName": "production",
        "AutoDeploy": true,
        "ApiId": { "Ref": "api" },
        "AccessLogSettings": {
          "DestinationArn": {
            "Fn::GetAtt": ["stageLogGroup", "Arn"]
          }
        }
      }
    },

    "getSignedS3LambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::Sub": "${AWS::StackName}-getSignedS3"
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": ["lambda.amazonaws.com"]
              },
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "Policies": [
          {
            "PolicyName": "root",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Resource": "arn:aws:logs:*:*:*",
                  "Action": "logs:*"
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:*"],
                  "Resource": ["arn:aws:s3:::euromomo.eu/uploads/*"]
                }
              ]
            }
          }
        ]
      }
    },

    "getSignedS3Lambda": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": ["getSignedS3LambdaRole"],
      "Properties": {
        "FunctionName": {
          "Fn::Sub": "${AWS::StackName}-getSignedS3"
        },
        "Code": {
          "S3Bucket": { "Ref": "operationsS3Bucket" },
          "S3Key": { "Ref": "getSignedS3S3Key" }
        },
        "Runtime": "nodejs10.x",
        "Handler": "index.handler",
        "Role": { "Fn::GetAtt": ["getSignedS3LambdaRole", "Arn"] }
      }
    },

    "getSignedS3Permission": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": ["api", "getSignedS3Lambda"],
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": { "Ref": "getSignedS3Lambda" },
        "Principal": "apigateway.amazonaws.com",
        "SourceArn": {
          "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${api}/*/*"
        }
      }
    },

    "getSignedS3Integration": {
      "Type": "AWS::ApiGatewayV2::Integration",
      "DependsOn": ["getSignedS3Permission"],
      "Properties": {
        "ApiId": { "Ref": "api" },
        "IntegrationType": "AWS_PROXY",
        "IntegrationUri": {
          "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${getSignedS3Lambda.Arn}/invocations"
        },
        "PayloadFormatVersion": "2.0"
      }
    },

    "getSignedS3Route": {
      "Type": "AWS::ApiGatewayV2::Route",
      "DependsOn": ["getSignedS3Integration"],
      "Properties": {
        "ApiId": { "Ref": "api" },
        "RouteKey": "POST /getSignedS3",
        "AuthorizationType": "NONE",
        "Target": { "Fn::Sub": "integrations/${getSignedS3Integration}" }
      }
    }
  }
}

1 Answer 1

0

After spending hours debugging this, I found that the problem was in my Lambda permission. I need to use the correct path in the permission.

This does not work:

arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${api}/*/*

This does work:

arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${api}/*/*/getSignedS3

I believe I could scope it even more to this:

arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${api}/*/POST/getSignedS3

This fixed all my problems and shows the correct path in the lambda web console.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.