Borislav Hadzhiev
Reading timeยท4 min
Photo from Unsplash
IAM Policies define specific permissions needed to access AWS resources and can be associated with IAM users, roles or groups.
In order to create IAM policies in AWS CDK, we use the Policy
constructs,
for example:
Let's start by creating a Policy with the PolicyDocument construct, which takes an array of PolicyStatement instances.
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 a Policy Document (Collection of Policy Statements) const filterLogEvents = new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ resources: ['arn:aws:logs:*:*:log-group:/aws/lambda/*'], actions: ['logs:FilterLogEvents'], // ๐ Default for `effect` is ALLOW effect: iam.Effect.ALLOW, }), ], }); // ๐ Create role, to which we'll attach our Policies const role = new iam.Role(this, 'example-iam-role', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), description: 'An example IAM role in AWS CDK', inlinePolicies: { // ๐ attach the Policy Document as inline policies FilterLogEvents: filterLogEvents, }, }); } }
Let's go over the code snippet:
We used the PolicyDocument
class, which takes a statements
prop. The
statements
prop is an array of policy statement instances.
We passed the following 3 props when instantiating the PolicyStatement class:
resources
- a list of ARNs of resources to add to the policy statementactions
- a list of actions to add to the policy statementeffect
- whether the actions
in the policy statement should be allowed
or denied. Note that by default effect
is set to ALLOW
so we could've
skipped passing effect
altogetherWe created an IAM role, to which we attached the policy document.
Let's run the deploy
command:
npx aws-cdk deploy
If we take a look at the permission policy of the role we've created, we can see
that the FilterLogEvents
policy has been attached to the role:
In order to use managed policies in AWS CDK, we have to use the
fromManagedPolicy*
methods on the
ManagedPolicy
construct, for example:
Let's use the fromAwsManagedPolicyName
method to import a policy that AWS
manages:
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 // ๐ Use an AWS Managed Policy const managedPolicy = iam.ManagedPolicy.fromAwsManagedPolicyName( 'service-role/AWSLambdaBasicExecutionRole', ); // ๐ attach the Managed Policy to the Role role.addManagedPolicy(managedPolicy); } }
Notice that in the call to fromAwsManagedPolicyName
method, we prefixed the
policy name with service-role/
. Some managed policies have a prefix of
service-role/
, others - job-function/
and others have no prefix at all.
Since we always have to include the prefix along with the policy name, the best way to check if a managed policy has a prefix is to look at its ARN.
If we take a look at the ARN of the AWSLambdaBasicExecutionRole
policy, we can
see the service-role/
prefix which we have to include.
In order to create a statement in an IAM Policy, we have to use the PolicyStatement 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 a Policy using the generic Construct const putLogEventsPolicy = new iam.Policy(this, 'cw-logs', { statements: [ new iam.PolicyStatement({ actions: ['logs:PutLogEvents'], resources: ['*'], }), ], }); // ๐ attach the Policy to the role role.attachInlinePolicy(putLogEventsPolicy); // ๐ Create a Policy Statement const createLogStreams = new iam.PolicyStatement({ actions: ['logs:CreateLogGroup', 'logs:CreateLogStream'], resources: ['*'], }); // ๐ Attach policy to Role role.addToPolicy(createLogStreams); } }
We used the Policy
and PolicyStatement
classes to create IAM Policies. The
Policy
class takes a statements
prop, which is an array of PolicyStatement
instances.
Notice how we didn't pass the effect
prop when instantiating the
PolicyStatement
class. The default value for effect
is Effect.ALLOW
. If
you want to override this behavior you should set effect
to Effect.DENY
.
Let's deploy the updated resources:
npx aws-cdk deploy
If we take a look at the IAM role we've provisioned, we can see that it has 4 permission policies attached to it:
To delete the resources we've provisioned, run the destroy
command:
npx aws-cdk destroy