-
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
StepFunction/Lambda PolicyDocument duplicate permissions (Maximum policy size exceeded) #1777
Comments
What is the correct way to override deeper elements now? I know I can access the Policy like this: const stateMachinePolicy = stateMachine.role.node.findChild('DefaultPolicy') as iam.Policy;
Also, where is the canonical location for 'how to' do an override/access a nested element now? It used to be available from the main docs page, but I can't seem to see it there anymore..?
Edit: Figured out how to do the overrides on the resource: const stateMachineResource = stateMachine.role.node.findChild('Resource') as stepfunctions.CfnStateMachine;
stateMachineResource.addOverride(...)
stateMachineResource.addPropertyOverride(...) |
You want to be getting the https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html |
Thanks @rix0rrr. Based on that I so far have this, though don't seem to quite have it working right just yet: const stateMachinePolicyDocumentOverride = new iam.PolicyDocument().addStatement(
new iam.PolicyStatement()
.allow()
.addAction('lambda:InvokeFunction')
.addResource(fooFunc.functionArn)
.addResource(barFunc.functionArn)
);
const stateMachinePolicyResource = stateMachine.node.findChild('Role/DefaultPolicy/Resource') as iam.CfnPolicy;
stateMachinePolicyResource.addPropertyOverride('PolicyDocument', stateMachinePolicyDocumentOverride) Edit: stateMachinePolicyResource.addPropertyDeletionOverride('PolicyDocument');
stateMachinePolicyResource.addPropertyOverride('PolicyDocumentA', stateMachinePolicyDocumentOverride); SecmapsStateMachineRoleDefaultPolicy3ED6D243:
Type: AWS::IAM::Policy
Properties:
..snip..
PolicyDocumentA:
statements:
- Action: lambda:InvokeFunction
Effect: Allow
Resource:
- Fn::GetAtt:
- FooFuncD8B69655
- Arn
- Fn::GetAtt:
- BarFunc9CC80B3F
- Arn But if I just add the property override (as below), or try to delete it then add it, it seems to just keep the old PolicyDocument (with all of it's many many repeated entries) stateMachinePolicyResource.addPropertyOverride('PolicyDocument', stateMachinePolicyDocumentOverride); Any thoughts on how to make it actually apply? |
Huh. Honestly, no. A raw override ( |
But I think the problem might be that it merges the documents :x |
A hacky workaround solution for you right now is to supply your own class that implements |
Will have a bit of a play around. It looks like using While I get that the find child/override stuff is designed to allow us to break out, while still 'protecting' the inner workings, I wonder if it would be nicer to have an easier ability to substitute aspects of a higher level component. eg. statemachine.HereThereBeDragons.role = new iam.Role(...) All of this override stuff (to my knowledge) is applied to the yaml/etc at synthesis. Is there currently a method to say "Give me a state machine, but use this custom Role class i'm providing"? Because that would be super handy in situations like this. Edit: Reading a bit deeper, it seems that the StateMachine actually accepts a |
Ok, here's my workaround. I decided to run with the class RoleWithUniquePolicyStatements extends iam.Role {
constructor(scope: cdk.Construct, id: string, props: iam.RoleProps, suppressWarnings: boolean = false) {
super(scope, id, props);
this.suppressWarnings = suppressWarnings;
this.uniqueStatements = new Set<string>()
}
suppressWarnings: boolean;
uniqueStatements: Set<string>;
addToPolicy(statement: iam.PolicyStatement): void {
const statementJson = JSON.stringify(statement.toJson(), null, 0);
if (this.uniqueStatements.has(statementJson)) {
if (!this.suppressWarnings) {
console.warn(`Prevented attempt to add duplicate PolicyStatement:\n${statementJson}\n`)
}
} else {
this.uniqueStatements = this.uniqueStatements.add(statementJson);
super.addToPolicy(statement);
}
}
// sneakyAddToPolicy(statement: iam.PolicyStatement): void {
// super.addToPolicy(statement)
// }
} Usage: new stepfunctions.StateMachine(this, 'FooStateMachine', {
definition,
role: new RoleWithUniquePolicyStatements(this, 'FooStateMachineRole', {
assumedBy: new iam.ServicePrincipal(`states.${this.region}.amazonaws.com`),
})
}); |
@rix0rrr what do you think we should do with this? |
I think we should deduplicate policies upon rendering (in effect, render them as the set they are). |
+1. This is an issue that will crop up again and again in different contexts (in fact, it already has, with permissions in CodePipeline for CloudFormation deployments). If we want to solve it once and for all, I believe it needs to be changed at the source (i.e., the IAM library). |
I have a lambda function, that is called by a number of parallel tasks in an AWS step function. Code (with irrelevant bits snipped out) looks something like this:
I end up getting an error like the following:
Looking at
cdk diff
, it seems that the same permission for the statemachine to execute the lambda function is repeated for each of the parallel tasks:I would have expected the policy to be treated like a set (eg. this permission would only be added once when it's exactly the same).
While it would be nice to have this solved 'properly' at some point, some form of workaround in the meantime would also be awesome. I assume I'll be able to override/replace the policy document somehow, but haven't quite figured that out yet.
The text was updated successfully, but these errors were encountered: