def _list_entities_to_transform(self, report: RuntimeReport, without_unused: bool, without_consolidated_groups: bool) -> dict: iam_raw_data = report.get_raw_data() raw_entities_to_transform = { 'Users': copy.copy(iam_raw_data['AccountUsers']), 'Roles': copy.copy(iam_raw_data['AccountRoles']), 'Policies': copy.copy(iam_raw_data['AccountPolicies']), 'Groups': copy.copy(iam_raw_data['AccountGroups']) } if without_unused: unused = report.get_unused() unused_entities = unused['Users'] + unused['Roles'] + unused['Policies'] + unused['Groups'] + unused['PolicyAttachments'] self.logger.warn(f'Filtering out {len(unused_entities)} entities from terraform. These entities will have to be handled manually') for user in unused['Users']: raw_entities_to_transform['Users'].remove(user) for role in unused['Roles']: raw_entities_to_transform['Roles'].remove(role) for group in unused['Groups']: raw_entities_to_transform['Groups'].remove(group) for policy in unused['Policies']: raw_entities_to_transform['Policies'].remove(policy) for policy_attachment_obj in unused['PolicyAttachments']: if 'Role' in policy_attachment_obj: TerraformTransformer.remove_from_transformation(policy_attachment_obj, raw_entities_to_transform, 'Role') elif 'User' in policy_attachment_obj: TerraformTransformer.remove_from_transformation(policy_attachment_obj, raw_entities_to_transform, 'User') elif 'Group' in policy_attachment_obj: TerraformTransformer.remove_from_transformation(policy_attachment_obj, raw_entities_to_transform, 'Group') # todo: iterate over users fix group attachments # todo: if without_unused, delete older groups # if not without_consolidated_groups: return raw_entities_to_transform
def report_groupings(report_with_recommendations: RuntimeReport): simple_user_clusters = report_with_recommendations.get_user_groups() admins = simple_user_clusters['Admins'] read_only = simple_user_clusters['ReadOnly'] powerusers = simple_user_clusters['Powerusers'] print( colored( f'\nThe following {len(admins["Users"])} users require admin access to the account:', 'yellow', attrs=['bold'])) for user in admins['Users']: print(colored('Admin: ', 'red', attrs=['bold']) + user) print() if len(powerusers['Users']) > 0: print(f'The following {len(powerusers["Users"])} users require ' + colored('partial write', 'yellow', attrs=['bold']) + ' access to the account:') for user in powerusers['Users']: print(colored('Poweruser: '******'yellow', attrs=['bold']) + user) print() if len(read_only['Users']) > 0: print( colored( f'The following {len(read_only["Users"])} users require ReadOnly access to the account:', 'grey', attrs=['bold'])) for user in read_only['Users']: print(colored('ReadOnly: ', 'green') + user)
def report_unused(runtime_results: RuntimeReport) -> None: print(f'Identifying unused IAM entities in the account...\n') time.sleep(2) unused = runtime_results.get_unused() unused_users = unused['Users'] if len(unused_users) > 0: print( colored( f'The following {len(unused_users)} users were found to be unused:', 'yellow', attrs=['bold'])) for user in unused_users: print( colored('Unused: ', 'red', attrs=['bold']) + f'{user["UserName"]}: last used {user["LastUsed"]} days ago' ) time.sleep(5) else: print( colored('No unused users were found in the account! Hurray!', color='green')) print() unused_access_keys = unused['UnusedActiveAccessKeys'] if len(unused_access_keys) > 0: print( colored( f'The following {len(unused_access_keys)} active access keys aren\'t being used:', 'yellow', attrs=['bold'])) for access_key_obj in unused_access_keys: print( colored('Unused: ', 'red', attrs=['bold']) + f'{access_key_obj["User"]} used access key #{access_key_obj["AccessKey"]} {access_key_obj["DaysSinceLastUse"]} days ago' ) time.sleep(5) else: print( colored( 'No unused access keys were found in the account! Hurray!', color='green')) print() unused_console_login_profiles = unused['UnusedConsoleLoginProfiles'] if len(unused_console_login_profiles) > 0: print( colored( f'The following {len(unused_console_login_profiles)} users have password access they aren\'t using:', 'yellow', attrs=['bold'])) for console_login_profile in unused_console_login_profiles: has_mfa = console_login_profile['MFAEnabled'] if has_mfa: print( colored(console_login_profile['User'], 'yellow', attrs=['bold']) + ' has password access to the AWS console (with MFA) but hasn\'t used it in the last ' + f'{console_login_profile["DaysSinceLastUse"]} days') else: print( colored(console_login_profile['User'], 'red', attrs=['bold']) + f' has password access to the AWS console ' + colored('WITHOUT MFA', 'red') + f' but hasn\'t used it in the last {console_login_profile["DaysSinceLastUse"]} days' ) time.sleep(5) else: print( colored( 'No unused Console Login Profiles were found in the account! Hurray!', color='green')) print() unused_roles = unused['Roles'] if len(unused_roles) > 0: print( colored(f'The following {len(unused_roles)} roles are unused:', 'yellow', attrs=['bold'])) for role in unused_roles: print( colored('Unused: ', 'red', attrs=['bold']) + f"{role['RoleName']}: last used {role['LastUsed']} days ago" ) time.sleep(5) else: print( colored('No unused roles were found in the account! Hurray!', color='green')) print() unused_groups = unused['Groups'] if len(unused_groups) > 0: print( colored( f'The following {len(unused_groups)} groups are redundant:', 'yellow', attrs=['bold'])) for group in unused_groups: if len(group['AttachedManagedPolicies'] + group['GroupPolicyList']) == 0: msg = ' has no policies attached to it' else: msg = ' has no members' print( colored(group['GroupName'], 'yellow', attrs=['bold']) + msg) time.sleep(5) else: print( colored( 'No redundant groups were found in the account! Hurray!', color='green')) print() unused_policies = unused['Policies'] if len(unused_policies) > 0: print( colored( f'The following {len(unused_policies)} policies are redundant:', 'yellow', attrs=['bold'])) for policy in unused_policies: print( colored(policy['PolicyName'], 'yellow', attrs=['bold']) + f' is not attached to any user, group or role') time.sleep(5) else: print( colored( 'No unattached policies were found in the account! Hurray!', color='green')) print() unused_policy_attachments = unused['PolicyAttachments'] if len(unused_policy_attachments) > 0: print( colored( f'The following {len(unused_policy_attachments)} policy attachments are unused:', 'yellow', attrs=['bold'])) for policy_attachment in unused_policy_attachments: principal = policy_attachment.get( 'Role') or policy_attachment.get( 'User') or policy_attachment.get('Group') print( colored('Policy attached but not used: ', 'yellow', attrs=['bold']) + colored(principal, 'grey', attrs=['bold']) + f' is not using the privileges given by {colored(policy_attachment["PolicyArn"], "red", attrs=["bold"])}' ) time.sleep(5) else: print( colored( 'No unused policy attachments were found in the account! Hurray!', color='green')) print() print( 'If you prefer to to change the current runtime and not move to IaC but the number of entities above is intimidating - consider using ' 'our playbooks, available at: ') print('https://www.bridgecrew.io/')