StackEngine

How to Fix API Gateway Lambda Execution Role Missing Permissions (lambda:InvokeFunction Error)

Threat/Impact Level: HIGH | Exploitability/Downtime Risk: HIGH | Time to Fix: 5 mins

TL;DR

  • What broke: API Gateway's execution role (or the Lambda resource-based policy) is missing lambda:InvokeFunction, causing every API call to return 500 Internal Server Error with AccessDeniedException in CloudWatch.
  • How to fix it: Either add lambda:InvokeFunction to the API Gateway IAM execution role scoped to the target Lambda ARN, or add a Lambda resource-based policy granting apigateway.amazonaws.com invoke rights.
  • Fast path: Use our Client-Side Sandbox above to auto-refactor this — paste your IAM policy or Terraform aws_iam_policy_document block and get the corrected output instantly.

The Incident (What Does the Error Mean?)

Raw error surfaced in CloudWatch Logs for the API Gateway stage:

{
  "message": "Wed, 05 Jun 2024 14:22:11 GMT : Execution failed due to configuration error: 
              Invalid permissions on Lambda function",
  "status": 500
}

And in the Lambda invocation log or X-Ray trace:

User: arn:aws:sts::123456789012:assumed-role/APIGatewayExecutionRole/AmazonAPIGateway-my-api
is not authorized to perform: lambda:InvokeFunction 
on resource: arn:aws:lambda:us-east-1:123456789012:function:my-function
because no identity-based policy allows the lambda:InvokeFunction action

Immediate consequence: 100% of requests to this API stage fail. No traffic reaches Lambda. The API is fully down.


The Attack Vector / Blast Radius

This is a misconfiguration causing a full service outage, not a security vulnerability in the traditional sense — but the blast radius is total for the affected API stage.

Cascading failure chain:

  1. API Gateway attempts to assume its execution role and call lambda:InvokeFunction.
  2. IAM denies the call — implicit deny wins over any resource-based policy that may exist.
  3. API Gateway returns 500 to the client. No retry logic at the gateway layer rescues this.
  4. If this API backs a downstream service (e.g., a mobile app, a webhook receiver, a B2B integration), all dependent systems fail simultaneously.

Why this happens in production unexpectedly:

  • Terraform aws_lambda_permission resource was removed or never applied.
  • The Lambda function was redeployed with a new ARN (e.g., alias or version change) and the permission was not updated.
  • IAM role was rotated or recreated during a security remediation and the lambda:InvokeFunction statement was dropped.
  • Cross-account Lambda invocation where the resource-based policy principal is wrong.

How to Fix It (The Solution)

There are two valid trust models for API Gateway invoking Lambda. Use one, not both inconsistently.

This grants API Gateway permission at the Lambda resource level. No changes to the execution role needed.

AWS CLI:

- # No resource-based policy exists — Lambda rejects the invocation
+ aws lambda add-permission \
+   --function-name my-function \
+   --statement-id apigateway-invoke-permission \
+   --action lambda:InvokeFunction \
+   --principal apigateway.amazonaws.com \
+   --source-arn "arn:aws:execute-api:us-east-1:123456789012:abc123def4/*/POST/my-resource"

Terraform (Enterprise Best Practice — scope to exact method/path ARN):

- resource "aws_lambda_permission" "apigw" {
-   statement_id  = "AllowAPIGatewayInvoke"
-   action        = "lambda:InvokeFunction"
-   function_name = aws_lambda_function.my_function.function_name
-   principal     = "apigateway.amazonaws.com"
-   # MISSING: source_arn — allows ANY API Gateway in the account to invoke
- }
+ resource "aws_lambda_permission" "apigw" {
+   statement_id  = "AllowAPIGatewayInvoke"
+   action        = "lambda:InvokeFunction"
+   function_name = aws_lambda_function.my_function.function_name
+   principal     = "apigateway.amazonaws.com"
+   source_arn    = "${aws_api_gateway_rest_api.my_api.execution_arn}/*/*"
+ }

Option B — IAM Execution Role Policy (When Using IAM Auth on the Integration)

If your API Gateway integration type is AWS with credentials pointing to an IAM role:

  {
    "Version": "2012-10-17",
    "Statement": [
-     {
-       "Effect": "Allow",
-       "Action": "lambda:*",
-       "Resource": "*"
-     }
+     {
+       "Effect": "Allow",
+       "Action": "lambda:InvokeFunction",
+       "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function"
+     }
    ]
  }

The - example above also shows a common over-permissioning anti-pattern (lambda:* on *) that passes IAM Access Analyzer but violates least privilege. Lock it to the exact function ARN and lambda:InvokeFunction only.


💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure Client-Side WASM utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.


Prevention in CI/CD

1. Checkov — catch missing source_arn on Lambda permissions:

# .checkov.yml
checks:
  - CKV_AWS_45   # Ensure Lambda function has a resource-based policy
  - CKV_AWS_116  # Ensure Lambda permission has source_arn condition

2. OPA/Conftest policy — enforce source_arn is always set:

package terraform.aws.lambda_permission

deny[msg] {
  r := input.resource.aws_lambda_permission[name]
  not r.source_arn
  msg := sprintf("aws_lambda_permission.%v must define source_arn to prevent confused deputy attacks", [name])
}

3. Terraform plan validation in CI:

# In your GitHub Actions / GitLab CI pipeline
terraform plan -out=tfplan
checkov -f tfplan --framework terraform_plan --check CKV_AWS_116

4. AWS Config Rule — continuous compliance: Enable lambda-function-public-access-prohibited and write a custom Config rule that alerts when any Lambda function has Principal: "*" without a Condition block scoping the aws:SourceArn.

5. Integration test in pipeline: After terraform apply in staging, run a smoke test that actually invokes the API endpoint and asserts HTTP 200. A missing permission is caught in staging, not prod.

Related Diagnostics

"Part of the Security Utility Matrix."

View all 140 Security Tools →