Multiple IAM roles per function

I am defining custom IAM roles and would like each function to be assigned to one or more of them. So for instance, my “functions” block in the serverless.yml is:

functions:
      receiver:
        description: Receives events from clients and place into an SQS queue.
        handler: lib/receiver.handler
        role: 
          - defaultRole
          - queuePublisher
        events:
          - http: POST logger

      event-manager:
        description: Checks the event queue for message depth and then invokes an appropriate number of "processors" to drain the queue.
        handler: lib/event-manager.handler
        role: 
          - defaultRole
          - functionInvoker
          - queueMeta
        events:
          - schedule:
              rate: rate(1 minute)
              enabled: true

I’ve left out the actual role definitions for brevity’s sake but there are no reported errors on them (anymore) and instead is complaining about having more than one role:

Unsupported role provided: “[“defaultRole”,“queuePublisher”]”

Is there any way around this?

In thinking about this, maybe the answer is that I need to define modular “policies” and then have the various roles be the possible groupings of these policies. Does this make sense? Has anyone done this?

You are correct in thinking you need to define things in terms of IAM Policies, not Roles.

A Lambda function can only have one Role. A Role can (and usually does) have multiple Policies attached to it.

When defined separately, Policies can be attached to multiple Roles.

AWS provides a bunch of commonly-used Policies that are called Managed Policies, which should cover a vast majority of your use-cases. A Role can also have Inline Policies i.e. policies that only exist for that role. Here’s the relevant docs.

1 Like

Thanks @rowanu. Do you know of any good YAML examples of a serverless config that weaves this together?

I’m imagining that a policy definition in serverless config might look like this:

resources:
  Resources:
    loggingPermission:
      Type: AWS::IAM::Policy
      Statement: 
        - Effect: Allow
          Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents
          Resource: arn:aws:logs:${self:provider.region}:${accountId}:log-group:/aws/lambda/*:*:*

Is that right?

Hmm, not quite. If you’re extending the default function role in Serverless then you can just define the policy statements (which is what you did in your snippet).

If you’re defining the CFN resource in the resources section, you need the whole object; Check the CFN IAM Policy docs. A full IAM Policy resource would look like:

resources:
  Resources:
    LoggingPermissionPolicy:
      Type: AWS::IAM::Policy
      Properties:
        PolicyName: LoggingPermission
        PolicyDocument:
          Version: 2012-10-17
          Statement:
            - Effect: Allow
              Action:
                - logs:CreateLogGroup
                - logs:CreateLogStream
                - logs:PutLogEvents
              Resource: arn:aws:logs:${self:provider.region}:${accountId}:log-group:/aws/lambda/*:*:*
        Roles:
          - Ref: MyRole

Here I’m using the CFN Ref function to link the Policy and Role.

You could also define the Policy in the Role (i.e. the other direction to the example above), see the CFN Policies property in the IAM Role docs

1 Like

Yes my first stab at it was a bit of a fumble but I did eventually end up with something nearly identical to what you suggested. Unfortunately then I ran into another issue:

Policy creation works ... but does it?