-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(iam):
Role.withoutPolicyUpdates()
(#5569)
Add a new method to `Role` called `withoutPolicyUpdates()`, which returns a wrapper object that will drop all policy updates. This can be used in situations where you want to skip the default IAM permission adding behavior of CDK. Needs only be used with roles that are created in the same CDK application; for imported roles, supplying `mutable=false` when calling `Role.fromRoleArn()` is sufficient. Fixes #2985. Fixes #4465. Closes #4501.
- Loading branch information
Showing
5 changed files
with
280 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { DependableTrait } from '@aws-cdk/core'; | ||
import { Grant } from '../grant'; | ||
import { IManagedPolicy } from '../managed-policy'; | ||
import { Policy } from '../policy'; | ||
import { PolicyStatement } from '../policy-statement'; | ||
import { IPrincipal } from '../principals'; | ||
import { IRole } from '../role'; | ||
|
||
/** | ||
* An immutable wrapper around an IRole | ||
* | ||
* This wrapper ignores all mutating operations, like attaching policies or | ||
* adding policy statements. | ||
* | ||
* Useful in cases where you want to turn off CDK's automatic permissions | ||
* management, and instead have full control over all permissions. | ||
* | ||
* Note: if you want to ignore all mutations for an externally defined role | ||
* which was imported into the CDK with {@link Role.fromRoleArn}, you don't have to use this class - | ||
* simply pass the property mutable = false when calling {@link Role.fromRoleArn}. | ||
*/ | ||
export class ImmutableRole implements IRole { | ||
public readonly assumeRoleAction = this.role.assumeRoleAction; | ||
public readonly policyFragment = this.role.policyFragment; | ||
public readonly grantPrincipal = this.role.grantPrincipal; | ||
public readonly roleArn = this.role.roleArn; | ||
public readonly roleName = this.role.roleName; | ||
public readonly node = this.role.node; | ||
public readonly stack = this.role.stack; | ||
|
||
constructor(private readonly role: IRole) { | ||
// implement IDependable privately | ||
DependableTrait.implement(this, { | ||
dependencyRoots: [ role ] | ||
}); | ||
} | ||
|
||
public attachInlinePolicy(_policy: Policy): void { | ||
// do nothing | ||
} | ||
|
||
public addManagedPolicy(_policy: IManagedPolicy): void { | ||
// do nothing | ||
} | ||
|
||
public addToPolicy(_statement: PolicyStatement): boolean { | ||
// Not really added, but for the purposes of consumer code pretend that it was. | ||
return true; | ||
} | ||
|
||
public grant(grantee: IPrincipal, ...actions: string[]): Grant { | ||
return this.role.grant(grantee, ...actions); | ||
} | ||
|
||
public grantPassRole(grantee: IPrincipal): Grant { | ||
return this.role.grantPassRole(grantee); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import '@aws-cdk/assert/jest'; | ||
import { Stack } from '@aws-cdk/core'; | ||
import * as iam from '../lib'; | ||
|
||
// tslint:disable:object-literal-key-quotes | ||
|
||
describe('ImmutableRole', () => { | ||
let stack: Stack; | ||
let mutableRole: iam.Role; | ||
let immutableRole: iam.IRole; | ||
|
||
beforeEach(() => { | ||
stack = new Stack(); | ||
mutableRole = new iam.Role(stack, 'MutableRole', { | ||
assumedBy: new iam.AnyPrincipal(), | ||
}); | ||
immutableRole = mutableRole.withoutPolicyUpdates(); | ||
}); | ||
|
||
test('ignores calls to attachInlinePolicy', () => { | ||
const user = new iam.User(stack, 'User'); | ||
const policy = new iam.Policy(stack, 'Policy', { | ||
statements: [new iam.PolicyStatement({ | ||
resources: ['*'], | ||
actions: ['s3:*'], | ||
})], | ||
users: [user], | ||
}); | ||
|
||
immutableRole.attachInlinePolicy(policy); | ||
|
||
expect(stack).toHaveResource('AWS::IAM::Policy', { | ||
"PolicyDocument": { | ||
"Statement": [ | ||
{ | ||
"Action": "s3:*", | ||
"Resource": "*", | ||
"Effect": "Allow", | ||
}, | ||
], | ||
"Version": "2012-10-17", | ||
}, | ||
"PolicyName": "Policy23B91518", | ||
"Users": [ | ||
{ | ||
"Ref": "User00B015A1", | ||
}, | ||
], | ||
}); | ||
}); | ||
|
||
test('ignores calls to addManagedPolicy', () => { | ||
mutableRole.addManagedPolicy({ managedPolicyArn: 'Arn1' }); | ||
|
||
immutableRole.addManagedPolicy({ managedPolicyArn: 'Arn2' }); | ||
|
||
expect(stack).toHaveResourceLike('AWS::IAM::Role', { | ||
"ManagedPolicyArns": [ | ||
'Arn1', | ||
], | ||
}); | ||
}); | ||
|
||
test('ignores calls to addToPolicy', () => { | ||
mutableRole.addToPolicy(new iam.PolicyStatement({ | ||
resources: ['*'], | ||
actions: ['s3:*'], | ||
})); | ||
|
||
immutableRole.addToPolicy(new iam.PolicyStatement({ | ||
resources: ['*'], | ||
actions: ['iam:*'], | ||
})); | ||
|
||
expect(stack).toHaveResourceLike('AWS::IAM::Policy', { | ||
"PolicyDocument": { | ||
"Statement": [ | ||
{ | ||
"Resource": "*", | ||
"Action": "s3:*", | ||
"Effect": "Allow", | ||
}, | ||
], | ||
}, | ||
}); | ||
}); | ||
}); |