aws iam- can a role assume a role and that role assume another role?

Viewed 762

Question same as the title, i want to know if a role and assume a role that can assume another role.

Example: Role A. A Role that is trusted by an external account and it a policy that can assume any role Role B. This role is assumed by A and it also has a policy that can assume Role C. Role C. This role has policy that can access S3 bucket for example.

2 Answers

Yes, you can make roles that assume roles. The process is called Role chaining:

Role chaining occurs when you use a role to assume a second role through the AWS CLI or API.

The key thing to remember about this is that once A assumes B, all permissions of A are lost temporary, and the effective permissions are of the role B. So the permissions of roles A, B and C do not add up.

Idea of Role Chaining:

You get the session of every Role in the Chain, then pass each one to the other, until you reach to final Role, which you will pass to it the final session(session of the role before it) and get the Client you want as s3, iam on the final_target_account.

Scenarios for making Account-Cross-Origin using Role Chaining:

  1. if you have three accounts(main_acc --> second_acc --> third_acc), and you are in your main account and you want to reach to the third account, but you cannot do so, only if you assume a role in the second account(cuz the second account is in the trust-relationship inside the role of the third account) to be able to reach to the third account role, that will give you permissions to do whatever you want to on the third account.
  2. You need to have control on the child accounts under an organization account, to be able to create any resources or infra-structure inside them, here you can assume the role of the Oragnization_main_account(payer), then from there assume the role inside the child_account, then do what you want directly on each child account in the organization.

-Note: There is a Role created by default from AWS side on the child_organization_accounts called AWSControlTowerExecution, please refer to AWS Docs.

How to Role Chaining using AWS Boto3 API:

def get_role_client_credentials(session,
                            session_name,
                            role_arn,
                            external_id=""):
client = session.client('sts')
if external_id:
    assumed_role = client.assume_role(RoleArn=role_arn,
                                      RoleSessionName=session_name,
                                      ExternalId=external_id)
else:
    assumed_role = client.assume_role(RoleArn=role_arn,
                                      RoleSessionName=session_name)
return assumed_role['Credentials']




def get_assumed_client(session,
                   client_name,
                   role_arn,
                   session_name,
                   region,
                   external_id=""):
credentials = get_role_client_credentials(session=session,
                                          session_name=session_name,
                                          role_arn=role_arn,
                                          external_id=external_id)

return session.client(client_name,
                      region_name=region,
                      aws_access_key_id=credentials['AccessKeyId'],                         
                    aws_secret_access_key=credentials['SecretAccessKey'],
                      aws_session_token=credentials['SessionToken'])

#### Role Chaining ######

def get_role_session_credentials(session,
                            session_name,
                            role_arn,
                            external_id=""):
client = session.client('sts')
if external_id:
    assumed_role = client.assume_role(RoleArn=role_arn,
                                      RoleSessionName=session_name,
                                      ExternalId=external_id)
else:
    assumed_role = client.assume_role(RoleArn=role_arn,
                                      RoleSessionName=session_name)
return assumed_role['Credentials']


def get_assumed_role_session(session,
                       role_arn,
                       session_name,
                       region,
                       external_id=""):
credentials = get_role_session_credentials(session,
                                          session_name=session_name,
                                          role_arn=role_arn,
                                          external_id=external_id)

return  boto3.session.Session(
                              region_name=region,                                  
                          aws_access_key_id=credentials['AccessKeyId'],                                
                  aws_secret_access_key=credentials['SecretAccessKey'],                                  
                         aws_session_token=credentials['SessionToken']
                              )

- Use the Above helper Functions This way:

    role_A_arn = f"arn:aws:iam::{second_target_account_id}:role/RoleA"
    assumed_Role_A_session = get_assumed_role_session(session, role_A_arn, 
                                default_session_name, region, external_id="")
    
    role_B_arn = f"arn:aws:iam::{third_target_account_id}:role/RoleB"
    assumed_Role_B_client = get_assumed_client(assumed_Role_A_session, 's3', role_B_arn, different_session_name, region, external_id="")

    assumed_Role_B_client.create_bucket(Bucket='testing-bucket',
                            CreateBucketConfiguration={
                               'LocationConstraint': f'{region}'
                            })
Related