Borislav Hadzhiev
Reading timeยท4 min
Photo from Unsplash
An IAM Group is a collection of users. Groups enable us to reuse common permissions by attaching permissions on the group, rather than on each individual user.
In order to create groups in AWS CDK, we have to instantiate the Group class.
Let's start by creating a simple IAM group with a managed policy:
import * as iam from 'aws-cdk-lib/aws-iam'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ๐ create an IAM group const group = new iam.Group(this, 'group-id', { managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ReadOnlyAccess'), ], }); console.log('group name ๐', group.groupName); console.log('group arn ๐', group.groupArn); } }
We instantiated the Group
class. The constructor method of the class takes 3
parameters:
groupName
- a name for the group. We didn't specify one in the example,
because by default CDK will generate a unique group name for us.managedPolicies
- a list of managed policies to associate with the group. We
used an AWS-managed policy that grants EC2 read permissions.path
- the path to the group - defaults to /
.The values for the groupName
and groupArn
are tokens at synthesis time, so
we can't use them in conditionals:
Tokens are encoded values that get resolved at deployment time by CloudFormation.
Let's run the deploy
command:
npx aws-cdk deploy
If we look at the group in the IAM console, we can see that the managed policy has been attached to it:
We can attach a policy to a Group in CDK, by using the following methods:
Let's look at an example of all 3 methods:
import * as iam from 'aws-cdk-lib/aws-iam'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // ๐ attach a managed policy to the group group.addManagedPolicy( iam.ManagedPolicy.fromAwsManagedPolicyName( 'service-role/AWSLambdaBasicExecutionRole', ), ); // ๐ add an inline policy to the group group.addToPolicy( new iam.PolicyStatement({ actions: ['logs:CreateLogGroup', 'logs:CreateLogStream'], resources: ['*'], }), ); // ๐ attach an inline policy on the group group.attachInlinePolicy( new iam.Policy(this, 'cw-logs', { statements: [ new iam.PolicyStatement({ effect: iam.Effect.DENY, actions: ['logs:PutLogEvents'], resources: ['*'], }), ], }), ); } }
We used the addManagedPolicy
, addToPolicy
and attachInlinePolicy
methods
on an instance of the
Group
class.
addManagedPolicy
- takes a single parameter - an IAM-managed policy
addToPolicy
- takes a
PolicyStatement
instance as a parameter
attachInlinePolicy
takes a
Policy
instance as a parameter
Let's issue the deploy
command:
npx aws-cdk deploy
If we take a look at the group in the IAM console, we can see that it now has 4 permission policies attached:
In order to add a user to a group in AWS CDK, we have to use the addUser method on an instance of the Group class.
import * as iam from 'aws-cdk-lib/aws-iam'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // ๐ create IAM User const user = new iam.User(this, 'user-id'); // ๐ add the User to the group group.addUser(user); } }
We created an IAM user and added it to a group.
Let's deploy the changes:
npx aws-cdk deploy
If we look at the Users
section of our group, we can see that the user we
created has been added:
In order to import an external IAM Group in an AWS CDK stack, we have to use the fromGroupArn static method on the Group class.
import * as cdk from 'aws-cdk-lib'; import * as iam from 'aws-cdk-lib/aws-iam'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ๐ import existing Group const importedGroup = iam.Group.fromGroupArn( this, 'existing-group-id', `arn:aws:iam::${cdk.Stack.of(this).account}:group/YOUR_GROUP_NAME`, ); console.log('imported group name ๐', importedGroup.groupName); console.log('imported group arn ๐', importedGroup.groupArn); } }
We used the fromGroupArn
static method on the Group
class to import an
external group. The method takes 3 parameters:
scope
- the scope of the constructid
- an identifier for the construct (must be unique within the scope)groupArn
- the ARN of the group we want to import