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

fix(iam): cannot import service role with a principal in its path #8692

Merged
merged 10 commits into from
Jul 8, 2020
7 changes: 3 additions & 4 deletions packages/@aws-cdk/aws-iam/lib/role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,9 @@ export class Role extends Resource implements IRole {
const parsedArn = scopeStack.parseArn(roleArn);
const resourceName = parsedArn.resourceName!;
// service roles have an ARN like 'arn:aws:iam::<account>:role/service-role/<roleName>'
// we want to support these as well, so strip out the 'service-role/' prefix if we see it
const roleName = resourceName.startsWith('service-role/')
? resourceName.slice('service-role/'.length)
: resourceName;
// or 'arn:aws:iam::<account>:role/service-role/servicename.amazonaws.com/service-role/<roleName>'
// we want to support these as well, so we just use the element after the last slash as role name
const roleName = resourceName.split('/').pop()!;

class Import extends Resource implements IRole {
public readonly grantPrincipal: IPrincipal = this;
Expand Down
45 changes: 35 additions & 10 deletions packages/@aws-cdk/aws-iam/test/role.from-role-arn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,20 +480,45 @@ describe('IAM Role.fromRoleArn', () => {
describe('imported with the ARN of a service role', () => {
beforeEach(() => {
roleStack = new Stack();
importedRole = Role.fromRoleArn(roleStack, 'Role',
`arn:aws:iam::${roleAccount}:role/service-role/codebuild-role`);
});

it("correctly strips the 'service-role' prefix from the role name", () => {
new Policy(roleStack, 'Policy', {
statements: [somePolicyStatement()],
roles: [importedRole],
describe('without a service principal in the role name', () => {
beforeEach(() => {
importedRole = Role.fromRoleArn(roleStack, 'Role',
`arn:aws:iam::${roleAccount}:role/service-role/codebuild-role`);
});

it("correctly strips the 'service-role' prefix from the role name", () => {
new Policy(roleStack, 'Policy', {
statements: [somePolicyStatement()],
roles: [importedRole],
});

expect(roleStack).toHaveResourceLike('AWS::IAM::Policy', {
'Roles': [
'codebuild-role',
],
});
});
});

expect(roleStack).toHaveResourceLike('AWS::IAM::Policy', {
'Roles': [
'codebuild-role',
],
describe('with a service principal in the role name', () => {
beforeEach(() => {
importedRole = Role.fromRoleArn(roleStack, 'Role',
`arn:aws:iam::${roleAccount}:role/aws-service-role/anyservice.amazonaws.com/codebuild-role`);
});

it("correctly strips both the 'aws-service-role' prefix and the service principal from the role name", () => {
new Policy(roleStack, 'Policy', {
statements: [somePolicyStatement()],
roles: [importedRole],
});

expect(roleStack).toHaveResourceLike('AWS::IAM::Policy', {
'Roles': [
'codebuild-role',
],
});
});
});
});
Expand Down