Home > Blockchain >  Boto3 list all accounts in an organization from member account
Boto3 list all accounts in an organization from member account

Time:09-12

I have 2 accounts:

  • Account A (Master/Management account)
  • Account B (Member account)

I deployed a Lambda function in Account B(Member account) that lists all the accounts in the organization. Below is the Lambda function code:

import boto3
import json

org_client = boto3.client('organizations')
org_id='o-ib1qmgzn48'

def lambda_handler(event, context):
    account_list = []
    def list_aws_accounts_for_ou(ou_id):
        # add accounts in the current/root OU
        try:
            lafp_paginator = org_client.get_paginator('list_accounts_for_parent')
            lafp_page_iterator = lafp_paginator.paginate(ParentId=org_id)
            for page in lafp_page_iterator:
                for acct in page['Accounts']:
                    account_list.append(acct)
        except org_client.exceptions.ClientError as error:
            print(f'Error: {error}')

        # add accounts in child ous
        try:
            lc_paginator = org_client.get_paginator('list_children')
            ou_page_iterator = lc_paginator.paginate(
                ParentId=org_id,
                ChildType='ORGANIZATIONAL_UNIT'
            )
            for page in ou_page_iterator:
                for child in page['Children']:
                    print(f"Adding accounts from child OU {child['Id']}")
                    account_list  = list_aws_accounts_for_ou(child['Id'])
        except org_client.exceptions.ClientError as error:
            print(f'Error: {error}')

        print(f"Found {len(account_list)} accounts in Oraganization {org_id}")

    return json.loads(json.dumps(account_list, default=str))

This Lambda function has a role(GetAccountsListLambdaRole) with the below permissions: Basic Lambda execution role An inline policy that assumes a role in Account A(Management/Master account)

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::Account A:role/OrganizationsReadAssumeRole"
    }
}

The 'OrganizationsReadAssumeRole' in Account A has the following permissions and trust policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "organizations:ListAccounts",
                "organizations:ListAccountsForParent",
                "organizations:ListChildren"
            ],
            "Resource": "*"
        }
    ]
}

The trust policy is:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::Account B:role/GetAccountsListLambdaRole"
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}

When I run the Lambda function, I'm getting the below errors:

Error: An error occurred (AccessDeniedException) when calling the ListAccountsForParent operation: You don't have permissions to access this resource.
Error: An error occurred (AccessDeniedException) when calling the ListChildren operation: You don't have permissions to access this resource.

I have a couple of questions here:

  1. Whatever I'm trying - getting an account list from a member account; is it possible? If yes, how can I resolve the above errors and achieve this?

Please help.

CodePudding user response:

You need to actually assume the OrganizationsReadAssumeRole role in the lambda. This blog has an example:

sts_connection = boto3.client('sts')
acct_a = sts_connection.assume_role( 
    RoleArn="arn:aws:iam::222222222222:role/OrganizationsReadAssumeRole",
    RoleSessionName="cross_acct_lambda"
)

ACCESS_KEY = acct_a['Credentials']['AccessKeyId']
SECRET_KEY = acct_a['Credentials']['SecretAccessKey']
SESSION_TOKEN = acct_a['Credentials']['SessionToken']

# create service client using the assumed role credentials, e.g. S3
org_client = boto3.client(
    'organizations',
    aws_access_key_id=ACCESS_KEY,
    aws_secret_access_key=SECRET_KEY,
    aws_session_token=SESSION_TOKEN,
)
... # rest of your code

Replace 222222222222 with the AWS account ID of the cross-account role that your function is assuming.

  • Related