Skip to content

Commit

Permalink
feat(iam): support fromGroupName() for IAM groups (aws#17243)
Browse files Browse the repository at this point in the history
IAM Policies and Users already support import by name. Extending same for Groups

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
nom3ad authored and Andrew Beresford committed Nov 29, 2021
1 parent d68c5de commit 6e30c0b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 13 deletions.
29 changes: 24 additions & 5 deletions packages/@aws-cdk/aws-iam/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ Identity Pools Developer Guide].

The following examples defines an OpenID Connect provider. Two client IDs
(audiences) are will be able to send authentication requests to
https://openid/connect.
<https://openid/connect>.

```ts
const provider = new iam.OpenIdConnectProvider(this, 'MyProvider', {
Expand Down Expand Up @@ -439,6 +439,26 @@ const user = iam.User.fromUserAttributes(this, 'MyImportedUserByAttributes', {
});
```

## Groups

An IAM user group is a collection of IAM users. User groups let you specify permissions for multiple users.

```ts
const group = new iam.Group(this, 'MyGroup');
```

To import an existing group by ARN:

```ts
const group = iam.Group.fromGroupArn(this, 'MyImportedGroupByArn', 'arn:aws:iam::account-id:group/group-name');
```

To import an existing group by name [with path](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-friendly-names):

```ts
const group = iam.Group.fromGroupName(this, 'MyImportedGroupByName', 'group-name');
```

To add a user to a group (both for a new and imported user/group):

```ts
Expand All @@ -450,12 +470,11 @@ user.addToGroup(group);
group.addUser(user);
```


## Features

* Policy name uniqueness is enforced. If two policies by the same name are attached to the same
* Policy name uniqueness is enforced. If two policies by the same name are attached to the same
principal, the attachment will fail.
* Policy names are not required - the CDK logical ID will be used and ensured to be unique.
* Policies are validated during synthesis to ensure that they have actions, and that policies
* Policy names are not required - the CDK logical ID will be used and ensured to be unique.
* Policies are validated during synthesis to ensure that they have actions, and that policies
attached to IAM principals specify relevant resources, while policies attached to resources
specify which IAM principals they apply to.
18 changes: 18 additions & 0 deletions packages/@aws-cdk/aws-iam/lib/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ export class Group extends GroupBase {
return new Import(scope, id);
}

/**
* Import an existing group by given name (with path).
* This method has same caveats of `fromGroupArn`
*
* @param scope construct scope
* @param id construct id
* @param groupName the groupName (path included) of the existing group to import
*/
static fromGroupName(scope: Construct, id: string, groupName: string) {
const groupArn = Stack.of(scope).formatArn({
service: 'iam',
region: '',
resource: 'group',
resourceName: groupName,
});
return Group.fromGroupArn(scope, id, groupArn);
}

public readonly groupName: string;
public readonly groupArn: string;

Expand Down
33 changes: 25 additions & 8 deletions packages/@aws-cdk/aws-iam/test/group.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ describe('IAM groups', () => {
{
MyGroupCBA54B1B: { Type: 'AWS::IAM::Group' },
User1E278A736:
{
Type: 'AWS::IAM::User',
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
},
{
Type: 'AWS::IAM::User',
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
},
User21F1486D1:
{
Type: 'AWS::IAM::User',
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
},
{
Type: 'AWS::IAM::User',
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
},
},
});
});
Expand All @@ -56,4 +56,21 @@ describe('IAM groups', () => {
],
});
});

test('groups imported by group name have valid arn', () => {
// GIVEN
const stack = new Stack();

// WHEN
const group1 = Group.fromGroupName(stack, 'imported-group1', 'MyGroupName1');
const group2 = Group.fromGroupName(stack, 'imported-group2', 'division/MyGroupName2');

// THEN
expect(stack.resolve(group1.groupArn)).toStrictEqual({
'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::', { Ref: 'AWS::AccountId' }, ':group/MyGroupName1']],
});
expect(stack.resolve(group2.groupArn)).toStrictEqual({
'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::', { Ref: 'AWS::AccountId' }, ':group/division/MyGroupName2']],
});
});
});

0 comments on commit 6e30c0b

Please sign in to comment.