Skip to content

Allow Role 'Fn::GetAtt' for Lambda role#3083

Merged
eahefnawy merged 1 commit intoserverless:masterfrom
erikerikson:allow-role-reference-in-func-role-attr
Jan 27, 2017
Merged

Allow Role 'Fn::GetAtt' for Lambda role#3083
eahefnawy merged 1 commit intoserverless:masterfrom
erikerikson:allow-role-reference-in-func-role-attr

Conversation

@erikerikson
Copy link
Contributor

@erikerikson erikerikson commented Jan 11, 2017

What did you implement:

Fixes #3081 by allowing the role defined for a Lambda to be a reference (e.g. { 'Fn::GetAtt', [ 'LambdaLogicalId', 'Arn'] }) to a role in the current service. If the role attribute is defined, check whether it is a role reference and if it is, fill the DependsOn attribute for the event mapping to be that logical ID.
Add tests that make sure this use case is covered in future incarnations of the code.

How did you implement it:

evaluate the role attribute (from either function or provider) and if it is a Fn::GetAtt to an ARN (which uses a LogicalId) use that logical ID as the value for DependsOn.

How can we verify it:

See tests in this PR. Alternatively, define a role in your service. Then use that role by reference by defining role on the provider and subsequently on the function. Deploy with both configurations.

Todos:

  • Write tests
  • Write documentation
  • Fix linting errors
  • Make sure code coverage hasn't dropped
  • Provide verification config/commands/resources
  • Enable "Allow edits from maintainers" for this PR
  • Change ready for review message below

Note that with regards to the documentation, this shouldn't be a change. I didn't check.

Is this ready for review?: YES
Is it a breaking change?: NO

Fix serverless#3081

The fix is to allow the role defined for a Lambda to be a `{ 'Fn::GetAtt', [ 'LambdaLogicalId', 'Arn'] }` reference to a role in the current service.  If the `role` attribute is defined, check whether it is a role reference and if it is, fill the depends on attribute for the event mapping to be that logical ID.
Add tests that make sure this use case is covered in future incarnations of the code.
@erikerikson
Copy link
Contributor Author

@pmuens @eahefnawy - Can we please consider this for the next release? I've been using it for a deploy and don't want my team to fall behind or off the official build. Thanks!

@pmuens
Copy link
Contributor

pmuens commented Jan 24, 2017

@erikerikson Thanks for the PR 👍 . Putting this into the v1.6 milestone...

@pmuens pmuens added this to the 1.6 milestone Jan 24, 2017
@erikerikson
Copy link
Contributor Author

Thanks @pmuens!

@pmuens pmuens requested review from eahefnawy and pmuens January 24, 2017 18:18
Copy link
Contributor

@pmuens pmuens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @erikerikson thanks for the PR!

I just gave it a spin today. Unfortunately I got the following error:

     An error occurred while provisioning your stack: HelloEventSourceMappingDynamodbTest
     - Cannot access stream arn:aws:dynamodb:us-east-1:XXXXX:table/test/stream/2017-01-25T13:33:32.098.
     Please ensure the role can perform the GetRecords, GetShardIterator,
     DescribeStream, and ListStreams Actions on your stream
     in IAM..

Here's the serverless.yml I'm using:

service: stream-test

provider:
  name: aws
  runtime: nodejs4.3
  cfLogs: true
  role:
    'Fn::GetAtt': [ 'test123', Arn ]

functions:
  hello:
    handler: handler.hello
    events:
      - stream: arn:aws:dynamodb:us-east-1:XXXXX:table/test/stream/2017-01-25T13:33:32.098
      - stream: arn:aws:kinesis:us-east-1:XXXXX:stream/test

