Example #1
0
def get_all_users(flags=FLAGS.ACCESS_KEYS | FLAGS.MFA_DEVICES
                  | FLAGS.LOGIN_PROFILE | FLAGS.SIGNING_CERTIFICATES,
                  **conn):
    """
    Returns a list of Users represented as dictionary below:

    {
        "Arn": ...,
        "AccessKeys": ...,
        "CreateDate": ...,  # str
        "InlinePolicies": ...,
        "ManagedPolicies": ...,
        "MFADevices": ...,
        "Path": ...,
        "UserId": ...,
        "UserName": ...,
        "SigningCerts": ...
    }

    :param flags:
    :param conn: dict containing enough information to make a connection to the desired account.
    :return: list of dicts containing fully built out user.
    """

    users = []
    account_users = get_account_authorization_details('User', **conn)

    for user in account_users:
        temp_user = {
            'Arn':
            user['Arn'],
            'CreateDate':
            get_iso_string(user['CreateDate']),
            'GroupList':
            user['GroupList'],
            'InlinePolicies':
            user['UserPolicyList'],
            'ManagedPolicies': [{
                "name": x['PolicyName'],
                "arn": x['PolicyArn']
            } for x in user['AttachedManagedPolicies']],
            'Path':
            user['Path'],
            'UserId':
            user['UserId'],
            'UserName':
            user['UserName']
        }

        user = modify(temp_user, output='camelized')
        _conn_from_args(user, conn)
        users.append(
            registry.build_out(flags,
                               start_with=user,
                               pass_datastructure=True,
                               **conn))

    return users
Example #2
0
def get_all_roles(**conn):
    """
    Returns a List of Roles respresented as dictionary below:

    {
        "Arn": ...,
        "AssumeRolePolicyDocument": ...,
        "CreateDate": ...,  # str
        "InlinePolicies": ...,
        "InstanceProfiles": ...,
        "ManagedPolicies": ...,
        "Path": ...,
        "RoleId": ...,
        "RoleName": ...,
    }

    :param conn: dict containing enough information to make a connection to the desired account.
    :return: list containing dicts or fully built out roles
    """

    roles = []
    account_roles = get_account_authorization_details('Role', **conn)

    for role in account_roles:
        roles.append({
            'Arn':
            role['Arn'],
            'AssumeRolePolicyDocument':
            role['AssumeRolePolicyDocument'],
            'CreateDate':
            str(role['CreateDate']),  # str
            'InlinePolicies':
            role['RolePolicyList'],
            'InstanceProfiles': [{
                'path':
                ip['Path'],
                'instance_profile_name':
                ip['InstanceProfileName'],
                'create_date':
                ip['CreateDate'].strftime('%Y-%m-%dT%H:%M:%SZ'),
                'instance_profile_id':
                ip['InstanceProfileId'],
                'arn':
                ip['Arn']
            } for ip in role['InstanceProfileList']],
            'ManagedPolicies': [{
                "name": x['PolicyName'],
                "arn": x['PolicyArn']
            } for x in role['AttachedManagedPolicies']],
            'Path':
            role['Path'],
            'RoleId':
            role['RoleId'],
            'RoleName':
            role['RoleName']
        })

    return roles
