serverless: !Join seems to be broken when using AWS::Lambda::Permission for Api Gateway

Are you certain it’s a bug?

  • Yes, it looks like a bug

Is the issue caused by a plugin?

  • It is not a plugin issue

Are you using the latest version?

  • Yes, I’m using the latest version

Is there an existing issue for this?

  • I have searched existing issues, it hasn’t been reported yet

Issue description

I’m not using any plugins.

Reproduction Repo: https://github.com/Schachte/ServerlessLambdaSetup

  RetrieveAllSubscribersLambdaPermissionApiGateway:
    Type: 'AWS::Lambda::Permission'
    Properties:
      FunctionName: { "Fn::GetAtt": [ RetrieveAllSubscribersLambdaFunction, Arn ] }
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: 
        Fn::Join: 
          - ""
          - - "helloworld"
            - "*"

The output is the following:

  An error occurred: RetrieveAllSubscribersLambdaPermissionApiGateway - 1 validation error detected: Value 'helloworld*:execute-api:us-west-2:185871347164:a53ihjk9/*/*' at 'sourceArn' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:(aws[a-zA-Z0-9-]*):([a-zA-Z0-9\-])+:([a-z]{2}((-gov)|(-iso(b?)))?-[a-z]+-\d{1})?:(\d{12})?:(.*) (Service: AWSLambda; Status Code: 400; Error Code: ValidationException; Request ID: 0646f60d41f; Proxy: null).

My question is, how is it possible for the random data in the error to still show up in the SourceArn if I only joined together the two strings above?

It seems like the join function in this case is making some assumption on what else should be injected in the value? Ideally, I just wanted to interpolate the logical id from a raw !Ref ApiGatewayRestApi

Service configuration (serverless.yml) content

Will post if necessary

Command name and used flags

sls deploy

Command output

See above

Environment information

Operating System:          darwin
     Node Version:              17.3.0
     Framework Version:         2.71.0 (local)
     Plugin Version:            5.5.3
     SDK Version:               4.3.0
     Components Version:        3.18.1

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 22

Most upvoted comments

@Schachte You need to update the resource policy. Take a look the serverless-api-gateway docs

Ah, that would make sense. I thought overriding the resource name in the other file would take precedence, but I must have been wrong. Ok, good to know. Looks like online there are some pretty weird behaviors using !sub and the ${} syntax in certain scenarios as well, so I can stick to join and the plugin, but was wondering why I was having such a hard time. Thanks again!

@Schachte I’m glad I could help 😃 Until the next one (hopefully not 😆 ) 🍻

@Schachte Glad to hear, the join syntax is actually different. I’ll also add both of these links on [the Stack Overflow thread] https://stackoverflow.com/questions/70727036/join-in-serverless-framework-is-broken?noredirect=1#comment125034330_70727036, so it can help someone else. I’m trying to find the documentation for the default names provided to resources by Serverless, that might expose the reason too.

Your original idea was right, it was a user error.

Working Solution Without Plugins

      SourceArn:
        'Fn::Join':
          - ''
          - - 'arn:'
            - !Ref 'AWS::Partition'
            - ':execute-api:'
            - !Ref 'AWS::Region'
            - ':'
            - !Ref 'AWS::AccountId'
            - ':'
            - !Ref ApiGatewayRestApi
            - /*/*

Abbreviated Syntax

      SourceArn:
        !Join
          - ''
          - - 'arn:'
            - !Ref 'AWS::Partition'
            - ':execute-api:'
            - !Ref 'AWS::Region'
            - ':'
            - !Ref 'AWS::AccountId'
            - ':'
            - !Ref ApiGatewayRestApi
            - /*/*

Had to reverse engineer the output json and convert to YAML from your plugin and it led me to this solution.

Thanks so much! Couldn’t have solved this one without you.

If anyone is reading this, would be curious to know why I can’t get !Sub to work. This deep into debugging, so curious:

        !Sub 
          - 'arn:aws:execute-api:us-west-2:${AWS::AccountId}:${GatewayId}/*/GET/users'
          - { GatewayId: !Ref ApiGatewayRestApi }

Alternatively, this fails with sub as well:

SourceArn: { "Fn::Sub": [ "arn:aws:execute-api:us-west-2:${AWS::AccountId}:${GatewayId}/*/GET/users", { "GatewayId": {"Ref" : "ApiGatewayRestApi" }} ]}

@Schachte Glad to hear, the join syntax is actually different. I’ll also add both of these links on [the Stack Overflow thread] https://stackoverflow.com/questions/70727036/join-in-serverless-framework-is-broken?noredirect=1#comment125034330_70727036, so it can help someone else. I’m trying to find the documentation for the default names provided to resources by Serverless, that might expose the reason too.

@Schacte That’s strange, looks like the SourceArn is being prepended. Worth taking a deeper look into.