Beispiel #1
0
    def test_find_monitor_change(self):
        RUNTIME_AUDITORS.clear()
        RUNTIME_WATCHERS.clear()
        find_changes(['TEST_ACCOUNT'], ['s3'])

        self.assertEqual(first=len(RUNTIME_WATCHERS.keys()),
                         second=1,
                         msg="Should run one watchers but ran {}".format(
                             len(RUNTIME_WATCHERS.keys())))

        expected_auditor_count = 0
        for au in auditor_registry['s3']:
            expected_auditor_count = expected_auditor_count + 1
            au_list = RUNTIME_AUDITORS[au.__name__]
            self.assertEqual(
                first=len(au_list),
                second=1,
                msg="Auditor {} should run once but ran {} time(s)".format(
                    au.__name__, len(au_list)))

        self.assertEqual(first=len(RUNTIME_AUDITORS.keys()),
                         second=expected_auditor_count,
                         msg="Should run {} auditor but ran {}".format(
                             expected_auditor_count,
                             len(RUNTIME_AUDITORS.keys())))
    def test_find_account_changes(self):
        RUNTIME_AUDITORS.clear()
        RUNTIME_WATCHERS.clear()
        find_changes(['TEST_ACCOUNT'], watcher_registry.keys())

        expected_watcher_count = 0
        expected_auditor_count = 0
        for key in orig_watcher_registry:
            expected_watcher_count = expected_watcher_count + 1
            wa_list = RUNTIME_WATCHERS[orig_watcher_registry[key].__name__]
            self.assertEqual(first=len(wa_list), second=1,
                             msg="Watcher {} should run once but ran {} time(s)"
                             .format(orig_watcher_registry[key].__name__, len(wa_list)))
            for au in auditor_registry[orig_watcher_registry[key].index]:
                expected_auditor_count = expected_auditor_count + 1
                au_list = RUNTIME_AUDITORS[au.__name__]
                self.assertEqual(first=len(au_list), second=1,
                                 msg="Auditor {} should run once but ran {} time(s)"
                                 .format(au.__name__, len(au_list)))

        self.assertEqual(first=len(RUNTIME_WATCHERS.keys()), second=expected_watcher_count,
                         msg="Should run {} watchers but ran {}"
                         .format(expected_watcher_count, len(RUNTIME_WATCHERS.keys())))

        self.assertEqual(first=len(RUNTIME_AUDITORS.keys()), second=expected_auditor_count,
                         msg="Should run {} auditor(s) but ran {}"
                         .format(expected_auditor_count, len(RUNTIME_AUDITORS.keys())))
Beispiel #3
0
    def test_find_account_changes(self):
        RUNTIME_AUDITORS.clear()
        RUNTIME_WATCHERS.clear()
        find_changes(['TEST_ACCOUNT'], watcher_registry.keys())

        expected_watcher_count = 0
        expected_auditor_count = 0
        for key in orig_watcher_registry:
            expected_watcher_count = expected_watcher_count + 1
            wa_list = RUNTIME_WATCHERS[orig_watcher_registry[key].__name__]
            self.assertEqual(
                first=len(wa_list),
                second=1,
                msg="Watcher {} should run once but ran {} time(s)".format(
                    orig_watcher_registry[key].__name__, len(wa_list)))
            for au in auditor_registry[orig_watcher_registry[key].index]:
                expected_auditor_count = expected_auditor_count + 1
                au_list = RUNTIME_AUDITORS[au.__name__]
                self.assertEqual(
                    first=len(au_list),
                    second=1,
                    msg="Auditor {} should run once but ran {} time(s)".format(
                        au.__name__, len(au_list)))

        self.assertEqual(first=len(RUNTIME_WATCHERS.keys()),
                         second=expected_watcher_count,
                         msg="Should run {} watchers but ran {}".format(
                             expected_watcher_count,
                             len(RUNTIME_WATCHERS.keys())))

        self.assertEqual(first=len(RUNTIME_AUDITORS.keys()),
                         second=expected_auditor_count,
                         msg="Should run {} auditor(s) but ran {}".format(
                             expected_auditor_count,
                             len(RUNTIME_AUDITORS.keys())))
Beispiel #4
0
    def test_find_all_changes(self):
        from security_monkey.scheduler import find_changes
        build_mock_result(watcher_configs, auditor_configs)

        find_changes(['TEST_ACCOUNT1', 'TEST_ACCOUNT2'],
                     ['index1', 'index2', 'index3'])

        watcher_keys = RUNTIME_WATCHERS.keys()
        self.assertEqual(first=3,
                         second=len(watcher_keys),
                         msg="Should run 3 watchers but ran {}".format(
                             len(watcher_keys)))

        self.assertTrue('index1' in watcher_keys, msg="Watcher index1 not run")
        self.assertTrue('index2' in watcher_keys, msg="Watcher index3 not run")
        self.assertTrue('index3' in watcher_keys, msg="Watcher index3 not run")

        self.assertEqual(
            first=2,
            second=len(RUNTIME_WATCHERS['index1']),
            msg="Watcher index1 should run twice but ran {} times".format(
                len(RUNTIME_WATCHERS['index1'])))
        self.assertEqual(
            first=2,
            second=len(RUNTIME_WATCHERS['index2']),
            msg="Watcher index2 should run twice but ran {} times".format(
                len(RUNTIME_WATCHERS['index2'])))
        self.assertEqual(
            first=2,
            second=len(RUNTIME_WATCHERS['index3']),
            msg="Watcher index2 should run twice but ran {} times".format(
                len(RUNTIME_WATCHERS['index3'])))

        auditor_keys = RUNTIME_AUDIT_COUNTS.keys()
        self.assertEqual(first=3,
                         second=len(auditor_keys),
                         msg="Should run 3 auditors but ran {}".format(
                             len(auditor_keys)))

        self.assertTrue('index1' in auditor_keys, msg="Auditor index1 not run")
        self.assertTrue('index2' in auditor_keys, msg="Auditor index2 not run")
        self.assertTrue('index3' in auditor_keys, msg="Auditor index3 not run")

        self.assertEqual(
            first=2,
            second=RUNTIME_AUDIT_COUNTS['index1'],
            msg="Auditor index1 should have audited 2 items but audited {}".
            format(RUNTIME_AUDIT_COUNTS['index1']))
        self.assertEqual(
            first=2,
            second=RUNTIME_AUDIT_COUNTS['index2'],
            msg="Auditor index2 should have audited 2 items but audited {}".
            format(RUNTIME_AUDIT_COUNTS['index2']))
        self.assertEqual(
            first=2,
            second=RUNTIME_AUDIT_COUNTS['index3'],
            msg="Auditor index3 should have audited 2 items but audited {}".
            format(RUNTIME_AUDIT_COUNTS['index3']))
    def test_find_account_changes(self):
        from security_monkey.scheduler import find_changes
        build_mock_result(watcher_configs, auditor_configs)

        find_changes(['TEST_ACCOUNT1'],
                     ['index1', 'index2', 'index3'])

        watcher_keys = RUNTIME_WATCHERS.keys()
        self.assertEqual(first=3, second=len(watcher_keys),
                         msg="Should run 3 watchers but ran {}"
                         .format(len(watcher_keys)))

        self.assertTrue('index1' in watcher_keys,
                        msg="Watcher index1 not run")
        self.assertTrue('index2' in watcher_keys,
                        msg="Watcher index3 not run")
        self.assertTrue('index3' in watcher_keys,
                        msg="Watcher index3 not run")

        self.assertEqual(first=1, second=len(RUNTIME_WATCHERS['index1']),
                         msg="Watcher index1 should run once but ran {} times"
                         .format(len(RUNTIME_WATCHERS['index1'])))
        self.assertEqual(first=1, second=len(RUNTIME_WATCHERS['index2']),
                         msg="Watcher index2 should run once but ran {} times"
                         .format(len(RUNTIME_WATCHERS['index2'])))
        self.assertEqual(first=1, second=len(RUNTIME_WATCHERS['index3']),
                         msg="Watcher index2 should run once but ran {} times"
                         .format(len(RUNTIME_WATCHERS['index3'])))

        auditor_keys = RUNTIME_AUDIT_COUNTS.keys()
        self.assertEqual(first=3, second=len(auditor_keys),
                         msg="Should run 3 auditors but ran {}"
                         .format(len(auditor_keys)))

        self.assertTrue('index1' in auditor_keys,
                        msg="Auditor index1 not run")
        self.assertTrue('index2' in auditor_keys,
                        msg="Auditor index2 not run")
        self.assertTrue('index3' in auditor_keys,
                        msg="Auditor index3 not run")

        self.assertEqual(first=1, second=RUNTIME_AUDIT_COUNTS['index1'],
                         msg="Auditor index1 should have audited 1 item but audited {}"
                         .format(RUNTIME_AUDIT_COUNTS['index1']))
        self.assertEqual(first=1, second=RUNTIME_AUDIT_COUNTS['index2'],
                         msg="Auditor index2 should have audited 1 item but audited {}"
                         .format(RUNTIME_AUDIT_COUNTS['index2']))
        self.assertEqual(first=1, second=RUNTIME_AUDIT_COUNTS['index3'],
                         msg="Auditor index3 should have audited 1 item but audited {}"
                         .format(RUNTIME_AUDIT_COUNTS['index3']))
    def test_find_monitor_change(self):
        RUNTIME_AUDITORS.clear()
        RUNTIME_WATCHERS.clear()
        find_changes(['TEST_ACCOUNT'], ['s3'])

        self.assertEqual(first=len(RUNTIME_WATCHERS.keys()), second=1,
                         msg="Should run one watchers but ran {}"
                         .format(len(RUNTIME_WATCHERS.keys())))

        expected_auditor_count = 0
        for au in auditor_registry['s3']:
            expected_auditor_count = expected_auditor_count + 1
            au_list = RUNTIME_AUDITORS[au.__name__]
            self.assertEqual(first=len(au_list), second=1,
                             msg="Auditor {} should run once but ran {} time(s)"
                             .format(au.__name__, len(au_list)))

        self.assertEqual(first=len(RUNTIME_AUDITORS.keys()), second=expected_auditor_count,
                         msg="Should run {} auditor but ran {}"
                         .format(expected_auditor_count, len(RUNTIME_AUDITORS.keys())))
