Allow any lambda to invoke lambda with resource policy?

Has anyone had any luck attaching a resource policy to a lambda to allow other lambdas to invoke it?

Basically, we have a lambda that is doing some basic logging type work and we want to allow any other lambda in our account to invoke it via an internal library without having to explicitly reference it in each lambda’s iamRoleStatements

I would have thought that this would have taken care of it, but my other lambdas running in the same account are still failing with error:

AccessDeniedException: User: arn:aws:sts::XXXXXX:assumed-role/chainioUpdShipEventsAdapter-dev-us-east-1-lambdaRole/chainioUpdShipEventsAdapter-dev-handler 
is not authorized to perform: 
lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:XXXXXX:function:chainioEventStreamWriter-dev-handler

Current resource setting in serverless.yml for chainioEventStreamWriter

resources:
  Resources:
    StreamWriterLambdaPermission:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName:
          Ref: HandlerLambdaFunction
        Action: 'lambda:invokeFunction'
        Principal: '*'
        SourceAccount: ${self:custom.${opt:stage}.aws_account}

Seems related to: Async Lambda invoke from another Lambda

2 Likes

Hi @bglick! So I did some testing with this, and I think the SourceAccount property is preventing it. From the docs, it says SourceAccount “is used for S3 and SES.”

That being said, I haven’t had any luck scoping to permissions down to my account. I’ve tried using the SourceArn property with something like arn:aws:lambda:us-east-1:<myId>:function:*. I also tried setting Principal: "lambda.amazonaws.com". Neither one worked.

1 Like

This sounds like a really bad use of one Lambda calling another Lambda. It would be better to implement logging as a library then use that inside your other Lambda’s without invoking a second Lambda. If you can’t do that then I would look at attaching your logging Lambda to a Kinesis stream and have the main Lambda put messages onto the stream when logging is required.

Yeah, I simplified the use case a bit.

We actually are using this to wrap a kinesis stream because we don’t want to leak the stream details into 50+ microservices which we would have to change if we decide to change the way we’re partitioning the stream or if we move to a different underlying implementation. Basically we want to have one service (Lambda) that the other services invoke and encapsulate the stream details in the single lambda.

The only way I could get this to work was with public access, i.e. Principal: *, which I quickly tried with a dummy lambda. As soon as I tried SourceArn or SourceAccount I hit the same AccessDenied error

This also seems to prevent cross-account lambda calling unless we assume a role in the target account