resources:
  Resources:
    test123:
      Type: AWS::IAM::Role
      Properties:
        RoleName: test123
        Path: "/"
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: myPolicyName
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action:
                    - logs:CreateLogGroup
                    - logs:CreateLogStream
                    - logs:PutLogEvents
                  Resource: arn:aws:logs:us-east-1:XXXXX:log-group:/aws/lambda/*:*:*

Am I missing something? 🤔
Do you have a serverless.yml at hand we can use to validate this real quick?

@erikerikson
Copy link
Contributor Author

This is the serverless.yml that I've needed this change to deploy:

https://github.com/Nordstrom/hello-retail/blob/initial-formation/product-catalog/serverless.yml

Line 20 is specifically the allowance of this change.

You would also need to deploy its dependency (following) to successfully deploy the serverless.yml above.

https://github.com/Nordstrom/hello-retail/blob/initial-formation/retail-stream/serverless.yml

As for your serverless.yml, you are defining a role that is applied to your function. The error you see happens because your declaration of a role bypasses the usual automated rights generation that would build IamPolicyLambdaExecution (1.). You also omit the standard set of Lambda rights for reading off those streams from the custom role you have defined. Given your serverless.yml, you would want to add the following policies:

          - PolicyName: ReadFromDynamoDb
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: 'Allow'
                  Action:
                    - 'dynamodb:GetRecords'
                    - 'dynamodb:GetShardIterator'
                    - 'dynamodb:DescribeStream'
                    - 'dynamodb:ListStreams'
                  Resource: arn:aws:dynamodb:us-east-1:XXXXX:table/test/stream/2017-01-25T13:33:32.098
          - PolicyName: ReadFromKinesis
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: 'Allow'
                  Action:
                    - 'kinesis:GetRecords'
                    - 'kinesis:GetShardIterator'
                    - 'kinesis:DescribeStream'
                    - 'kinesis:ListStreams'
                  Resource: arn:aws:kinesis:us-east-1:XXXXX:stream/test
  1. Note that modifying a role provided at the provider or function level is considered inappropriate. Those means of supplying a role assert that the role is to be externally managed. The referenced role can be defined in the same service but it could also be imported or managed by a different team.

Copy link
Contributor

@pmuens pmuens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops. That's embarassing. Sorry for wasting your time @erikerikson 😞 I copied the role resource definition from some other location w/o thinking about it (damn it "copy and paste"!)...

You're 100% correct. Here's the serverless.yml I used to validate this PR (you can move the definition to the function level or provider level:

service: stream-test

provider:
  name: aws
  runtime: nodejs4.3
  cfLogs: true

functions:
  hello:
    handler: handler.hello
    role:
      'Fn::GetAtt': [ testRole, Arn ]
    events:
      - stream: arn:aws:dynamodb:us-east-1:XXXXX:table/test/stream/2017-01-26T12:11:48.130
      - stream: arn:aws:kinesis:us-east-1:XXXXX:stream/test

resources:
  Resources:
    testRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: testRole
        Path: "/"
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: ReadFromDynamoDb
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: 'Allow'
                  Action:
                    - 'dynamodb:GetRecords'
                    - 'dynamodb:GetShardIterator'
                    - 'dynamodb:DescribeStream'
                    - 'dynamodb:ListStreams'
                  Resource: arn:aws:dynamodb:us-east-1:XXXX:table/test/stream/2017-01-26T12:11:48.130
          - PolicyName: ReadFromKinesis
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: 'Allow'
                  Action:
                    - 'kinesis:GetRecords'
                    - 'kinesis:GetShardIterator'
                    - 'kinesis:DescribeStream'
                    - 'kinesis:ListStreams'
                  Resource: arn:aws:kinesis:us-east-1:XXXX:stream/test

The PR works great. Thanks for the fix! 💪 💯

@erikerikson
Copy link
Contributor Author

Hah! Not at all. You've totally helped me out with exactly the same sort of thing. There's a lot of complexity and being right every time (tm) is for the computers! 😄

@erikerikson
Copy link
Contributor Author

Thanks for helping me feel a bit better about being human myself!

@pmuens
Copy link
Contributor

pmuens commented Jan 27, 2017

Thanks @erikerikson 👍 😃

Copy link
Contributor

@eahefnawy eahefnawy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great @erikerikson 👍 ... G2M 😊

funcRole['Fn::GetAtt'].length === 2 &&
typeof funcRole['Fn::GetAtt'][0] === 'string' &&
typeof funcRole['Fn::GetAtt'][1] === 'string' &&
funcRole['Fn::GetAtt'][1] === 'Arn'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robust!!! 💯 💪

@eahefnawy eahefnawy merged commit dde1b48 into serverless:master Jan 27, 2017
@erikerikson erikerikson deleted the allow-role-reference-in-func-role-attr branch January 27, 2017 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants