Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS API Gateway and Lambda function deployed through terraform -- Execution failed due to configuration error: Invalid permissions on Lambda function

I'm deploying an API gateway and a Lambda function together through Terraform, and the Lambda function is meant to be triggered by the API Gateway. After the resources successfully deploy, I test the API Gateway and I get response:

{ "message": "Internal server error" } .

The actual logs of the API gateway say:

Execution failed due to configuration error: Invalid permissions on Lambda function

I can get the actual api-lambda functionality to work by going to the integration request section of the API gateway, reselecting my existing function, and "saving" it again with the little checkmark, but this breaks automation and I want this to work without having to do that manual step every time. Not sure if this is a bug in Terraform/AWS or if I'm doing something wrong. (Found someone asking the same question but using SAM but no responses: Execution failed due to configuration error: Invalid permissions on Lambda function)

My current setup is deploying the API via a swagger json file, and the Lambda Invoke ARN is used as the URI in the integration section of this file. I have tried switching this between a hard coded ARN and a variable to no avail. I also tried including an aws_api_gateway_deployment and aws_api_gateway_integration resource but I figured that if I'm already using a swagger file, using those would conflict with what the swagger file is already building.

My main.tf for my api_gateway module looks like this:

resource "aws_api_gateway_rest_api" "post_session" {
    name = "${var.api_gateway_name}"
    body = "${data.template_file.post-session.rendered}"

    endpoint_configuration {
        types = ["PRIVATE"]
    }
}

data "template_file" "post-session" {
    template = "${file("../source/aapt-ual-post-session-v1-swagger-apigateway.json")}"

    vars {
        session_init_arn = "${var.session_init_function_arn}"
    }
}

My relevant section of the swagger file looks like this:

"x-amazon-apigateway-integration": {
      "uri": "${session_init_arn}",
      "responses": {
        "default": {
          "statusCode": "200"
        }
      },
      "requestTemplates": {
        "application/json":  ....

And my lambda_permission/api_gateway trigger section of my Lambda module looks like this:

resource "aws_lambda_permission" "post_session_trigger" {
     statement_id  = "Allow_My_Post_Session_Invoke"
     action        = "lambda:InvokeFunction"
     function_name = "${aws_lambda_function.init_function.function_name}"
     principal     = "apigateway.amazonaws.com"
     source_arn = "arn:aws:execute-api:us-east-1:${var.account_id}:${var.post_session_id}/v1/POST/aa/ual/session"

}

Let me know if you have any suggestions, thanks!

like image 857
transposeglobal Avatar asked Feb 22 '19 21:02

transposeglobal


2 Answers

As per the suggestion from Denis Weerasiri, I checked the Lambda permissions after reselecting the Lambda function name in the Integration section of the API Gateway, and it had added another policy. The change that I needed to make was changing the v1 to a * in the source_arn in the Lambda function resource. So the new API Gateway trigger in my Lambda module looks like this:

resource "aws_lambda_permission" "post_session_trigger" {
     statement_id  = "Allow_My_Post_Session_Invoke"
     action        = "lambda:InvokeFunction"
     function_name = "${aws_lambda_function.init_function.function_name}"
     principal     = "apigateway.amazonaws.com"
     source_arn = "arn:aws:execute-api:us-east-1:${var.account_id}:${var.post_session_id}/*/POST/aa/ual/session"}
like image 61
transposeglobal Avatar answered Oct 12 '22 16:10

transposeglobal


I had a similar problem and was using Terraform. It needed the policy with the "POST" in it. For some reason the /*/ (wildcard) policy didn't work?

Here's the policy and the example terraform I used to solve the issue.

Many thanks to all above.

Here is what my Lambda function policy JSON looked like and the terraform:

    {
      "Version": "2012-10-17",
      "Id": "default",
      "Statement": [
        {
          "Sid": "AllowAPIGatewayInvoke",
          "Effect": "Allow",
          "Principal": {
            "Service": "apigateway.amazonaws.com"
          },
          "Action": "lambda:InvokeFunction",
          "Resource": "arn:aws:lambda:us-east-1:999999999999:function:MY-APP",
          "Condition": {
            "ArnLike": {
              "AWS:SourceArn": "arn:aws:execute-api:us-east-1:999999999999:d85kyq3jx3/test/*/MY-APP"
            }
          }
        },
        {
          "Sid": "e841fc76-c755-43b5-bd2c-53edf052cb3e",
          "Effect": "Allow",
          "Principal": {
            "Service": "apigateway.amazonaws.com"
          },
          "Action": "lambda:InvokeFunction",
          "Resource": "arn:aws:lambda:us-east-1:999999999999:function:MY-APP",
          "Condition": {
            "ArnLike": {
              "AWS:SourceArn": "arn:aws:execute-api:us-east-1:999999999999:d85kyq3jx3/*/POST/MY-APP"
            }
          }
        }
      ]
    }

    add in a terraform like this:


    //************************************************
    // allows you to read in the ARN and parse out needed info, like region, and account
    //************************************************
    data "aws_arn" "api_gw_deployment_arn" {
        arn = aws_api_gateway_deployment.MY-APP_deployment.execution_arn 
    }

    //************************************************
    // Add in this to support API GW testing in AWS Console.
    //************************************************
    resource "aws_lambda_permission" "apigw-post" {
        statement_id  = "AllowAPIGatewayInvokePOST"
        action        = "lambda:InvokeFunction"
        //function_name = aws_lambda_function.lambda-MY-APP.arn
        function_name = module.lambda.function_name
        principal     = "apigateway.amazonaws.com"

        // "arn:aws:execute-api:us-east-1:473097069755:708lig5xuc/dev/POST1/cloudability-church-ws"
        source_arn = "arn:aws:execute-api:${data.aws_arn.api_gw_deployment_arn.region}:${data.aws_arn.api_gw_deployment_arn.account}:${aws_api_gateway_deployment.MY-APP_deployment.rest_api_id}/*/POST/${var.api_gateway_root_path}"
    }
like image 29
atom88 Avatar answered Oct 12 '22 16:10

atom88