how.wtf

Create IAM role with multiple principals in AWS CDK

· Thomas Taylor

I need to create an IAM role that is assumable by multiple principals, but the AWS CDK role creation documentation only lists the following example:

 1lambda_role = iam.Role(self, "Role",
 2    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
 3    description="Example role..."
 4)
 5
 6stream = kinesis.Stream(self, "MyEncryptedStream",
 7    encryption=kinesis.StreamEncryption.KMS
 8)
 9
10stream.grant_read(lambda_role)

That works great, but how do I list multiple principals?

Specifying multiple principals for IAM role

Luckily, there is a solution: the CompositePrincipal.

How to use the composite principal with AWS CDK

The CompositePrincipal class enables developers to pass in variadic arguments of type IPrincipal.

In the snippet of code below, I

  1. Create two roles that are assumable by the {"AWS": "*"} principal.
  2. Create a third role that contains a CompositePrincipal for both of the previous roles using iam.ArnPrincipal
  3. Showcase the role arns in a CloudFormation output
 1from os import path
 2
 3import aws_cdk as cdk
 4import aws_cdk.aws_iam as iam
 5
 6
 7class MultiplePrincipalsStack(cdk.Stack):
 8    def __init__(self, scope: cdk.App, construct_id: str, **kwargs) -> None:
 9        super().__init__(scope, construct_id, **kwargs)
10        one = iam.Role(self, "Role1", assumed_by=iam.AnyPrincipal())
11        two = iam.Role(self, "Role2", assumed_by=iam.AnyPrincipal())
12
13        three = iam.Role(
14            self,
15            "RoleWithMultiplePrincipals",
16            assumed_by=iam.CompositePrincipal(
17                iam.ArnPrincipal(one.role_arn), iam.ArnPrincipal(two.role_arn)
18            ),
19        )
20
21        cdk.CfnOutput(self, "RoleArn1", value=one.role_arn)
22        cdk.CfnOutput(self, "RoleArn2", value=two.role_arn)
23        cdk.CfnOutput(self, "RoleArn3", value=three.role_arn)

After running cdk deploy, here are the stack outputs:

1Outputs:
2stack.RoleArn1 = arn:aws:iam::123456789012:role/stack-Role13A5C70C1-2RU2vpUAiHMy
3stack.RoleArn2 = arn:aws:iam::123456789012:role/stack-Role291939BC6-4geKeo5cAu3w
4stack.RoleArn3 = arn:aws:iam::123456789012:role/stack-RoleWithMultiplePrincipals7CD0E21E-Rd9Rxpc2Ioqe

Testing the role assumption

Using the outputs from before, we can verify that everything worked correctly using the AWS CLI.

I assumed Role1 by using the aws sts assume-role command:

1aws sts assume-role \
2    --role-arn arn:aws:iam::123456789012:role/stack-Role13A5C70C1-2RU2vpUAiHMy \
3    --role-session-name test

I exported the credentials from the output then assumed RoleWithMultiplePrincipals:

1aws sts assume-role \
2    --role-arn arn:aws:iam::123456789012:role/stack-RoleWithMultiplePrincipals7CD0E21E-Rd9Rxpc2Ioqe \
3    --role-session-name test2

Everything worked!

#python   #aws   #aws-cdk   #serverless  

Reply to this post by email ↪