How to Create an IAM User in AWS CDK

avatar

Borislav Hadzhiev

Mon Apr 26 20214 min read

banner

Photo by Linda Xu

To create an IAM User in aws CDK we have to instantiate and configure the User class.

Creating IAM Users in AWS CDK #

In order to create an IAM User in AWS CDK we have to use the User construct.

To have a complete reference for how to create an IAM User, let's define a simple CDK stack, where we:

  • create an IAM user
  • add the User to a Group
  • attach permission policies to the User
  • set a permissions boundary on the User
The code for this article is available on GitHub
lib/cdk-starter-stack.ts
import * as iam from '@aws-cdk/aws-iam';
import * as cdk from '@aws-cdk/core';

export class CdkStarterStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // ๐Ÿ‘‡ Create group
    const group = new iam.Group(this, 'example-group', {
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ReadOnlyAccess'),
      ],
    });

    // ๐Ÿ‘‡ Create Managed Policy
    const loggingManagedPolicy = iam.ManagedPolicy.fromAwsManagedPolicyName(
      'CloudWatchReadOnlyAccess',
    );

    // ๐Ÿ‘‡ Create Permissions Boundary
    const permissionsBoundary = new iam.ManagedPolicy(
      this,
      'example-permissions-boundary',
      {
        statements: [
          new iam.PolicyStatement({
            effect: iam.Effect.DENY,
            actions: ['sqs:*'],
            resources: ['*'],
          }),
        ],
      },
    );

    // ๐Ÿ‘‡ Create User
    const user = new iam.User(this, 'example-user', {
      userName: 'example-user',
      managedPolicies: [loggingManagedPolicy],
      groups: [group],
      permissionsBoundary,
    });
  }
}

Let's go over what we did in the code snippet.

  1. we created an IAM Group, using the Group construct. In our case the group grants read only access to the EC2 service, via an AWS managed policy.

  2. we referenced a managed IAM Policy using the ManagedPolicy construct. In this case the managed policy grants simple logging permissions.

  3. we created a Permissions Boundary using the PermissionsBoundary class. In our case the permissions boundary denies any sqs related actions on all resources.

  4. we created an IAM User, using the User construct. Let's go over the props we've passed to the User construct:

    • userName - a name for the user. If we didn't specify one, CDK would automatically generate a unique name for us. If we specify a userName, we can't perform updates, that require resource replacement, so it's best to omit this prop unless we really need it.
    • managedPolicies - a list of managed policies to associate with the user.
    • groups - a list of groups the user will be added to
    • permissionsBoundary - use a permissions boundary to set the maximum permissions that an IAM policy could grant the user.

There is also a password prop - the password for the IAM user. You only need to set a password if the user will need to access the AWS Management console.

Let's execute a deployment:

shell
npx cdk deploy

If we take a look at the User in the IAM console, we can see that the user has been created, added to a group and the policies and permissions boundary have all been set:

iam user console

Adding Permissions to an IAM User after creation in AWS CDK #

In order to add additional permissions to a user after creation, we have to use the methods on the user object, for example:

The code for this article is available on GitHub

Let's look at an example that uses the addManagedPolicy and attachInlinePolicy methods.

lib/cdk-starter-stack.ts
import * as iam from '@aws-cdk/aws-iam';
import * as cdk from '@aws-cdk/core';

export class CdkStarterStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props)

    // ...rest

    // ๐Ÿ‘‡ add a managed policy to the user
    user.addManagedPolicy(
      iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonS3ReadOnlyAccess'),
    );

    // ๐Ÿ‘‡ create an inline policy
    const inlinePolicy = new iam.Policy(this, 'cloudwatch-logs-policy', {
      statements: [
        new iam.PolicyStatement({
          actions: ['logs:PutLogEvents'],
          resources: ['*'],
        }),
      ],
    });

    // ๐Ÿ‘‡ attach the inline policy to the user
    user.attachInlinePolicy(inlinePolicy);
  }
}

Let's go over what we did in the code snippet.

  1. we referenced an AWS managed policy and added it to the user with the addManagedPolicy method
  2. we created an inline IAM policy with simple logging permissions
  3. we attached the inline IAM policy to the user, via the attachInlinePolicy method

Let's deploy the changes:

shell
npx cdk deploy

If we take a look at the IAM console, we can see that the user now has 4 permission policies applied to it:

iam user policies

The same approach applies if we wanted to add the IAM user to a group. Then we would create the group and use the addToGroup method on the user object.

Removal Policy of IAM Users in AWS CDK #

When a CDK stack gets deleted, the IAM users provisioned by the stack also get deleted. If you need to override this behavior you can use the applyRemovalPolicy method and set the policy of the user to RETAIN.

However, note that if the user references any resources created by the stack, i.e. groups, policies, permission boundaries, an attempt to delete these resources would fail.

For example trying to delete a group, that a user references, results in an error:

Cannot delete entity, must remove users from group first.

Clean up #

To delete the resources we've provisioned execute the destroy command:

shell
npx cdk destroy

Further Reading #

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee