Search code examples
pythonamazon-web-servicesboto3amazon-rds

Python boto3 get all RDS instance list of an organization


Let's say I have an organization which contains 25 aws account where each account may or may not contains some reserved RDS instance. So I need to use boto3 to connect my organization and iterate each account to check that RDS reserved instance. What I do on a single account level to check RDS instances.

This Code will list all RDS instances present in the single account

Sample Code

#!/usr/bin/env python
import boto3
client = boto3.client('rds')
response = 
client.describe_db_instances()
for i in response['DBInstances']:
   db_name = i['DBName']
   db_instance_name = i['DBInstanceIdentifier']
   db_type = i['DBInstanceClass']
   db_storage = i['AllocatedStorage']
   db_engine = i['Engine']
   print (db_instance_name,db_type,db_storage,db_engine)

So my question is how to connect to organization level, list each accounts RDS reserved instances? And what type/level of credentials I need to use?


Solution

  • One way to do this is using a common role. The prerequisite for this approach is that a role, which has access to make the necessary API calls, needs to exist in each of the accounts that belong to the organization. You then assume this common role to perform API calls in the target accounts. This sort of setup is outlined at https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_access.html.

    With that role in place, you can run boto3 code to find all the accounts in your organization--something like this perhaps:

    org_client = boto3.client('organizations')
    root_id = org_client.list_roots()['Roots'][0]['Id']
    LOGGER.info('root ID: %s', root_id)
    paginator = org_client.get_paginator('list_organizational_units_for_parent')
    response_iterator = paginator.paginate(ParentId=root_id)
    for item in response_iterator:
        for ou in item['OrganizationalUnits']:
            ou_paginator = org_client.get_paginator('list_accounts_for_parent')
            ou_response_iterator = ou_paginator.paginate(ParentId=ou['Id'])
            for ou_item in ou_response_iterator:
                for account in ou_item['Accounts']:
                    account_id = account['Id']
                    //next, assume a role in this account
    

    Then, the next step is to assume the role, with code similar to what is shown at https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-api.html. Build the RoleARN below (arn:aws:iam::account-of-role-to-assume:role/name-of-role) using the account ID from above and the common role name:

    import boto3
    
    # The calls to AWS STS AssumeRole must be signed with the access key ID
    # and secret access key of an existing IAM user or by using existing temporary 
    # credentials such as those from another role. (You cannot call AssumeRole 
    # with the access key for the root account.) The credentials can be in 
    # environment variables or in a configuration file and will be discovered 
    # automatically by the boto3.client() function. For more information, see the 
    # Python SDK documentation: 
    # http://boto3.readthedocs.io/en/latest/reference/services/sts.html#client
    
    # create an STS client object that represents a live connection to the 
    # STS service
    sts_client = boto3.client('sts')
    
    # Call the assume_role method of the STSConnection object and pass the role
    # ARN and a role session name.
    assumed_role_object=sts_client.assume_role(
        RoleArn="arn:aws:iam::account-of-role-to-assume:role/name-of-role",
        RoleSessionName="AssumeRoleSession1"
    )
    
    # From the response that contains the assumed role, get the temporary 
    # credentials that can be used to make subsequent API calls
    credentials=assumed_role_object['Credentials']
    
    # Use the temporary credentials that AssumeRole returns to make a 
    # connection to Amazon S3  
    rds_client=boto3.client(
        'rds',
        aws_access_key_id=credentials['AccessKeyId'],
        aws_secret_access_key=credentials['SecretAccessKey'],
        aws_session_token=credentials['SessionToken'],
    )
    

    You can query RDS to find any instances and add any that are found to a list. After you are done iterating through all the accounts in the organization, you should have a complete list across all accounts that belong to the organization.