def test_admin_verified_for_group_member(self): admin_policy = Policy( 'arn:aws:iam::000000000000:group/admins', 'inline_admin', { 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Action': '*', 'Resource': '*' }] }) admin_group = Group('arn:aws:iam::000000000000:group/admins', [admin_policy]) not_admin_group = Group('arn:aws:iam::000000000000:group/losers', []) new_node_1 = Node('arn:aws:iam::000000000000:user/node_1', 'id1', [], [admin_group], None, None, 1, False, False, None, False, None) new_node_2 = Node('arn:aws:iam::000000000000:user/node_2', 'id2', [], [not_admin_group], None, None, 1, False, False, None, False, None) update_admin_status([new_node_1, new_node_2]) self.assertTrue(new_node_1.is_admin, 'Member of admin group should be marked as an admin') self.assertFalse( new_node_2.is_admin, 'Member of non-admin group should not be marked as an admin')
def get_unfilled_groups(iamclient, nodes: List[Node]) -> List[Group]: """Using an IAM.Client object, returns a list of Group objects. Adds to each passed Node's group_memberships property. Does not set Policy objects. Those have to be filled in later. Writes high-level progress information to parameter output """ result = [] # paginate through groups and build result logger.info("Obtaining IAM groups in the account.") group_paginator = iamclient.get_paginator('list_groups') for page in group_paginator.paginate(PaginationConfig={'PageSize': 25}): logger.debug('list_groups page: {}'.format(page)) for group in page['Groups']: result.append(Group(arn=group['Arn'], attached_policies=[])) # loop through group memberships logger.info("Connecting IAM users to their groups.") for node in nodes: if not arns.get_resource(node.arn).startswith('user/'): continue # skip when not an IAM user logger.debug('finding groups for user {}'.format(node.arn)) user_name = arns.get_resource(node.arn)[5:] if '/' in user_name: user_name = user_name.split('/')[-1] logger.debug('removed path from username {}'.format(user_name)) group_list = iamclient.list_groups_for_user(UserName=user_name) for group in group_list['Groups']: for group_obj in result: if group['Arn'] == group_obj.arn: node.group_memberships.append(group_obj) return result
def get_nodes_groups_and_policies(iamclient) -> dict: """Using an IAM.Client object, return a dictionary containing nodes, groups, and policies to be added to a Graph object. Admin status for the nodes are not updated. Writes high-level information on progress to the output stream. """ logger.info('Obtaining IAM Users/Roles/Groups/Policies in the account.') result_paginator = iamclient.get_paginator( 'get_account_authorization_details') user_results = [] group_results = [] role_results = [] policy_results = [] for page in result_paginator.paginate(): user_results += page['UserDetailList'] group_results += page['GroupDetailList'] role_results += page['RoleDetailList'] policy_results += page['Policies'] logger.info( 'Sorting users, roles, groups, policies, and their relationships.') # this is the result we return: dictionary with nodes/groups/users all filled out result = {'nodes': [], 'groups': [], 'policies': []} for p in policy_results: # go through each policy and update policy_results doc = [ x['Document'] for x in p['PolicyVersionList'] if x['IsDefaultVersion'] ][0] result['policies'].append(Policy(p['Arn'], p['PolicyName'], doc)) for g in group_results: # go through all inline policies and update policy_results group_policies = [] if 'GroupPolicyList' in g: # have to key-check these for p in g['GroupPolicyList']: group_policies.append( Policy( g['Arn'], # inline policies get the same Arn as their principal p['PolicyName'], p['PolicyDocument'])) result[ 'policies'] += group_policies # this is just adding the inline policies for the group for p in g['AttachedManagedPolicies']: group_policies.append( _get_policy_by_arn_or_raise(p['PolicyArn'], result['policies'])) result['groups'].append(Group(g['Arn'], group_policies)) for u in user_results: # go through all inline policies and update policy_results user_policies = [] if 'UserPolicyList' in u: # have to key-check these for p in u['UserPolicyList']: user_policies.append( Policy( u['Arn'], # inline policies inherit the Arn of their principal for the purposes of tracking p['PolicyName'], p['PolicyDocument'])) result['policies'] += user_policies for p in u['AttachedManagedPolicies']: user_policies.append( _get_policy_by_arn_or_raise(p['PolicyArn'], result['policies'])) if 'PermissionsBoundary' in u: boundary_policy = _get_policy_by_arn_or_raise( u['PermissionsBoundary']['PermissionsBoundaryArn'], result['policies']) else: boundary_policy = None group_list = [] for group_name in u['GroupList']: for group in result['groups']: if arns.get_resource(group.arn).split('/')[-1] == group_name: group_list.append(group) break _tags = {} if 'Tags' in u: for tag in u['Tags']: _tags[tag['Key']] = tag['Value'] # still need to figure out access keys result['nodes'].append( Node(u['Arn'], u['UserId'], user_policies, group_list, None, None, 0, 'PasswordLastUsed' in u, False, boundary_policy, False, _tags)) for r in role_results: # go through all inline policies and update policy_results role_policies = [] for p in r['RolePolicyList']: role_policies.append( Policy( r['Arn'], # inline policies inherit the Arn of their principal for the purposes of tracking p['PolicyName'], p['PolicyDocument'])) result['policies'] += role_policies for p in r['AttachedManagedPolicies']: role_policies.append( _get_policy_by_arn_or_raise(p['PolicyArn'], result['policies'])) _tags = {} if 'Tags' in r: for tag in r['Tags']: _tags[tag['Key']] = tag['Value'] result['nodes'].append( Node(r['Arn'], r['RoleId'], role_policies, None, r['AssumeRolePolicyDocument'], [x['Arn'] for x in r['InstanceProfileList']], 0, False, False, None, False, _tags)) logger.info("Obtaining Access Keys data for IAM users") for node in result['nodes']: if arns.get_resource(node.arn).startswith('user/'): # Grab access-key count and update node user_name = arns.get_resource(node.arn)[5:] if '/' in user_name: user_name = user_name.split('/')[-1] access_keys_data = iamclient.list_access_keys(UserName=user_name) node.access_keys = len(access_keys_data['AccessKeyMetadata']) # logger.debug('Access Key Count for {}: {}'.format(user_name, len(access_keys_data['AccessKeyMetadata']))) logger.info('Gathering MFA virtual device information') mfa_paginator = iamclient.get_paginator('list_virtual_mfa_devices') for page in mfa_paginator.paginate(AssignmentStatus='Assigned'): for device in page['VirtualMFADevices']: user_arn = device['User']['Arn'] logger.debug('Found virtual MFA device for {}'.format(user_arn)) for node in result['nodes']: if node.arn == user_arn: node.has_mfa = True break logger.info('Gathering MFA physical device information') for node in result['nodes']: node_resource_name = arns.get_resource(node.arn) if node_resource_name.startswith('user/'): user_name = node_resource_name.split('/')[-1] mfa_devices_response = iamclient.list_mfa_devices( UserName=user_name) if len(mfa_devices_response['MFADevices']) > 0: node.has_mfa = True return result