Example #3
0
def test_get_account_authorization_details_role(test_iam):
    """Tests the get_account_authorization API."""
    from cloudaux.aws.iam import get_account_authorization_details

    # Test that we can get the results we expect from get_account_authorization_details
    roles = get_account_authorization_details('Role')
    assert len(roles) == 1
    assert roles[0]['RoleName'] == 'testRoleCloudAuxName'

    users = get_account_authorization_details('User')
    assert len(users) == 1
    assert users[0]['UserName'] == 'testCloudAuxUser'

    groups = get_account_authorization_details('Group')
    assert len(groups) == 1
    assert groups[0]['GroupName'] == 'testCloudAuxGroup'

    local_managed_policies = get_account_authorization_details('LocalManagedPolicy')
    assert len(local_managed_policies) == 1
    assert local_managed_policies[0]['PolicyName'] == 'testCloudAuxPolicy'

    # aws_managed_policies gets updated from time to time so the length might change
    # Just test that we have more than 1
    aws_managed_policies = get_account_authorization_details('AWSManagedPolicy')
    assert len(aws_managed_policies) > 1

    # With no filter supplied:
    with pytest.raises(InvalidAuthorizationFilterException,
                       match='Must provide filter value: User, Role, Group, LocalManagedPolicy, AWSManagedPolicy'):
        get_account_authorization_details(filter='LOLNO')
Example #4
0
 def _fetch(self, account_number: str) -> Dict[str, IAMEntry]:
     logger.info("getting role data for account %s", account_number)
     conn = copy.deepcopy(self.config["connection_iam"])
     conn["account_number"] = account_number
     auth_details = get_account_authorization_details(filter="Role", **conn)
     auth_details_by_id = {item["RoleId"]: item for item in auth_details}
     # convert policies list to dictionary to maintain consistency with old call which returned a dict
     for _, data in auth_details_by_id.items():
         data["RolePolicyList"] = {
             item["PolicyName"]: item["PolicyDocument"]
             for item in data["RolePolicyList"]
         }
     return auth_details_by_id
Example #5
0
def test_get_account_authorization_details_role(test_iam):
    # Test that we can get the results we expect from get_account_authorization_details
    roles = get_account_authorization_details('Role')
    assert len(roles) == 1
    assert roles[0]['RoleName'] == 'testRoleCloudAuxName'

    users = get_account_authorization_details('User')
    assert len(users) == 1
    assert users[0]['UserName'] == 'testCloudAuxUser'

    groups = get_account_authorization_details('Group')
    assert len(groups) == 1
    assert groups[0]['GroupName'] == 'testCloudAuxGroup'

    local_managed_policies = get_account_authorization_details(
        'LocalManagedPolicy')
    assert len(local_managed_policies) == 1
    assert local_managed_policies[0]['PolicyName'] == 'testCloudAuxPolicy'

    # aws_managed_policies gets updated from time to time so the length might change
    # Just test that we have more than 1
    aws_managed_policies = get_account_authorization_details(
        'AWSManagedPolicy')
    assert len(aws_managed_policies) > 1
