コード例 #1
0
def test_role_get_permissions_for_policy_version_no_policies(
        mock_get_permissions_in_policy, role_dict):
    r = Role(**role_dict)
    r.policies = {}
    r.get_permissions_for_policy_version()

    mock_get_permissions_in_policy.assert_not_called()
コード例 #2
0
ファイル: test_roledata.py プロジェクト: PierreLiddle/repokid
    def test_calculate_repo_scores(self, mock_get_repoable_permissions,
                                   mock_get_role_permissions):
        roles = [Role(ROLES[0]), Role(ROLES[1]), Role(ROLES[2])]
        roles[0].disqualified_by = []
        roles[0].aa_data = 'some_aa_data'

        # disqualified by a filter
        roles[1].policies = [{'Policy': ROLE_POLICIES['unused_ec2']}]
        roles[1].disqualified_by = ['some_filter']
        roles[1].aa_data = 'some_aa_data'

        # no AA data
        roles[2].policies = [{'Policy': ROLE_POLICIES['all_services_used']}]
        roles[2].disqualified_by = []
        roles[2].aa_data = None

        mock_get_role_permissions.side_effect = [[
            'iam:AddRoleToInstanceProfile', 'iam:AttachRolePolicy',
            'ec2:AllocateHosts', 'ec2:AssociateAddress'
        ], ['iam:AddRoleToInstanceProfile', 'iam:AttachRolePolicy'
            ], ['iam:AddRoleToInstanceProfile', 'iam:AttachRolePolicy']]

        mock_get_repoable_permissions.side_effect = [
            set(['iam:AddRoleToInstanceProfile', 'iam:AttachRolePolicy'])
        ]

        minimum_age = 90
        repokid.utils.roledata._calculate_repo_scores(roles, minimum_age)

        assert roles[0].repoable_permissions == 2
        assert roles[0].repoable_services == ['iam']
        assert roles[1].repoable_permissions == 0
        assert roles[1].repoable_services == []
        assert roles[2].repoable_permissions == 0
        assert roles[2].repoable_services == []
コード例 #3
0
def test_role_is_eligible_for_repo_stale_aa_data(mock_stale_aa_services, role_dict):
    mock_stale_aa_services.return_value = ["service1", "service2"]
    r = Role(**role_dict)
    eligible, reason = r.is_eligible_for_repo()
    mock_stale_aa_services.assert_called_once()
    assert not eligible
    assert reason == "stale Access Advisor data for service1, service2"
コード例 #4
0
def test_role_fetch_aa_data_no_arn(role_dict):
    role_data = copy.deepcopy(role_dict)
    role_data.pop("arn")
    role_data.pop("account")
    r = Role(**role_data)
    with pytest.raises(ModelError):
        r.fetch_aa_data()
コード例 #5
0
def test_role_is_eligible_for_repo_no_aa_data(mock_stale_aa_services, role_dict):
    r = Role(**role_dict)
    r.aa_data = []
    eligible, reason = r.is_eligible_for_repo()
    mock_stale_aa_services.assert_not_called()
    assert not eligible
    assert reason == "no Access Advisor data available"
コード例 #6
0
def cancel_scheduled_repo(account_number, dynamo_table, role_name=None, is_all=None):
    """
    Cancel scheduled repo for a role in an account
    """
    if not is_all and not role_name:
        LOGGER.error('Either a specific role to cancel or all must be provided')
        return

    if is_all:
        roles = Roles([Role(get_role_data(dynamo_table, roleID))
                      for roleID in role_ids_for_account(dynamo_table, account_number)])

        # filter to show only roles that are scheduled
        roles = [role for role in roles if (role.repo_scheduled)]

        for role in roles:
            set_role_data(dynamo_table, role.role_id, {'RepoScheduled': 0, 'ScheduledPerms': []})

        LOGGER.info('Canceled scheduled repo for roles: {}'.format(', '.join([role.role_name for role in roles])))
        return

    role_id = find_role_in_cache(dynamo_table, account_number, role_name)
    if not role_id:
        LOGGER.warn('Could not find role with name {} in account {}'.format(role_name, account_number))
        return

    role = Role(get_role_data(dynamo_table, role_id))

    if not role.repo_scheduled:
        LOGGER.warn('Repo was not scheduled for role {} in account {}'.format(role.role_name, account_number))
        return

    set_role_data(dynamo_table, role.role_id, {'RepoScheduled': 0, 'ScheduledPerms': []})
    LOGGER.info('Successfully cancelled scheduled repo for role {} in account {}'.format(role.role_name,
                role.account))
コード例 #7
0
def list_role_rollbacks(message: Message) -> ResponderReturn:
    role_id = find_role_in_cache(message.role_name, message.account)

    if not role_id:
        return ResponderReturn(
            successful=False,
            return_message="Unable to find role {} in account {}".format(
                message.role_name, message.account
            ),
        )

    role = Role(role_id=role_id)
    role.fetch(fields=["Policies"])
    return_val = "Restorable versions for role {} in account {}\n".format(
        message.role_name, message.account
    )
    for index, policy_version in enumerate(role.policies):
        total_permissions, _ = get_permissions_in_policy(policy_version["Policy"])
        return_val += "({:>3}):  {:<5}     {:<15}  {}\n".format(
            index,
            len(total_permissions),
            policy_version["Discovered"],
            policy_version["Source"],
        )
    return ResponderReturn(successful=True, return_message=return_val)
コード例 #8
0
def test_role_update_opt_out_future(role_dict):
    r = Role(**role_dict)
    future_dt = datetime.datetime.now() + datetime.timedelta(days=1)
    r.opt_out = {"expire": future_dt.timestamp()}
    r._update_opt_out()
    # opt out should not have been touched since it is not expired
    assert r.opt_out == {"expire": future_dt.timestamp()}
コード例 #9
0
def test_role_mark_inactive(mock_store, role_dict):
    r = Role(**role_dict)
    r.active = True
    r.mark_inactive()
    assert not r.active
    mock_store.assert_called_once()
    assert mock_store.call_args[1]["fields"] == ["Active"]
コード例 #10
0
def test_role_is_eligible_for_repo_disqualified(mock_stale_aa_services, role_dict):
    r = Role(**role_dict)
    r.disqualified_by = ["filter1", "filter2"]
    eligible, reason = r.is_eligible_for_repo()
    mock_stale_aa_services.assert_not_called()
    assert not eligible
    assert reason == "disqualified by filter1, filter2"
コード例 #11
0
def test_role_stale_aa_services(role_dict):
    r = Role(**role_dict)
    r.config["repo_requirements"] = {"oldest_aa_data_days": 5}
    recent_dt = datetime.datetime.now() - datetime.timedelta(days=1)
    older_dt = datetime.datetime.now() - datetime.timedelta(days=14)

    r.aa_data = [
        {
            "serviceName": "service1",
            "lastUpdated": recent_dt.isoformat()
        },
        {
            "serviceName": "service2",
            "lastUpdated": recent_dt.isoformat()
        },
        {
            "serviceName": "service3",
            "lastUpdated": older_dt.isoformat()
        },
        {
            "serviceName": "service4",
            "lastUpdated": older_dt.isoformat()
        },
    ]
    stale = r._stale_aa_services()
    assert "service1" not in stale
    assert "service2" not in stale
    assert "service3" in stale
    assert "service4" in stale
コード例 #12
0
def test_role_is_eligible_for_repo(mock_stale_aa_services, role_dict):
    mock_stale_aa_services.return_value = []
    r = Role(**role_dict)
    eligible, reason = r.is_eligible_for_repo()
    mock_stale_aa_services.assert_called_once()
    assert eligible
    assert not reason
コード例 #13
0
ファイル: repo.py プロジェクト: timstahl/repokid
def _repo_role(
    account_number: str,
    role_name: str,
    config: RepokidConfig,
    hooks: RepokidHooks,
    commit: bool = False,
    scheduled: bool = False,
) -> List[str]:
    """
    Calculate what repoing can be done for a role and then actually do it if commit is set
      1) Check that a role exists, it isn't being disqualified by a filter, and that is has fresh AA data
      2) Get the role's current permissions, repoable permissions, and the new policy if it will change
      3) Make the changes if commit is set
    Args:
        account_number (string)
        role_name (string)
        commit (bool)

    Returns:
        None
    """
    role_id = find_role_in_cache(role_name, account_number)
    # only load partial data that we need to determine if we should keep going
    role = Role(role_id=role_id, config=config)
    role.fetch()
    return role.repo(hooks, commit=commit, scheduled=scheduled)
コード例 #14
0
ファイル: __init__.py プロジェクト: timstahl/repokid
def list_repoable_services(message: Message) -> ResponderReturn:
    role_id = find_role_in_cache(message.role_name, message.account)

    if not role_id:
        return ResponderReturn(
            successful=False,
            return_message="Unable to find role {} in account {}".format(
                message.role_name, message.account),
        )
    else:
        role = Role(role_id=role_id)
        role.fetch(fields=["RepoableServices"])

        (
            repoable_permissions,
            repoable_services,
        ) = get_services_and_permissions_from_repoable(role.repoable_services)

        return ResponderReturn(
            successful=True,
            return_message=
            ("Role {} in account {} has:\n    Repoable Services: \n{}\n\n    Repoable Permissions: \n{}"
             .format(
                 message.role_name,
                 message.account,
                 "\n".join([service for service in repoable_services]),
                 "\n".join([perm for perm in repoable_permissions]),
             )),
        )
コード例 #15
0
def test_role_calculate_repo_scores(
    mock_get_permissions_for_policy_version,
    mock_get_repoable_permissions,
    mock_convert_repoable_perms_to_perms_and_services,
    role_dict,
):
    mock_get_permissions_for_policy_version.return_value = (
        {
            "service1:action1", "service1:action2", "service2",
            "service3:action3"
        },
        {"service1:action2", "service2", "service3:action3"},
    )
    mock_get_repoable_permissions.return_value = {
        "service1:action2", "service2"
    }
    mock_convert_repoable_perms_to_perms_and_services.return_value = (
        {"service1:action2"},
        {"service2"},
    )

    r = Role(**role_dict)
    r.calculate_repo_scores(0, {})

    mock_get_permissions_for_policy_version.assert_called_once()
    mock_get_repoable_permissions.assert_called_once()
    mock_convert_repoable_perms_to_perms_and_services.assert_called_once()
    assert r.total_permissions == 4
    assert r.repoable_services == ["service1:action2", "service2"]
    assert r.repoable_permissions == 2
コード例 #16
0
    def test_log_during_repoable_calculation_batch_hooks(self):
        hooks = {
            "DURING_REPOABLE_CALCULATION_BATCH":
            [log_during_repoable_calculation_batch_hooks]
        }

        input_dict = {
            "role_batch": [Role.parse_obj(ROLES[0]), "def"],
            "potentially_repoable_permissions": [],
            "minimum_age": 1,
        }

        with pytest.raises(repokid.hooks.MissingHookParamaeter):
            # role_batch', 'potentially_repoable_permissions', 'minimum_age'
            repokid.hooks.call_hooks(hooks,
                                     "DURING_REPOABLE_CALCULATION_BATCH",
                                     input_dict)

        input_dict["role_batch"] = [
            Role.parse_obj(ROLES[0]),
            Role.parse_obj(ROLES[1]),
            Role.parse_obj(ROLES[2]),
        ]
        assert input_dict == repokid.hooks.call_hooks(
            hooks, "DURING_REPOABLE_CALCULATION_BATCH", input_dict)
コード例 #17
0
    def test_get_role_permissions(self, mock_all_permissions,
                                  mock_get_actions_from_statement,
                                  mock_expand_policy):
        test_role = Role(ROLES[0])

        all_permissions = [
            "ec2:associateaddress",
            "ec2:attachvolume",
            "ec2:createsnapshot",
            "s3:createbucket",
            "s3:getobject",
        ]

        # empty policy to make sure we get the latest
        test_role.policies = [
            {
                "Policy": ROLE_POLICIES["all_services_used"]
            },
            {
                "Policy": ROLE_POLICIES["unused_ec2"]
            },
        ]

        mock_all_permissions.return_value = all_permissions
        mock_get_actions_from_statement.return_value = ROLE_POLICIES[
            "unused_ec2"]["ec2_perms"]
        mock_expand_policy.return_value = ROLE_POLICIES["unused_ec2"][
            "ec2_perms"]

        total_permissions, eligible_permissions = repokid.utils.roledata._get_role_permissions(
            test_role)
        assert total_permissions == set(
            ROLE_POLICIES["unused_ec2"]["ec2_perms"])
        assert eligible_permissions == set(
            ROLE_POLICIES["unused_ec2"]["ec2_perms"])
コード例 #18
0
ファイル: test_roledata.py プロジェクト: PierreLiddle/repokid
    def test_get_role_permissions(self, mock_all_permissions,
                                  mock_get_actions_from_statement,
                                  mock_expand_policy):
        test_role = Role(ROLES[0])

        all_permissions = [
            'ec2:associateaddress', 'ec2:attachvolume', 'ec2:createsnapshot',
            's3:createbucket', 's3:getobject'
        ]

        # empty policy to make sure we get the latest
        test_role.policies = [{
            'Policy': ROLE_POLICIES['all_services_used']
        }, {
            'Policy': ROLE_POLICIES['unused_ec2']
        }]

        mock_all_permissions.return_value = all_permissions
        mock_get_actions_from_statement.return_value = ROLE_POLICIES[
            'unused_ec2']['ec2_perms']
        mock_expand_policy.return_value = ROLE_POLICIES['unused_ec2'][
            'ec2_perms']

        permissions = repokid.utils.roledata._get_role_permissions(test_role)
        assert permissions == set(ROLE_POLICIES['unused_ec2']['ec2_perms'])
コード例 #19
0
def test_role_fetch(mock_get_role_by_id, role_dict):
    stored_role_data = copy.deepcopy(role_dict)
    stored_role_data["repoable_permissions"] = 20
    mock_get_role_by_id.return_value = stored_role_data
    r = Role(**role_dict)
    assert r.repoable_permissions == 5
    r.fetch()
    assert r.repoable_permissions == 20
コード例 #20
0
def test_role_is_eligible_for_repo_no_repoable_permissions(
        mock_stale_aa_services, role_dict):
    r = Role(**role_dict)
    r.repoable_permissions = []
    eligible, reason = r.is_eligible_for_repo()
    mock_stale_aa_services.assert_not_called()
    assert not eligible
    assert reason == "no repoable permissions"
コード例 #21
0
def test_role_fetch_not_found(role_dict):
    local_role_data = copy.deepcopy(role_dict)
    local_role_data.pop("role_id")
    local_role_data.pop("role_name")
    local_role_data.pop("account")
    r = Role(**local_role_data)
    with pytest.raises(ModelError):
        r.fetch()
コード例 #22
0
def test_role_get_permissions_for_policy_version(
        mock_get_permissions_in_policy, role_dict):
    r = Role(**role_dict)
    r.get_permissions_for_policy_version()

    mock_get_permissions_in_policy.assert_called_once()
    assert mock_get_permissions_in_policy.call_args[0][0] == vars.policies[-1][
        "Policy"]
    assert not mock_get_permissions_in_policy.call_args[1]["warn_unknown_perms"]
コード例 #23
0
def test_role_fetch_not_found(mock_get_role_by_arn, role_dict):
    mock_get_role_by_arn.side_effect = RoleNotFoundError
    local_role_data = copy.deepcopy(role_dict)
    local_role_data.pop("role_id")
    local_role_data.pop("role_name")
    local_role_data.pop("account")
    r = Role(**local_role_data)
    with pytest.raises(RoleNotFoundError):
        r.fetch()
コード例 #24
0
def test_role_get_repoed_policy_no_repoable_services(
        mock_get_services_and_permissions_from_repoable,
        mock_get_repoed_policy, role_dict):
    r = Role(**role_dict)
    r.repoable_services = []
    with pytest.raises(MissingRepoableServices):
        r.get_repoed_policy()
    mock_get_repoed_policy.assert_not_called()
    mock_get_services_and_permissions_from_repoable.assert_not_called()
コード例 #25
0
def test_role_fetch_no_id(mock_get_role_by_name, role_dict):
    stored_role_data = copy.deepcopy(role_dict)
    stored_role_data["repoable_permissions"] = 20
    mock_get_role_by_name.return_value = stored_role_data
    local_role_data = copy.deepcopy(role_dict)
    local_role_data.pop("role_id")
    r = Role(**local_role_data)
    assert r.repoable_permissions == 5
    r.fetch()
    assert r.repoable_permissions == 20
コード例 #26
0
    def test_calculate_repo_scores(self, mock_call_hooks,
                                   mock_get_repoable_permissions,
                                   mock_get_role_permissions):
        roles = [Role(ROLES[0]), Role(ROLES[1]), Role(ROLES[2])]
        roles[0].disqualified_by = []
        roles[0].aa_data = "some_aa_data"

        # disqualified by a filter
        roles[1].policies = [{"Policy": ROLE_POLICIES["unused_ec2"]}]
        roles[1].disqualified_by = ["some_filter"]
        roles[1].aa_data = "some_aa_data"

        # no AA data
        roles[2].policies = [{"Policy": ROLE_POLICIES["all_services_used"]}]
        roles[2].disqualified_by = []
        roles[2].aa_data = None

        hooks = {}

        mock_get_role_permissions.side_effect = [
            (
                [
                    "iam:AddRoleToInstanceProfile",
                    "iam:AttachRolePolicy",
                    "ec2:AllocateHosts",
                    "ec2:AssociateAddress",
                ],
                ["iam:AddRoleToInstanceProfile", "iam:AttachRolePolicy"],
            ),
            (
                ["iam:AddRoleToInstanceProfile", "iam:AttachRolePolicy"],
                ["iam:AddRoleToInstanceProfile", "iam:AttachRolePolicy"],
            ),
            (
                ["iam:AddRoleToInstanceProfile", "iam:AttachRolePolicy"],
                ["iam:AddRoleToInstanceProfile", "iam:AttachRolePolicy"],
            ),
        ]

        mock_call_hooks.return_value = set(
            ["iam:AddRoleToInstanceProfile", "iam:AttachRolePolicy"])
        mock_get_repoable_permissions.side_effect = [
            set(["iam:AddRoleToInstanceProfile", "iam:AttachRolePolicy"])
        ]

        minimum_age = 90
        repokid.utils.roledata._calculate_repo_scores(roles, minimum_age,
                                                      hooks)

        assert roles[0].repoable_permissions == 2
        assert roles[0].repoable_services == ["iam"]
        assert roles[1].repoable_permissions == 0
        assert roles[1].repoable_services == []
        assert roles[2].repoable_permissions == 0
        assert roles[2].repoable_services == []
コード例 #27
0
def test_role_get_repoed_policy(
    mock_get_services_and_permissions_from_repoable, mock_get_repoed_policy, role_dict
):
    mock_get_repoed_policy.return_value = ({"repoed": "woohoo"}, ["old_policy_name"])
    r = Role(**role_dict)
    repoed_policies, deleted_policy_names = r.get_repoed_policy(scheduled=False)
    mock_get_repoed_policy.assert_called_once()
    mock_get_services_and_permissions_from_repoable.assert_not_called()
    assert mock_get_repoed_policy.call_args[0][0] == vars.policies[-1]["Policy"]
    assert mock_get_repoed_policy.call_args[0][1] == set(vars.repoable_services)
    assert repoed_policies == {"repoed": "woohoo"}
    assert deleted_policy_names == ["old_policy_name"]
コード例 #28
0
def test_role_add_policy_version_duplicate(mock_store,
                                           mock_calculate_no_repo_permissions,
                                           role_dict):
    r = Role(**role_dict)
    source = "Fixture"
    fake_policy = vars.policies[0]["Policy"]
    assert len(r.policies) == 1
    r.add_policy_version(fake_policy, source=source, store=True)
    assert len(r.policies) == 1
    assert r.policies[0]["Policy"] == fake_policy
    mock_calculate_no_repo_permissions.assert_not_called()
    mock_store.assert_not_called()
コード例 #29
0
def test_role_store_create(mock_create_dynamodb_entry, mock_get_role_by_id,
                           role_dict, role_dict_with_aliases):
    expected = copy.deepcopy(role_dict_with_aliases)
    mock_get_role_by_id.side_effect = RoleNotFoundError
    r = Role(**role_dict)
    r.store()
    mock_create_dynamodb_entry.assert_called_once()

    # Remove LastUpdated from the fn call and expected dict so we can compare the rest
    mock_create_dynamodb_entry.call_args[0][0].pop("LastUpdated")
    expected.pop("LastUpdated")

    assert mock_create_dynamodb_entry.call_args[0][0] == expected
コード例 #30
0
def test_role_store_remote_updated(mock_get_role_by_id, role_dict,
                                   role_dict_with_aliases):
    expected = copy.deepcopy(role_dict_with_aliases)
    expected.pop("RoleId")
    expected.pop("RoleName")
    expected.pop("Account")

    # simulate the record having been updated in DynamoDB since we last fetched it
    last_updated = (vars.last_updated +
                    datetime.timedelta(hours=2)).strftime("%Y-%m-%d %H:%M")
    mock_get_role_by_id.return_value = {"LastUpdated": last_updated}
    r = Role(**role_dict)
    with pytest.raises(IntegrityError):
        r.store()