Pat Needham
Pat Needham

Reputation: 5638

CloudFormation API Gateway Lambda integration request not getting right permissions?

I have a CloudFormation stack template that creates an API Gateway resource where the method is of Type: LAMBDA_PROXY. It initially works fine for accessing the root domain, for example https://28af295f439b5f0aef7c7805864ba3981f282e1e.guacchain.com/ - but when I try accessing https://28af295f439b5f0aef7c7805864ba3981f282e1e.guacchain.com/about the network request gives back status code 500 and response {"message": "Internal server error"}

The generated Lambda function has this as its Resource-based Policy:

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "stack-28af295f439b5f0aef7c7805864ba3981f282e1e-lambdaApiGatewayInvoke-128TRSSUE8WDQ",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:378688096774:function:lambda-28af295f439b5f0aef7c7805864ba3981f282e1e",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:execute-api:us-east-1:378688096774:bccwb0kvvd/*/*/*"
        }
      }
    }
  ]
}

When going to the API Gateway Integration Request page and simply editing the Lambda Function field (cutting the existing value then pasting it back, then hitting the checkmark), I get this "Add permission" popup: enter image description here

After clicking OK and then refreshing the Lambda console page, its Resource-base Policy updates to include two seemingly duplicate statements (only difference being the Sid field):

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "stack-28af295f439b5f0aef7c7805864ba3981f282e1e-lambdaApiGatewayInvoke-128TRSSUE8WDQ",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:378688096774:function:lambda-28af295f439b5f0aef7c7805864ba3981f282e1e",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:execute-api:us-east-1:378688096774:bccwb0kvvd/*/*/*"
        }
      }
    },
    {
      "Sid": "d6d795d4-8461-4774-bd6e-ae8d8ea3bcee",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:378688096774:function:lambda-28af295f439b5f0aef7c7805864ba3981f282e1e",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:execute-api:us-east-1:378688096774:bccwb0kvvd/*/*/*"
        }
      }
    }
  ]
}

After deploying the API Gateway and waiting about a minute, https://28af295f439b5f0aef7c7805864ba3981f282e1e.guacchain.com/about finally becomes accessible. So my question is, what's inadequate with the original Lambda Resource-based Policy that prevents all requests except for the / one to be accessed on the domain?

One subtle note I want to point out is that after cutting the Lambda function name and pasting it on the Integration Request page, it doesn't show as an autocomplete option, while others do.

This is the lambdaIAMRole I have defined in the CloudFormation stack:

  lambdaIAMRole:
    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:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Effect: Allow
                Resource:
                  - !Sub >-
                    arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${lambdaFunctionName}:*
          PolicyName: lambda

And the Lambda function resource has Role: !GetAtt lambdaIAMRole.Arn as part of its Properties field.

Upvotes: 4

Views: 808

Answers (1)

Marcin
Marcin

Reputation: 238727

Based on the comments and inspection of the CloudFormation template, it was found that the issue was caused by the incorrect setup of IntegrationHttpMethod in apiGatewayLambdaResourceMethod.

Instead of

IntegrationHttpMethod: GET

it should be

IntegrationHttpMethod: POST

This is because AWS_PROXY for lambda requires POST method, not GET.

Upvotes: 2

Related Questions