Example #6
0
def update_role_cache(account_number, dynamo_table, config, hooks):
    """
    Update data about all roles in a given account:
      1) list all the roles and initiate a role object with basic data including name and roleID
      2) get inline policies for each of the roles
      3) build a list of active roles - we'll want to keep data about roles that may have been deleted in case we
         need to restore them, so if we used to have a role and now we don't see it we'll mark it inactive
      4) update data about the roles in Dynamo
      5) mark inactive roles in Dynamo
      6) load and instantiate filter plugins
      7) for each filter determine the list of roles that it filters
      8) update data in Dynamo about filters
      9) get Aardvark data for each role
      10) update Dynamo with Aardvark data
      11) calculate repoable permissions/policies for all the roles
      12) update Dynamo with information about how many total and repoable permissions and which services are repoable
      13) update stats in Dynamo with basic information like total permissions and which filters are applicable

    Args:
        account_number (string): The current account number Repokid is being run against

    Returns:
        None
    """
    conn = config["connection_iam"]
    conn["account_number"] = account_number

    LOGGER.info(
        "Getting current role data for account {} (this may take a while for large accounts)"
        .format(account_number))

    role_data = get_account_authorization_details(filter="Role", **conn)
    role_data_by_id = {item["RoleId"]: item for item in role_data}

    # convert policies list to dictionary to maintain consistency with old call which returned a dict
    for _, data in role_data_by_id.items():
        data["RolePolicyList"] = {
            item["PolicyName"]: item["PolicyDocument"]
            for item in data["RolePolicyList"]
        }

    roles = Roles([Role(rd) for rd in role_data])

    active_roles = []
    LOGGER.info("Updating role data for account {}".format(account_number))
    for role in tqdm(roles):
        role.account = account_number
        current_policies = role_data_by_id[role.role_id]["RolePolicyList"]
        active_roles.append(role.role_id)
        roledata.update_role_data(dynamo_table, account_number, role,
                                  current_policies)

    LOGGER.info("Finding inactive roles in account {}".format(account_number))
    roledata.find_and_mark_inactive(dynamo_table, account_number, active_roles)

    LOGGER.info("Filtering roles")
    plugins = FilterPlugins()

    # Blocklist needs to know the current account
    filter_config = config["filter_config"]
    blocklist_filter_config = filter_config.get(
        "BlocklistFilter", filter_config.get("BlacklistFilter"))
    blocklist_filter_config["current_account"] = account_number

    for plugin_path in config.get("active_filters"):
        plugin_name = plugin_path.split(":")[1]
        if plugin_name == "ExclusiveFilter":
            # ExclusiveFilter plugin active; try loading its config. Also, it requires the current account, so add it.
            exclusive_filter_config = filter_config.get("ExclusiveFilter", {})
            exclusive_filter_config["current_account"] = account_number
        plugins.load_plugin(plugin_path,
                            config=config["filter_config"].get(
                                plugin_name, None))

    for plugin in plugins.filter_plugins:
        filtered_list = plugin.apply(roles)
        class_name = plugin.__class__.__name__
        for filtered_role in filtered_list:
            LOGGER.info("Role {} filtered by {}".format(
                filtered_role.role_name, class_name))
            filtered_role.disqualified_by.append(class_name)

    for role in roles:
        set_role_data(dynamo_table, role.role_id,
                      {"DisqualifiedBy": role.disqualified_by})

    LOGGER.info(
        "Getting data from Aardvark for account {}".format(account_number))
    aardvark_data = get_aardvark_data(config["aardvark_api_location"],
                                      account_number=account_number)

    LOGGER.info("Updating roles with Aardvark data in account {}".format(
        account_number))
    for role in roles:
        try:
            role.aa_data = aardvark_data[role.arn]
        except KeyError:
            LOGGER.warning("Aardvark data not found for role: {} ({})".format(
                role.role_id, role.role_name))
        else:
            set_role_data(dynamo_table, role.role_id, {"AAData": role.aa_data})

    LOGGER.info(
        "Calculating repoable permissions and services for account {}".format(
            account_number))

    batch_processing = config.get("query_role_data_in_batch", False)
    batch_size = config.get("batch_processing_size", 100)
    roledata._calculate_repo_scores(
        roles,
        config["filter_config"]["AgeFilter"]["minimum_age"],
        hooks,
        batch_processing,
        batch_size,
    )
    for role in roles:
        LOGGER.debug(
            "Role {} in account {} has\nrepoable permissions: {}\nrepoable services: {}"
            .format(
                role.role_name,
                account_number,
                role.repoable_permissions,
                role.repoable_services,
            ))
        set_role_data(
            dynamo_table,
            role.role_id,
            {
                "TotalPermissions": role.total_permissions,
                "RepoablePermissions": role.repoable_permissions,
                "RepoableServices": role.repoable_services,
            },
        )

    LOGGER.info("Updating stats in account {}".format(account_number))
    roledata.update_stats(dynamo_table, roles, source="Scan")
Example #7
0
def update_role_cache(account_number, dynamo_table, config, hooks):
    """
    Update data about all roles in a given account:
      1) list all the roles and initiate a role object with basic data including name and roleID
      2) get inline policies for each of the roles
      3) build a list of active roles - we'll want to keep data about roles that may have been deleted in case we
         need to restore them, so if we used to have a role and now we don't see it we'll mark it inactive
      4) update data about the roles in Dynamo
      5) mark inactive roles in Dynamo
      6) load and instantiate filter plugins
      7) for each filter determine the list of roles that it filters
      8) update data in Dynamo about filters
      9) get Aardvark data for each role
      10) update Dynamo with Aardvark data
      11) calculate repoable permissions/policies for all the roles
      12) update Dynamo with information about how many total and repoable permissions and which services are repoable
      13) update stats in Dynamo with basic information like total permissions and which filters are applicable

    Args:
        account_number (string): The current account number Repokid is being run against

    Returns:
        None
    """
    conn = config['connection_iam']
    conn['account_number'] = account_number

    LOGGER.info('Getting current role data for account {} (this may take a while for large accounts)'.format(
        account_number))
    role_data = get_account_authorization_details(filter='Role', **conn)
    role_data_by_id = {item['RoleId']: item for item in role_data}

    # convert policies list to dictionary to maintain consistency with old call which returned a dict
    for _, data in role_data_by_id.items():
        data['RolePolicyList'] = {item['PolicyName']: item['PolicyDocument'] for item in data['RolePolicyList']}

    roles = Roles([Role(rd) for rd in role_data])

    active_roles = []
    LOGGER.info('Updating role data for account {}'.format(account_number))
    for role in tqdm(roles):
        role.account = account_number
        current_policies = role_data_by_id[role.role_id]['RolePolicyList']
        active_roles.append(role.role_id)
        roledata.update_role_data(dynamo_table, account_number, role, current_policies)

    LOGGER.info('Finding inactive roles in account {}'.format(account_number))
    roledata.find_and_mark_inactive(dynamo_table, account_number, active_roles)

    LOGGER.info('Filtering roles')
    plugins = FilterPlugins()

    # Blacklist needs to know the current account
    config['filter_config']['BlacklistFilter']['current_account'] = account_number

    for plugin_path in config.get('active_filters'):
        plugin_name = plugin_path.split(':')[1]
        plugins.load_plugin(plugin_path, config=config['filter_config'].get(plugin_name, None))

    for plugin in plugins.filter_plugins:
        filtered_list = plugin.apply(roles)
        class_name = plugin.__class__.__name__
        for filtered_role in filtered_list:
            LOGGER.info('Role {} filtered by {}'.format(filtered_role.role_name, class_name))
            filtered_role.disqualified_by.append(class_name)

    for role in roles:
        set_role_data(dynamo_table, role.role_id, {'DisqualifiedBy': role.disqualified_by})

    LOGGER.info('Getting data from Aardvark for account {}'.format(account_number))
    aardvark_data = _get_aardvark_data(config['aardvark_api_location'], account_number=account_number)

    LOGGER.info('Updating roles with Aardvark data in account {}'.format(account_number))
    for role in roles:
        try:
            role.aa_data = aardvark_data[role.arn]
        except KeyError:
            LOGGER.warning('Aardvark data not found for role: {} ({})'.format(role.role_id, role.role_name))
        else:
            set_role_data(dynamo_table, role.role_id, {'AAData': role.aa_data})

    LOGGER.info('Calculating repoable permissions and services for account {}'.format(account_number))
    roledata._calculate_repo_scores(roles, config['filter_config']['AgeFilter']['minimum_age'], hooks)
    for role in roles:
        LOGGER.debug('Role {} in account {} has\nrepoable permissions: {}\nrepoable services:'.format(
            role.role_name, account_number, role.repoable_permissions, role.repoable_services
        ))
        set_role_data(dynamo_table, role.role_id, {'TotalPermissions': role.total_permissions,
                                                   'RepoablePermissions': role.repoable_permissions,
                                                   'RepoableServices': role.repoable_services})

    LOGGER.info('Updating stats in account {}'.format(account_number))
    roledata.update_stats(dynamo_table, roles, source='Scan')