Skip to content

FunctionUrl with AuthType.NONE missing lambda:InvokeFunction permission — 403 on all Function URLs #98

@so0k

Description

@so0k

Bug Report

Description

FunctionUrl with authType: NONE only adds a lambda:InvokeFunctionUrl permission but is missing the required lambda:InvokeFunction permission. This causes all public Function URLs to return 403 Forbidden (AccessDeniedException).

Root Cause

In src/aws/compute/function-url.ts, when authType === NONE, only one permission is added:

props.function.addPermission("invoke-function-url", {
  principal: new iam.AnyPrincipal(),
  action: "lambda:InvokeFunctionUrl",
  functionUrlAuthType: props.authType,
});

The AWS Console adds two permission statements when creating a public Function URL:

Statement Action Condition
FunctionURLAllowPublicAccess lambda:InvokeFunctionUrl lambda:FunctionUrlAuthType: NONE
FunctionURLAllowInvokeAction lambda:InvokeFunction lambda:InvokedViaFunctionUrl: true

TerraConstructs only adds the first one.

Reproduction

const fn = new NodejsFunction(this, "Handler", { /* ... */ });
const url = fn.addFunctionUrl({ authType: FunctionUrlAuthType.NONE });
// Deploy → curl the function URL → 403 Forbidden

Direct invocation via aws lambda invoke works fine — the 403 only affects Function URL access.

Evidence

  • Verified resource policy has correct lambda:InvokeFunctionUrl with Principal: * and FunctionUrlAuthType: NONE condition
  • Created identical function via AWS Console with Function URL → works (HTTP 200)
  • Compared policies: Console adds both lambda:InvokeFunctionUrl AND lambda:InvokeFunction
  • Manually added lambda:InvokeFunction permission via CLI → immediately fixed the 403

AWS Documentation

From Control access to Lambda function URLs:

"When you use the AWS CLI, you must add the lambda:InvokeFunctionUrl and lambda:InvokeFunction statements separately."

Suggested Fix

Add a second permission in FunctionUrl constructor when authType === NONE:

if (props.authType === FunctionUrlAuthType.NONE) {
  props.function.addPermission("invoke-function-url", {
    principal: new iam.AnyPrincipal(),
    action: "lambda:InvokeFunctionUrl",
    functionUrlAuthType: props.authType,
  });
  // Required for public Function URLs to work
  props.function.addPermission("invoke-function-url-invoke", {
    principal: new iam.AnyPrincipal(),
    action: "lambda:InvokeFunction",
  });
}

Environment

  • TerraConstructs v0.2.3
  • AWS region: us-east-1
  • Terraform AWS provider
  • Node.js 22, ARM64 Lambda

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions