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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions