Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING - Replace IamPolicyLambdaExecution with inline policies and added ManagedPolicyArns to fix VPC permissions #2983

Merged
merged 9 commits into from Feb 28, 2017

Conversation

nicka
Copy link
Member

@nicka nicka commented Dec 19, 2016

What did you implement:

Closes #1786
Closes #2780
Closes #2830

How did you implement it:

  • Migrated the IamPolicyLambdaExecution resource statements towards inline polices within the IamRoleLambdaExecution resource to fix CloudFormation dependency issues. As a bonues, we save an extra CloudFormation resource.
  • Added the ManagedPolicyArns property to IamRoleLambdaExecution resource when VPC config is provided.
  • Improved logic which checks if all functions contain a custom role, in which case we skip creation of the IamRoleLambdaExecution resource.

NOTE: This might be a breaking change since users could be referecing to the IamPolicyLambdaExecution policy which this PR removes.

Research

Adding VPC config to an existing stack still occasionally fails with the ec2 permissions issue. As a solution to this I will try to work with ManagedPolicyArns. Each account should come with a default arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole by AWS which could be used within the ManagedPolicyArns property.

Update 1:
The ManagedPolicyArns with the default AWSLambdaVPCAccessExecutionRole works!!!

Update 2:
ManagedPolicyArns has been added as a default when vpc config is provided.

How can we verify

  • Real-life test create/update stack
  • Real-life test create/update stack - with VPC provider level
  • Real-life test create/update stack - with VPC functional level
  • Real-life test create/update stack - with role provider level
  • Real-life test create/update stack - with multiple functions with one having a role
  • Real-life test create/update stack - with multiple functions all having a role
  • Real-life test create/update stack - with custom provider iamRoleStatements
  • Real-life test create/update stack - with Kinesis stream
  • Real-life test create/update stack - with DyanomoDB stream

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

Is this ready for review?: YES

@mthenw
Copy link
Contributor

mthenw commented Dec 20, 2016

@nicka

@erikerikson
Copy link
Member

Rockin'! This has been needed for a very long while!

@nicka nicka changed the title Replace IamPolicyLambdaExecution with inline policies Replace IamPolicyLambdaExecution with inline policies and added ManagedPolicyArns to fix VPC permissions Dec 20, 2016
if (!this.serverless.service.getAllFunctions().length) {
return BbPromise.resolve();
}

let anyFunctionHasNoRole = false;
Copy link
Member Author

Choose a reason for hiding this comment

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

@pmuens @eahefnawy @mthenw I updated this logic as it seemed to be broken, or my brain didn't compute 😊

@nicka
Copy link
Member Author

nicka commented Dec 20, 2016

@pmuens @eahefnawy @mthenw I added the ManagedPolicyArns property to the IamRoleLambdaExecution resource by default in case vpc config is provided. Will also re-run all my previous tests against actual stacks tomorrow.

@nicka
Copy link
Member Author

nicka commented Dec 21, 2016

@serverless/team Successfully tested all stack create/update cases against actual stacks. This PR is now 100% ready for review 👍

@pmuens pmuens added this to the 2.0 milestone Dec 22, 2016
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.

Just did a first dive into the code. Really, really great work! Love the refactoring and the inline policies!

Tested it with a simple setup and it works as nothing has changed.
Even ran the complex-integration-test-suite against it and it succeeded.

However this PR needs far more attention / deep dives with different configurations as it touches mission critical parts.

I'll test it more thoroughly and encourage everyone who reads this to do as well.

Great work @nicka 🥇

@nicka
Copy link
Member Author

nicka commented Jan 3, 2017

@pmuens Any news on this?

@nicka nicka mentioned this pull request Jan 3, 2017
6 tasks
@pmuens
Copy link
Contributor

pmuens commented Jan 3, 2017

@nicka thanks for getting back.
We're currently working on the v1.5 release which is just around the corner 😸

This PR is a great move towards v2 so we'll focus on this one quite soon! 👍

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.

Just gave it another spin today. Deployed a simple service, a more complex service (with multiple event sources) and ran the complex-integration-test-suite again. Couldn't break it 👍

Does anyone know a very complex, yet easy to deploy open source Serverless project / service we can use to test it against this?

I'll look through the code again tomorrow...

Great job @nicka 💯 👍

@pmuens pmuens changed the title Replace IamPolicyLambdaExecution with inline policies and added ManagedPolicyArns to fix VPC permissions BREAKING - Replace IamPolicyLambdaExecution with inline policies and added ManagedPolicyArns to fix VPC permissions Jan 23, 2017
@eahefnawy eahefnawy modified the milestones: 1.7, 1.6 Jan 30, 2017
@pmuens pmuens modified the milestones: 1.8, 1.7 Feb 8, 2017
@pmuens
Copy link
Contributor

pmuens commented Feb 15, 2017

Hey @nicka we finalized the decision to include this PR in v1.8!

Could you maybe look at the conflicts and resolve them 😬 . That would be super awesome 💯

Sorry for any inconveniences. Let us know if you need any help and thanks in advance! 👍

/cc @eahefnawy @brianneisler

@nicka
Copy link
Member Author

nicka commented Feb 15, 2017

@pmuens Sure thing, I'll try my best to finish this by the end of this week.

@ghost
Copy link

ghost commented Feb 15, 2017

I'm working behind a company firewall and when I run

serverless deploy -v

I'm getting

  WARNING: You are running v1.7.0. v1.8.0 will include the following breaking changes:
    - Will replace IamPolicyLambdaExecution resource with inline policies -> https://git.io/vDilm
    - "sls info" will output the short function name rather than the lambda name -> https://git.io/vDiWx

  You can opt-out from these warnings by setting the "SLS_IGNORE_WARNING=*" environment variable.

I just installed serverless npm module, why am I getting a old module to begin with?

@dannycohn
Copy link
Contributor

You are not getting an old version. This is a warning that the next version will have breaking changes to give you time to adjust.

@nicka
Copy link
Member Author

nicka commented Feb 20, 2017

@pmuens @mthenw @erikerikson Rebased on top of master (the merge conflicts where hell), def needs some love and testing before merging!

Copy link
Member

@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.

@nicka testing this now...I requested one small but essential change.

Thanks a lot! and sorry for the delay! 🙌

[this.provider.naming.getRoleLogicalId()]: iamRoleLambdaExecutionTemplate,
}
);

this.serverless.service.getAllFunctions().forEach((functionName) => {
Copy link
Member

Choose a reason for hiding this comment

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

This code block must be at the very beginning of the merge() method, otherwise bug #3174 will resurface. In other words, now that we always use log group resources, they must be merged regardless of whether we're using custom or default roles.

Copy link
Member Author

@nicka nicka Feb 23, 2017

Choose a reason for hiding this comment

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

I'm not sure if I completely follow because of all the prior checks:

// resolve early if no functions are provided
// resolve early if provider level role is provided
// resolve early if all functions contain a custom role

If we're talking purely about Log groups and assuming the user is providing his own IAM statement the create logs code:

this.serverless.service.getAllFunctions().forEach((functionName) => {
      const functionObject = this.serverless.service.getFunction(functionName);
      const logGroupLogicalId = this.provider.naming
        .getLogGroupLogicalId(functionName);
      const newLogGroup = {
        [logGroupLogicalId]: {
          Type: 'AWS::Logs::LogGroup',
          Properties: {
            LogGroupName: this.provider.naming.getLogGroupName(functionObject.name),
          },
        },
      };
      _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
        newLogGroup);
});

might come between:

// resolve early if no functions are provided
// HEREEEEEE
// resolve early if provider level role is provided

Copy link
Member

Choose a reason for hiding this comment

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

@nicka yep exactly ... what we're trying to avoid is to resolving early before getting the chance to merge the LogGroup, which must be merged regardless of the what role we're using.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I'll update the flow 👍

]
}
}
]
Copy link
Member

Choose a reason for hiding this comment

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

This is probably taken from the legacy policy json file, but do you see any reason why we have two seperate statements? we can just have 1 statement for all 3 permissions (CreateLogGroup, CreateLogStream & PutLogEvents), since after all they're all affecting the same resources/functions. Actually, I don't think we need the logs:CreateLogGroup permission anymore since we're now explicitly creating it via CF.

This has probably should've been done earlier and not really critical, but do you see any downside to that? if not let's make those changes 😊

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes total sense to update, especially if were ALWAYS creating the log groups. Will only keep CreateLogStream and PutLogEvents then.

Copy link
Member Author

Choose a reason for hiding this comment

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

Might still need two because of /* within IAM. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

aaah right I think you're right! 😊

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry for the delay, switched MacBook's etc. Will work on the updates.

Copy link
Member

Choose a reason for hiding this comment

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

@eahefnawy using two was important because the use of star would give creation rights to any log group with the same prefix. but as you note, it is legacy that can be removed now that explicit log group creation happens.

There's a bit more paranoia not in there though... Here is our latest:

                - Effect: Allow
                  Action:
                    - logs:CreateLogStream
                  Resource:
                    - Fn::GetAtt:
                      - TheLogGroup
                      - Arn
                - Effect: Allow
                  Action:
                    - logs:PutLogEvents
                  Resource:
                    - Fn::Join:
                      - ":"
                      - - Fn::GetAtt:
                          - TheLogGroup
                          - Arn
                        - "*"

This way, the lambda can't create log streams in any similarly-prefixed-but-not-the-log-group-that-has-been-created while still being able to create in the created log group and then write to any such log stream.

Copy link
Member

Choose a reason for hiding this comment

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

small surface space but since we're choosing this for all users and we can do it once and be done... seems worth the energy.

Copy link
Member

Choose a reason for hiding this comment

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

and... pretty sure it's my fault it's not already correct. sorry for that

@eahefnawy
Copy link
Member

@nicka added another comment. Sorry for the hassle 🙌

@nicka
Copy link
Member Author

nicka commented Feb 27, 2017

@eahefnawy Updated!

Copy link
Member

@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.

Thanks @nicka ... G2M 🙌

@eahefnawy eahefnawy merged commit dc0c92b into serverless:master Feb 28, 2017
@AndrewFarley
Copy link

My stacks aren't complex, but I confirm this fixes the problem for me for my projects that functions in a VPC during initial creation! +1 here, good job, can't wait for it in next release. Cheers!

@nicka
Copy link
Member Author

nicka commented Mar 1, 2017

Woehoe!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants