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')
Beispiel #2
0
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
Beispiel #3
0
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