Skip to content

Serverless canary creates IAM role resource if Role property is not provided + Policies property added #2107

New issue

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

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

Already on GitHub? # to your account

Merged
merged 27 commits into from
Aug 5, 2021

Conversation

aaythapa
Copy link
Contributor

@aaythapa aaythapa commented Jul 29, 2021

Issue #, if available:

Description of changes:

Description of how you validated changes:

  • Unit tests to make sure an IAM::Role resource was made whenever the Role property wasn't filled and the right roles were attached to the policy.
  • Unit tests to make sure whenever Policies was defined it was appended to the IAM::Role resource
  • Integration tests to make sure Serverless::Canary and IAM::Role deployed correctly.

Checklist:

  • Write/update tests
  • make pr passes
  • Update documentation
  • Verify transformed template deploys and application functions as expected

Examples?

Please reach out in the comments, if you want to add an example. Examples will be
added to sam init through https://github.com/awslabs/aws-sam-cli-app-templates/

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@aaythapa aaythapa changed the title Feat/sam canary Serverless canary creates IAM role resource if Role property is not provided + Policies property added Jul 29, 2021
@codecov-commenter
Copy link

codecov-commenter commented Jul 29, 2021

Codecov Report

❗ No coverage uploaded for pull request base (feat/sam-canary@f05f778). Click here to learn what that means.
The diff coverage is n/a.

Impacted file tree graph

@@                Coverage Diff                 @@
##             feat/sam-canary    #2107   +/-   ##
==================================================
  Coverage                   ?   94.01%           
==================================================
  Files                      ?       93           
  Lines                      ?     6348           
  Branches                   ?     1278           
==================================================
  Hits                       ?     5968           
  Misses                     ?      175           
  Partials                   ?      205           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f05f778...2ab5ac9. Read the comment docs.

Copy link
Contributor

@c2tarun c2tarun left a comment

Choose a reason for hiding this comment

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

PR description says that unit tests were added but I didn't find them. Did you forgot to check them in?

@@ -129,3 +129,45 @@ def lambda_invoke_function_role_policy(cls, function_arn, logical_id):
},
}
return document

@classmethod
def execute_canary_policy(cls, logical_id, result_bucket, canary_name):
Copy link
Contributor

Choose a reason for hiding this comment

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

Some documentation on what this method do.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also we can make the method naming consistent with others above: <service>-<action>-policy.

if synthetics_canary.ArtifactS3Location is None:

artifact_bucket_name = ""
if self.ArtifactS3Location is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did this change from synthetics_canary.ArtifactS3Location to self.ArtifactS3Location?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

to keep it consistent with the other times that I check whether or not a property is None. Like for example later in the code is check for self.Tracing and self.VpcConfig

:rtype: model.iam.IAMRole
"""

assume_role_policy_document = IAMRolePolicies.lambda_assume_role_policy()
Copy link
Contributor

Choose a reason for hiding this comment

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

So this feels like user have no way to override this. In SAM Function we have a property AssumeRolePolicyDocument which allows user to override this. Can we do similar to that?

For more context if user want to have more protection by adding condition for account ID check they can do that without AssumeRolePolicyDocument

# if user has defined Policies property, those policies will be appended to this role
function_policies = ResourcePolicies(
{"Policies": self.Policies},
# No support for policy templates in the "core"
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the No support for policy templates in the "core"? Not too sure, it was included in the other places where ResourcePolicies is used so I included it here just in case

@classmethod
def execute_canary_policy(cls, logical_id, result_bucket, canary_name):
document = {
"PolicyName": logical_id + "CanaryPolicy",
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we split this into 3 methods, one for each statement?

@@ -129,3 +129,45 @@ def lambda_invoke_function_role_policy(cls, function_arn, logical_id):
},
}
return document

@classmethod
def execute_canary_policy(cls, logical_id, result_bucket, canary_name):
Copy link
Contributor

Choose a reason for hiding this comment

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

Also we can make the method naming consistent with others above: <service>-<action>-policy.

Comment on lines 149 to 159
"Fn::Join": [
"",
[
{
"Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${"
"AWS::AccountId}:log-group:/${AWS::Partition}/lambda/cwsyn-"
},
canary_name,
"-*",
],
]
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason we don't put canary_name into the Fn::Sub string? (removing Join)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

did some more testing on the logs and turns out the canary name is not even needed. Will take it out and take out the Fn::Join as well

Comment on lines 870 to 871
"""Constructs a Role based on this SAM Canaries's Policies and ArtifactS3Location property.
Copy link
Contributor

Choose a reason for hiding this comment

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

could use more comments here to explain what is happening here (what polices will be added in what scenario)

# The policy to execute the canary is only added to the role if the user hasn't defined ArtifactS3Location
# this emulates CloudWatch Synthetics Canary dashboard's behavior
policy_documents = []
if self.ArtifactS3Location is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: We didn't use if self.Tracing is not None above, to keep consistent, can we use if not self.ArtifactS3Location: here?

{
"Effect": "Allow",
"Action": "cloudwatch:PutMetricData",
"Resource": "*",
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to be more specific about the resource? (or the condition below is enough)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the condition should be enough, its the same one used by cloudwatch dashboard when you generate a role policy through there

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that is Sam meant about Resources. To answer Sam's question we allow Canary Lambda to putmetricdata so that the integration to publishing metrics is not very brittle. Another approach could be that metric data is created and only permission to those will be granted. But every time we require to publish new metric we have to update it. Plus I couldn't find any way to create metric data using CFN, so it might have to be done by hand. This is similar to LambdaBasicExecution permission for logs.

Copy link
Contributor

@aahung aahung left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for addressing the comments

role_attributes = self.get_passthrough_resource_attributes()
if self.AssumeRolePolicyDocument is not None:
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Use if self.AssumeRolePolicyDocument:

}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Add an extra line at the end of the file

Copy link
Contributor

@c2tarun c2tarun left a comment

Choose a reason for hiding this comment

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

LGTM!

{
"Effect": "Allow",
"Action": "cloudwatch:PutMetricData",
"Resource": "*",
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that is Sam meant about Resources. To answer Sam's question we allow Canary Lambda to putmetricdata so that the integration to publishing metrics is not very brittle. Another approach could be that metric data is created and only permission to those will be granted. But every time we require to publish new metric we have to update it. Plus I couldn't find any way to create metric data using CFN, so it might have to be done by hand. This is similar to LambdaBasicExecution permission for logs.

@c2tarun c2tarun merged commit 2af925f into aws:feat/sam-canary Aug 5, 2021
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants