Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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']],
});
});
});