7

Since a few days, AWS Lambdas can be exposed as web services directly without an API Gateway.

This works fine when setting up through the UI console, but I can’t seem to get it done with Cloudformation, because the resource policy is not attached with AuthType: NONE. And without the policy, I get "message": "Forbidden" from AWS when trying to access the Lambda through the function url.

My Lambda is the following:

exports.handler = async event => {
    return {
        statusCode: 200,
        body: JSON.stringify("Hello World")
    }
}

and here’s the CFN template:

AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  stackName:
    Type: String
  lambdaFile:
    Type: String
  lambdaBucket:
    Type: String

Resources:
  lambdaRole:
    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/${stackName}:*"
          PolicyName: "lambda"

  runtimeLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        S3Bucket: !Ref lambdaBucket
        S3Key: !Ref lambdaFile
      Environment:
        Variables:
          NODE_ENV: production
      FunctionName: !Sub "${stackName}-runtime"
      Handler: runtime.handler
      MemorySize: 128
      Role: !GetAtt lambdaRole.Arn
      Runtime: "nodejs14.x"
      Timeout: 5

  lambdaLogGroup:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Sub "/aws/${stackName}"
      RetentionInDays: 30

  runtimeLambdaUrl:
    Type: "AWS::Lambda::Url"
    Properties:
      AuthType: NONE
      TargetFunctionArn: !Ref runtimeLambdaFunction

Outputs:
  runtimeLambdaUrl:
    Value: !GetAtt runtimeLambdaUrl.FunctionUrl

The interesting thing is that I can add the policy through the UI console, and then it works.

Here’s the initial config screen for the function URL right after CFN deployment:

enter image description here

This is what I see when pushing the “Edit” button:

enter image description here

After clicking “Save”, I get the following (note the blue box):

enter image description here

Also, when I go into “Edit” mode again, I now see the following:

enter image description here

After that, the function can be accessed via its URL.

I tried to add the policy into my CFN stack, either standalone as AWS::IAM::Policy, but then it is not a resource-based policy or as an additional action on the lambdaRole. But in either case, I can’t add a Principal and the policy doesn’t have an effect.

Does anybody know how I can make a pure Clouformation deployment for a Lambda with a function URL? Or is this a bug in Cloudformation and/or Lambda?

3
  • Have you managed to solve this problem? any chance you could share the final template? Commented Jul 28, 2022 at 15:36
  • The solution posted by Marcin below is the correct one. Sorry, I can’t share the template as it has much more details and I would have to massively clean it up first. Commented Jul 28, 2022 at 17:37
  • yep tried that and did not worked neither, might be some other problem. Thanks anyway, Gonna stick to Api Gateway anyway, too much hassle configuring this 🤣 Commented Jul 28, 2022 at 18:58

1 Answer 1

6

Your template is missing AWS::Lambda::Permission, thus its does not work. You already know what the permissions should be based on AWS console inspection, so you have to recreate those permissions using AWS::Lambda::Permission. This allows you to specify FunctionUrlAuthType.

Sign up to request clarification or add additional context in comments.

2 Comments

I’ll be damned, that was it. The interesting thing is, I’ve transformed it from a stack using API Gateway, and I didn’t need a Permission resource there. (And I could swear I had looked at AWS::Lambda::Permission yesterday, but didn’t find anything related to FunctionUrl.) Anyway, thanks!
Could you share CFN template for the same? I tried to apply solution but didn't worked for me. May be I am missing something.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.