IAM Condition Examples in AWS CDK - Complete Guide

avatar

Borislav Hadzhiev

Wed Apr 28 20214 min read

banner

Photo by Robert Bye

In order to set conditions on policies in AWS CDK, we have to use the `conditions` prop.

Table of Contents #

  1. Using IAM Conditions in AWS CDK
  2. Adding Conditions to IAM Policies in AWS CDK
  3. More Examples of Conditions on IAM Policies in AWS CDK

Using IAM Conditions in AWS CDK #

IAM condition blocks let us set conditions that must be met for a policy to take effect.

In order to use conditions in AWS CDK, we have to set the conditions prop when instantiating the PolicyStatement class.

The code for this article is available on GitHub

Let's look at an example, where we create an IAM role and attach policies with conditions to it.

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 role
    const role1 = new iam.Role(this, 'iam-role-id-1', {
      assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
    });

    const policyWithConditions = new iam.PolicyStatement({
      actions: ['ec2:CreateTags', 'ec2:DeleteTags'],
      resources: ['*'],
      // ๐Ÿ‘‡ set condition
      conditions: {
        'ForAllValues:StringEquals': {
          'aws:TagKeys': ['my-tag-key', 'your-tag-key'],
        },
      },
    });

    role1.addToPolicy(policyWithConditions);
  }
}

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

  1. we created an IAM role, that can be assumed by the lambda service (principal)
  2. we created a policy statement with a condition. The policy grants permission to create and delete ec2 tags if a condition is met. The condition controls what tag key names are allowed to be specified in the request. In this case the condition is met only for requests to create or delete tags with a key of my-tag-key or your-tag-key

Let's execute a deployment:

shell
npx cdk deploy

If we take a look at the policy that's attached to the role, we can see that the condition has been set:

condition set policy

Condition key names are case-insensitive, i.e. including the aws:TagKeys condition is equivalent to testing for AWS:TAGKEYS.

Adding Conditions to IAM Policies in AWS CDK #

In order to add condition(s) to an IAM policy in AWS CDK, we have to use the addCondition or addConditions methods on an instance of the PolicyStatement class.

The code for this article is available on GitHub

Let's take a look at an example, where we use both 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 single condition with `addCondition`
    policyWithConditions.addCondition('StringEquals', {
      'ec2:AuthorizedService': 'lambda.amazonaws.com',
    });

    // ๐Ÿ‘‡ add multiple conditions with `addConditions`
    policyWithConditions.addConditions({
      DateLessThan: {
        'aws:CurrentTime': '2022-12-31T23:59:59Z',
      },
      DateGreaterThan: {
        'aws:CurrentTime': '2021-04-27T23:59:59Z',
      },
    });
  }
}

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

  1. we used the addCondition method to add a condition to the IAM policy. The condition is met and the policy takes effect only if lambda is the requester service.
  2. we used the addConditions method to add multiple conditions to the IAM policy. The conditions are met and the policy takes effect only in the specified time frame.

Let's execute a deployment:

shell
npx cdk deploy

After a successful deployment the conditions we added are reflected in the IAM policy:

policy added conditions

More Examples of Conditions on IAM Policies in AWS CDK #

Let's look at another example, we are going to create a second role, which has conditions, that restrict access, based on the names of the objects in s3 buckets.

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);

    // ... rest

    const role2 = new iam.Role(this, 'iam-role-id-2', {
      assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
      description:
        'grants permission to list all of the objects in all s3 buckets under a public prefix',
      inlinePolicies: {
        ListBucketObjectsPolicy: new iam.PolicyDocument({
          statements: [
            new iam.PolicyStatement({
              resources: ['arn:aws:s3:::*'],
              actions: ['s3:ListBucket'],
              // ๐Ÿ‘‡ limit the response of the ListBucket action
              conditions: {
                StringEquals: {
                  's3:prefix': 'public',
                },
              },
            }),
            new iam.PolicyStatement({
              effect: iam.Effect.DENY,
              resources: ['arn:aws:s3:::*'],
              actions: ['s3:ListBucket'],
              // ๐Ÿ‘‡ DENY all but objects with the `public` prefix
              conditions: {
                StringNotEquals: {
                  's3:prefix': 'public',
                },
              },
            }),
          ],
        }),
      }
    }
  }
}

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

  1. we created an IAM role and attached an inline policy to it.

  2. the policy consists of 2 statements. The first statement allows the s3:ListBucket action under the condition that the requester specifies the public prefix. The second statement denies the s3:ListBucket action under the condition that the requester did not specify the public prefix.

    In other words the condition restricts the requester to only be able to list object keys with the public prefix.

Let's execute a deployment:

shell
npx cdk deploy

If we take a look at the policy attached to the second role, we can see that the conditions have been set:

conditions set policy 2

Check out my other article AWS CDK IAM Policy Example - Complete Guide, if you like to read more on creating IAM policies in AWS CDK.

Clean up #

To delete the provisioned resources, 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