Using Boto3 to find Users and HostRoles with certain AWS Policy

Recently I was asked to scour multiple AWS accounts to find any users or host role that had the S3FullAccess policy applied.    So I came up with the following that will go through all users and roles to identify the ones with the S3FullAccess policy assigned.

You can use this as a skeleton to search for any policy across many accounts at once.

Sure does beat using the GUI and visually checking each user and role.

For this example, I opted to just create a simple Text File with the output. It was simple and all that was needed. I’m sure you could change that to use any sort of output format if you wish. You could also add more sophistication my making the target group a passed in parameter instead of how I hard coded it into this example. So I hope this is enough to get you started.

import boto3
import json

def iam_list(account=None, id=None, secret=None):
    # fout is the output string in this function.   I will add to this string and return it to the main(). 
    fout = '\n\n-'.ljust(50, '-') + '\n' + account + '\n-'.ljust(50, '-') + '\n\n'
    # Create session into local account using assumed role or with id/key pairs
    iamres = boto3.resource('iam', region_name='us-east-1',
                            aws_access_key_id=id,
                            aws_secret_access_key=secret
    )
    iamclient = boto3.client('iam', region_name='us-east-1',
                            aws_access_key_id=id,
                            aws_secret_access_key=secret
    )
    ec2client = boto3.client('ec2', region_name='us-east-1',
                            aws_access_key_id=id,
                            aws_secret_access_key=secret
    )
    s3full = iamres.Policy('arn:aws:iam::aws:policy/AmazonS3FullAccess')

    fout += 'S3FullAccess Policy is attached to ' + str(s3full.attachment_count) + ' items.\n'

    # Do the Attached Groups
    fout += '\nAttached Groups:\n'
    for each_attachment in s3full.attached_groups.all():
        fout += 'Group:\n'
        fout += '    ' + each_attachment.group_name + '\n'
        fout += '    With Members:\n'
        for each_member in each_attachment.users.all():
            fout += '        ' + each_member.name + ' with arn: ' +  each_member.arn + '\n'

    # Do the Attached Users
    fout += '\nAttached Users:\n'
    for each_attachment in s3full.attached_users.all():
        fout += '    ' + each_attachment.user_name + ' with ' + each_attachment.arn + '\n'

    # Do the Attached Roles
    fout += '\nAttached Roles:\n'
    for each_attached_role in s3full.attached_roles.all():
        fout += '    ' + each_attached_role.role_name + ' with ' + each_attached_role.arn + '\n'
        fout += '    In Use on these hosts:\n'
        hostcount = 0
        for each_profile in each_attached_role.instance_profiles.all():
            ec2list = ec2client.describe_instances()
            # I need the attached role name after the last / to match the ec2 iaminstanceprofile['Arn']
            targetarn = each_attached_role.arn.split('/')[-1]
            for each_res in ec2list['Reservations']:
                for each_ec2 in each_res['Instances']:
                    try:
                        target1 = each_ec2['IamInstanceProfile']
                        targetec2arn = target1['Arn']
                        splittargetec2arn = targetec2arn.split('/')[-1]
                        if targetarn == splittargetec2arn:
                            hostcount += 1
                            for each_tag in each_ec2['Tags']:
                                if each_tag['Key'] == 'Name':
                                    fout += '        ' + each_tag['Value'] + '\n'
                    except:
                        pass
        if hostcount ==0:
            fout += '        Not Found on any Host\n'
        fout += '\n'

    return fout


def main():
    outstr = ''
    outstr += iam_list(account='account1', id='account1key', secret='account1secretkey')
    outstr += iam_list(account='account2', id='account2key', secret='account2secretkey')
    outstr += iam_list(account='account3', id='account3key', secret='account3secretkey')
    # Add more accounts as needed. 

    with open("/home/ubuntu/iam_group_report_report.txt", "w") as the_file:
        the_file.write(outstr)


if __name__== "__main__":
    main()
Tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

Solve : *
23 − 1 =