Beispiel #7
0
    def test_find_batch_changes(self):
        """
        Runs through a full find job via the IAMRole watcher, as that supports batching.

        However, this is mostly testing the logic through each function call -- this is
        not going to do any boto work and that will instead be mocked out.
        :return:
        """
        from security_monkey.scheduler import find_changes
        from security_monkey.monitors import Monitor
        from security_monkey.watchers.iam.iam_role import IAMRole
        from security_monkey.auditors.iam.iam_role import IAMRoleAuditor

        test_account = Account(name="TEST_ACCOUNT1")
        watcher = IAMRole(accounts=[test_account.name])

        technology = Technology(name="iamrole")
        db.session.add(technology)
        db.session.commit()

        watcher.batched_size = 3  # should loop 4 times

        self.add_roles()

        # Set up the monitor:
        batched_monitor = Monitor(IAMRole, test_account)
        batched_monitor.watcher = watcher
        batched_monitor.auditors = [
            IAMRoleAuditor(accounts=[test_account.name])
        ]

        import security_monkey.scheduler
        security_monkey.scheduler.get_monitors = lambda x, y, z: [
            batched_monitor
        ]

        # Moto screws up the IAM Role ARN -- so we need to fix it:
        original_slurp_list = watcher.slurp_list
        original_slurp = watcher.slurp

        def mock_slurp_list():
            items, exception_map = original_slurp_list()

            for item in watcher.total_list:
                item["Arn"] = "arn:aws:iam::012345678910:role/{}".format(
                    item["RoleName"])

            return items, exception_map

        def mock_slurp():
            batched_items, exception_map = original_slurp()

            for item in batched_items:
                item.arn = "arn:aws:iam::012345678910:role/{}".format(
                    item.name)
                item.config["Arn"] = item.arn
                item.config["RoleId"] = item.name  # Need this to stay the same

            return batched_items, exception_map

        watcher.slurp_list = mock_slurp_list
        watcher.slurp = mock_slurp

        find_changes([test_account.name], test_account.name)

        # Check that all items were added to the DB:
        assert len(Item.query.all()) == 11

        # Check that we have exactly 11 item revisions:
        assert len(ItemRevision.query.all()) == 11

        # Check that there are audit issues for all 11 items:
        assert len(ItemAudit.query.all()) == 11

        # Delete one of the items:
        # Moto lacks implementation for "delete_role" (and I'm too lazy to submit a PR :D) -- so need to create again...
        mock_iam().stop()
        mock_sts().stop()
        self.add_roles(initial=False)

        # Run the it again:
        watcher.current_account = None  # Need to reset the watcher
        find_changes([test_account.name], test_account.name)

        # Check that nothing new was added:
        assert len(Item.query.all()) == 11

        # There should be the same number of issues and 2 more revisions:
        assert len(ItemAudit.query.all()) == 11
        assert len(ItemRevision.query.all()) == 13

        # Check that the deleted roles show as being inactive:
        ir = ItemRevision.query.join((Item, ItemRevision.id == Item.latest_revision_id)) \
            .filter(Item.arn.in_(
                ["arn:aws:iam::012345678910:role/roleNumber9",
                 "arn:aws:iam::012345678910:role/roleNumber10"])).all()

        assert len(ir) == 2
        assert not ir[0].active
        assert not ir[1].active

        # Finally -- test with a slurp list exception (just checking that things don't blow up):
        def mock_slurp_list_with_exception():
            import security_monkey.watchers.iam.iam_role
            security_monkey.watchers.iam.iam_role.list_roles = lambda **kwargs: 1 / 0

            items, exception_map = original_slurp_list()

            assert len(exception_map) > 0
            return items, exception_map

        watcher.slurp_list = mock_slurp_list_with_exception
        watcher.current_account = None  # Need to reset the watcher
        find_changes([test_account.name], test_account.name)

        mock_iam().stop()
        mock_sts().stop()
    def test_find_batch_changes(self):
        """
        Runs through a full find job via the IAMRole watcher, as that supports batching.

        However, this is mostly testing the logic through each function call -- this is
        not going to do any boto work and that will instead be mocked out.
        :return:
        """
        from security_monkey.scheduler import find_changes
        from security_monkey.monitors import Monitor
        from security_monkey.watchers.iam.iam_role import IAMRole
        from security_monkey.auditors.iam.iam_role import IAMRoleAuditor

        test_account = Account(name="TEST_ACCOUNT1")
        watcher = IAMRole(accounts=[test_account.name])

        technology = Technology(name="iamrole")
        db.session.add(technology)
        db.session.commit()

        watcher.batched_size = 3  # should loop 4 times

        self.add_roles()

        # Set up the monitor:
        batched_monitor = Monitor(IAMRole, test_account)
        batched_monitor.watcher = watcher
        batched_monitor.auditors = [IAMRoleAuditor(accounts=[test_account.name])]

        import security_monkey.scheduler
        security_monkey.scheduler.get_monitors = lambda x, y, z: [batched_monitor]

        # Moto screws up the IAM Role ARN -- so we need to fix it:
        original_slurp_list = watcher.slurp_list
        original_slurp = watcher.slurp

        def mock_slurp_list():
            exception_map = original_slurp_list()

            for item in watcher.total_list:
                item["Arn"] = "arn:aws:iam::012345678910:role/{}".format(item["RoleName"])

            return exception_map

        def mock_slurp():
            batched_items, exception_map = original_slurp()

            for item in batched_items:
                item.arn = "arn:aws:iam::012345678910:role/{}".format(item.name)
                item.config["Arn"] = item.arn
                item.config["RoleId"] = item.name  # Need this to stay the same

            return batched_items, exception_map

        watcher.slurp_list = mock_slurp_list
        watcher.slurp = mock_slurp

        find_changes([test_account.name], test_account.name)

        # Check that all items were added to the DB:
        assert len(Item.query.all()) == 11

        # Check that we have exactly 11 item revisions:
        assert len(ItemRevision.query.all()) == 11

        # Check that there are audit issues for all 11 items:
        assert len(ItemAudit.query.all()) == 11

        # Delete one of the items:
        # Moto lacks implementation for "delete_role" (and I'm too lazy to submit a PR :D) -- so need to create again...
        mock_iam().stop()
        mock_sts().stop()
        self.add_roles(initial=False)

        # Run the it again:
        watcher.current_account = None  # Need to reset the watcher
        find_changes([test_account.name], test_account.name)

        # Check that nothing new was added:
        assert len(Item.query.all()) == 11

        # There should be 2 less issues and 2 more revisions:
        assert len(ItemAudit.query.all()) == 9
        assert len(ItemRevision.query.all()) == 13

        # Check that the deleted roles show as being inactive:
        ir = ItemRevision.query.join((Item, ItemRevision.id == Item.latest_revision_id)) \
            .filter(Item.arn.in_(
                ["arn:aws:iam::012345678910:role/roleNumber9",
                 "arn:aws:iam::012345678910:role/roleNumber10"])).all()

        assert len(ir) == 2
        assert not ir[0].active
        assert not ir[1].active

        # Finally -- test with a slurp list exception (just checking that things don't blow up):
        def mock_slurp_list_with_exception():
            import security_monkey.watchers.iam.iam_role
            security_monkey.watchers.iam.iam_role.list_roles = lambda **kwargs: 1 / 0

            exception_map = original_slurp_list()

            assert len(exception_map) > 0
            return exception_map

        watcher.slurp_list = mock_slurp_list_with_exception
        watcher.current_account = None  # Need to reset the watcher
        find_changes([test_account.name], test_account.name)

        mock_iam().stop()
        mock_sts().stop()