-
Notifications
You must be signed in to change notification settings - Fork 4k
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
feat(iam): Validate the policy statements when synthesizing policy #7897
Changes from all commits
7647d98
ae838a1
e4470b2
507f493
8befbe9
8ba9a3b
d0081f9
4e743ed
f37637b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -249,6 +249,18 @@ const newPolicyDocument = PolicyDocument.fromJson(policyDocument); | |
|
||
``` | ||
|
||
### Policy Statement | ||
|
||
As per the doc of [IAM policy grammar](https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/reference_policies_grammar.html#policies-grammar-bnf), the action and resource blocks are mandatory. Hence, the new policy stament using `PolicyStatementProps` can be created as: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure this README section is helping a lot. What kind of information do you think people are missing? Or did you write this section just to appease the linter? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I just added it to appease the linter. Is there any better way to handle this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ha, yes, we can add a tag to silence it. |
||
|
||
```ts | ||
const policy = new Policy(stack, 'HelloPolicy', { policyName: 'Default' }); | ||
policy.addStatements(new PolicyStatement({ | ||
resources: ['*'], | ||
actions: ['sqs:SendMessage'] | ||
})); | ||
``` | ||
|
||
### OpenID Connect Providers | ||
|
||
OIDC identity providers are entities in IAM that describe an external identity | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,7 @@ export class PolicyStatement { | |
if (props.conditions !== undefined) { | ||
this.addConditions(props.conditions); | ||
} | ||
this.validateProps(props); | ||
} | ||
|
||
// | ||
|
@@ -408,6 +409,27 @@ export class PolicyStatement { | |
} | ||
this.addConditions(conditions); | ||
} | ||
|
||
/** | ||
* Validate PolicyStatementProps | ||
* | ||
* As per [IAM policy grammar](https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/reference_policies_grammar.html#policies-grammar-bnf), | ||
* the action and resource blocks are mandatory. | ||
* | ||
* @param props | ||
*/ | ||
private validateProps(props: PolicyStatementProps) { | ||
if (props.conditions || props.effect || props.notPrincipals || props.notResources || props.principals || props.resources || props.sid) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite get this additional guarding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The additional const p = new PolicyStatement(); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah the old usage pattern. Good catch. Could you rewrite it a little though to make that more self-evident for the future? Maybe to the following: const anyConstructorParamsSupplied = Object.values(props).filter(x => x !== undefined).length > 0;
if (anyConstructorParamsSupplied && !(props.actions || props.notActions)) {
throw new Error('...');
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey but while writing that, that reminds me... We can force either a full policy statement in the constructor, or an empty policy statement in the constructor and then using the fluent API... but why would we prevent a mix? I think it's actually a breaking change to do that. People could have written: const s = new PolicyStatement({ resources: ['*'] });
s.addPrincipal(...): And this change would break them. The only place where we can do proper validation is at the end, when we are rendering the policy statement out. |
||
if (!props.actions && !props.notActions) { | ||
throw new Error('Action block is mandatory. Either `actions` or `notActions` prop must be specified'); | ||
} | ||
} | ||
if (props.actions || props.conditions || props.effect || props.notActions || props.notPrincipals || props.principals || props.sid) { | ||
if (!props.resources && !props.notResources) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also have a question on IAM policy grammar. It says the action and resource blocks are mandatory. However, for certain policies (example: trust relationship policy) for (const a of input.lambdaFunctionAssociations) {
if (a.lambdaFunction.role && a.lambdaFunction.role instanceof iam.Role && a.lambdaFunction.role.assumeRolePolicy) {
a.lambdaFunction.role.assumeRolePolicy.addStatements(new iam.PolicyStatement({
actions: [ 'sts:AssumeRole' ],
principals: [ new iam.ServicePrincipal('edgelambda.amazonaws.com') ],
}));
}
} Please let me know if I'm missing something. I will move this PR to draft in the meantime. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The docs aren't super clear about this, but there is a distinction between:
The syntax between these two is quite similar, except:
Now here's the catch: An AssumeRolePolicy is actually a resource policy on an identity object. You can see that that's true, because the AssumeRolePolicy defines what actions are allowed to performed on the role (very specifically, who is allowed to Assume it). And so therefore, it does not take a Resource. The resource is implicitly: this role. |
||
throw new Error('Resource block is mandatory. Either `resources` or `notResources` prop must be specified'); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah as you mentioned yourself, this is incorrect. This
*
doesn't go here.