Borislav Hadzhiev
Reading timeยท5 min
Photo from Unsplash
Policies in AWS define the permissions that allow or deny access to resources.
Managed policies can be reused on multiple IAM entities, as opposed to inline Policies, which are only applied to a single entity.
In this article we are going to go over examples of AWS managed and Customer managed policies.
In order to create a managed policy in CDK, we have to instantiate the ManagedPolicy class and pass it one or more policy statements.
Let's look at a simple example where we create a managed policy and attach it to an IAM role:
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 Role const role = new iam.Role(this, 'iam-role-id', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), description: 'An example IAM role in AWS CDK', }); // ๐ Create a Managed Policy and associate it with the role const managedPolicy = new iam.ManagedPolicy(this, 'managed-policy-id', { description: 'Allows ec2 describe action', statements: [ new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['ec2:Describe'], resources: ['*'], }), ], roles: [role], }); } }
Let's go over what we did in the code snippet.
We created an IAM role by instantiating the
Role
construct. We set the lambda
service as the principal of the role.
We created a managed policy by instantiating the ManagedPolicy class. The props we passed to it are:
description
- a short description of the managed policystatements
- a list of
PolicyStatement
instances. Note that the effect
for policy statements is set to ALLOW
by
default, so we could have omitted the property.roles
- a list of roles to attach the managed policy toLet's run the deploy
command:
npx aws-cdk deploy
After a successful deployment, we can see that the managed policy has been attached to the role:
In order to attach a managed policy to an IAM entity, after the entity has
been created, we have to use the addManagedPolicy
method. This method is
available on instances of the Role
, User
and Group
classes.
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 group and pass it an AWS Managed Policy const group = new iam.Group(this, 'group-id', { managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonS3ReadOnlyAccess'), ], }); // ๐ add a managed policy to a group after creation group.addManagedPolicy(managedPolicy); } }
Let's go over what we did in the code snippet.
addManagedPolicy
method on the group instance to attach the
managed policy to the group.Let's run the deploy
command:
npx aws-cdk deploy
If we take a look at the group we created, we can see that both of our managed policies are attached:
An alternative way to attach a managed policy to an IAM entity is to use the
attachTo*
methods on instances of the
ManagedPolicy
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 User const user = new iam.User(this, 'example-user', { userName: 'example-user', }); // ๐ attach the managed policy to a User managedPolicy.attachToUser(user) } }
We created an IAM user and used the attachToUser
method to attach a managed
policy to it.
In order to add policy statements to a managed policy in CDK, we have to use the addStatements method on a managed policy instance.
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 // ๐ add policy statements to a managed policy managedPolicy.addStatements( new iam.PolicyStatement({ actions: ['sqs:GetQueueUrl'], resources: ['*'], }), ); } }
We used the addStatements
method on a managed policy instance. The method
takes
PolicyStatement
instances.
Let's run the deploy
command:
npx aws-cdk deploy
If we look at the managed policy we provisioned, we can see that the
sqs:GetQueueUrl
action is also permitted on all resources:
In order to import managed policies in AWS CDK, we have to use the from*
static methods on the
ManagedPolicy
construct:
Let's start with an example where we import an AWS 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); // ... rest // ๐ Import an AWS Managed policy const lambdaManagedPolicy = iam.ManagedPolicy.fromAwsManagedPolicyName( 'service-role/AWSLambdaBasicExecutionRole', ); console.log('managed policy arn ๐', lambdaManagedPolicy.managedPolicyArn); } }
We used the fromAwsManagedPolicyName
static method on the ManagedPolicy
class.
Note that we prefixed the policy name with service-role/
. Some managed policy
names have to be prefixed with service-role/
, others with job-function/
and
others don't have a prefix. The prefix should always be included for the
managed policies that have one, otherwise we'd get an error.
The easiest way to see if a managed policy has a prefix is to look at the ARN of the policy, for example:
In the screenshot we can see that the managed policy ARN includes a
service-role/
prefix, which we should specify in the parameter passed to
fromAwsManagedPolicyName
.
In order to import external customer managed policies, we have to use the
fromManagedPolicyName
or fromManagedPolicyArn
static 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 // ๐ Import a Customer Managed Policy by Name const customerManagedPolicyByName = iam.ManagedPolicy.fromManagedPolicyName( this, 'external-policy-by-name', 'YOUR_MANAGED_POLICY_NAME', ); // ๐ Import a Customer Managed Policy by ARN const customerManagedPolicyByArn = iam.ManagedPolicy.fromManagedPolicyArn( this, 'external-policy-by-arn', 'YOUR_MANAGED_POLICY_ARN', ); } }
The third parameter we pass to the fromManagedPolicyName
static method is the
name of the external managed policy we want to import.
The third parameter of the fromManagedPolicyArn
static method is the ARN of
the external managed policy we want to import.
To delete the provisioned resources, execute the destroy
command:
npx aws-cdk destroy