示例#1
0
    def test_add_single_rule_builds_correct_map(self):
        """Test that adding a single rule builds the correct map."""
        rule_book = ire.IamRuleBook(test_rules.RULES1, self.fake_timestamp)
        actual_rules = rule_book.resource_rules_map

        # expected
        rule_bindings = [{
            'role': 'roles/*',
            'members': ['user:*@company.com']
        }]
        rule = scanner_rules.Rule(
            'my rule',
            0, [IamPolicyBinding.create_from(b) for b in rule_bindings],
            mode='whitelist')
        expected_org_rules = ire.ResourceRules(self.org789,
                                               rules=set([rule]),
                                               applies_to='self_and_children')
        expected_proj1_rules = ire.ResourceRules(self.project1,
                                                 rules=set([rule]),
                                                 applies_to='self')
        expected_proj2_rules = ire.ResourceRules(self.project2,
                                                 rules=set([rule]),
                                                 applies_to='self')
        expected_rules = {
            (self.org789, 'self_and_children'): expected_org_rules,
            (self.project1, 'self'): expected_proj1_rules,
            (self.project2, 'self'): expected_proj2_rules
        }

        self.assertEqual(expected_rules, actual_rules)
示例#2
0
    def test_org_whitelist_rules_vs_policy_no_violations(self):
        """Test ruleset on an org with whitelist with no rule violations.

        Setup:
            * Create a RulesEngine with RULES1 rule set.
            * Create policy.

        Expected result:
            * Find no rule violations.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(test_rules.RULES1,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        policy = {
            'bindings': [{
                'role': 'roles/editor',
                'members': [
                    'user:[email protected]',
                ]
            }]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.org789, policy))

        self.assertItemsEqual(set(), actual_violations)
示例#3
0
    def test_empty_policy_with_rules_no_violations(self):
        """Test an empty policy against the RulesEngine with rules.

        Setup:
            * Create a RulesEngine.
            * Created expected violations list.

        Expected results:
            No policy violations found.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(test_rules.RULES1,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, {}))

        # expected
        expected_violations = set()

        self.assertEqual(expected_violations, actual_violations)
示例#4
0
    def test_org_project_inherit_org_rule_violation(self):
        """Test org with blacklist and child with whitelist, no inherit.

        Test that the project whitelist rule overrides the org blacklist rule
        when the project does not inherit from parent.

        Setup:
            * Create a RulesEngine with RULES5 rule set.
            * Create policy.

        Expected result:
            * Find 1 rule violation.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules5 = copy.deepcopy(test_rules.RULES5)
        rules5['rules'][1]['inherit_from_parents'] = True
        rules_engine.rule_book = ire.IamRuleBook(rules5, self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(
            side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        project_policy = {
            'bindings': [
                {
                    'role': 'roles/owner',
                    'members': [
                        'user:[email protected]',
                    ]
                }
            ]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, project_policy)
        )

        # expected
        expected_outstanding_proj = {
            'roles/owner': [
                IamPolicyMember.create_from('user:[email protected]')
            ]
        }

        expected_violations = set([
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='org blacklist',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='ADDED',
                role=project_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding_proj['roles/owner'])),
        ])

        self.assertItemsEqual(expected_violations, actual_violations)
示例#5
0
    def test_one_member_mismatch(self):
        """Test a policy where one member mismatches the whitelist.

        Setup:
            * Create a RulesEngine and add test_rules.RULES1.
            * Create the policy binding.
            * Create the Rule and rule bindings.
            * Create the resource association for the Rule.

        Expected results:
            One policy binding member missing from the whitelist.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(test_rules.RULES1,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': ['user:[email protected]', 'user:[email protected]']
            }]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, policy))

        # expected
        rule_bindings = [{
            'role': 'roles/*',
            'members': ['user:*@company.com']
        }]
        rule = scanner_rules.Rule(
            'my rule',
            0, [IamPolicyBinding.create_from(b) for b in rule_bindings],
            mode='whitelist')
        expected_outstanding = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }
        expected_violations = set([
            scanner_rules.RuleViolation(
                resource_type=self.project1.type,
                resource_id=self.project1.id,
                rule_name=rule.rule_name,
                rule_index=rule.rule_index,
                role='roles/editor',
                violation_type=scanner_rules.VIOLATION_TYPE.get(rule.mode),
                members=tuple(expected_outstanding['roles/editor']))
        ])

        self.assertEqual(expected_violations, actual_violations)
示例#6
0
    def test_org_2_child_rules_report_violation(self):
        """Test org "children" whitelist works with org "children" blacklist.

        Test that org children whitelist with org children blacklist rules
        report violation.

        Setup:
            * Create a RulesEngine with RULES6 rule set.
            * Create policy.

        Expected result:
            * Find 1 rule violation.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(
            test_rules.RULES6, self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(
            side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        project_policy = {
            'bindings': [
                {
                    'role': 'roles/owner',
                    'members': [
                        'user:[email protected]',
                    ]
                }
            ]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, project_policy)
        )

        # expected
        expected_outstanding_proj = {
            'roles/owner': [
                IamPolicyMember.create_from('user:[email protected]')
            ]
        }

        expected_violations = set([
            scanner_rules.RuleViolation(
                rule_index=1,
                rule_name='project blacklist',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='ADDED',
                role=project_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding_proj['roles/owner'])),
        ])

        self.assertItemsEqual(expected_violations, actual_violations)
示例#7
0
    def test_folder_rule_whitelist(self):
        """Test a simple folder whitelist rule."""
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook({}, test_rules.FOLDER_RULES1,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(
            side_effect=[[self.org789], [self.folder1, self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        # one violation for folder because of organization 778899
        # one violation for project because of project3's parent
        folder_policy = {
            'bindings': [{
                'role': 'roles/editor',
                'members': [
                    'user:[email protected]',
                ]
            }]
        }

        project_policy = {
            'bindings': [{
                'role': 'roles/editor',
                'members': [
                    'user:[email protected]',
                ]
            }]
        }

        actual_violations = set(
            itertools.chain(
                rules_engine.find_policy_violations(self.folder1,
                                                    folder_policy),
                rules_engine.find_policy_violations(self.project3,
                                                    project_policy)))

        # expected
        expected_outstanding = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }

        expected_violations = set([
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='folder rule 1',
                resource_id=self.folder1.id,
                resource_type=self.folder1.type,
                violation_type='ADDED',
                role=project_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding['roles/editor'])),
        ])
        self.assertItemsEqual(expected_violations, actual_violations)
示例#8
0
    def test_org_project_noinherit_project_overrides_org_rule(self):
        """Test org with blacklist and child with whitelist, no inherit.

        Test that the project whitelist rule overrides the org blacklist rule
        when the project does not inherit from parent.

        Setup:
            * Create a RulesEngine with RULES5 rule set.
            * Create policy.

        Expected result:
            * Find 0 rule violations.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(
            test_rules.RULES5, self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(
            side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        project_policy = {
            'bindings': [
                {
                    'role': 'roles/owner',
                    'members': [
                        'user:[email protected]',
                    ]
                }
            ]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, project_policy)
        )

        # expected
        expected_outstanding_proj = {
            'roles/editor': [
                IamPolicyMember.create_from('user:[email protected]')
            ]
        }

        expected_violations = set([])

        self.assertItemsEqual(expected_violations, actual_violations)
示例#9
0
    def test_org_self_bl_proj_noinherit_wl_no_violation(self):
        """Test proj policy doesn't violate rule b/l user (org), w/l (project).

        Test that an org with a blacklist on the org level plus a project
        whitelist with no rule inheritance allows the user blacklisted by
        the org, on the project level.

        Setup:
            * Create a RulesEngine with RULES5 rule set.
            * Tweak the rules to make the org blacklist apply to "self".
            * Create policy.

        Expected result:
            * Find 0 rule violations.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules5 = copy.deepcopy(test_rules.RULES5)
        rules5['rules'][0]['resource'][0]['applies_to'] = 'self'
        rules_engine.rule_book = ire.IamRuleBook(rules5, self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(
            side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        project_policy = {
            'bindings': [{
                    'role': 'roles/owner',
                    'members': [
                        'user:[email protected]',
                    ]
                }]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, project_policy)
        )

        # expected
        expected_violations = set([])

        self.assertItemsEqual(expected_violations, actual_violations)
示例#10
0
    def test_policy_with_no_rules_has_no_violations(self):
        """Test a policy against an empty RuleBook.

        Setup:
            * Create a Rules Engine
            * Create the policy bindings.
            * Created expected violations list.

        Expected results:
            No policy violations found.
        """
        self.mock_org_rel_dao.find_ancestors = mock.MagicMock(
            side_effect=[self.org789])

        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(
            {}, snapshot_timestamp=self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': ['user:[email protected]', 'user:[email protected]']
            }]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, policy))

        # expected
        expected_violations = set()

        self.assertEqual(expected_violations, actual_violations)
示例#11
0
    def test_no_mismatch(self):
        """Test a policy where no members mismatch the whitelist.

        Setup:
            * Create a RulesEngine and add test_rules.RULES1.
            * Create the policy binding.
            * Create the Rule and rule bindings.
            * Create the resource association for the Rule.

        Expected results:
            No policy binding members missing from the whitelist.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(test_rules.RULES1,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': ['user:[email protected]', 'user:[email protected]']
            }]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, policy))

        # expected
        expected_violations = set()

        self.assertEqual(expected_violations, actual_violations)
示例#12
0
    def test_org_self_rules_work_with_org_child_rules(self):
        """Test org "self" whitelist works with org "children" whitelist

        Test hierarchical rules.

        Setup:
            * Create a RulesEngine with RULES4 rule set.
            * Create policy.

        Expected result:
            * Find 3 rule violations.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(test_rules.RULES4,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[], [self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        org_policy = {
            'bindings': [{
                'role':
                'roles/owner',
                'members': [
                    'user:[email protected]',
                    'user:[email protected]',
                ]
            }]
        }

        project_policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': [
                    'user:[email protected]',
                    'user:[email protected]',
                ]
            }]
        }

        actual_violations = set(
            itertools.chain(
                rules_engine.find_policy_violations(self.org789, org_policy),
                rules_engine.find_policy_violations(self.project1,
                                                    project_policy)))

        # expected
        expected_outstanding_org = {
            'roles/owner':
            [IamPolicyMember.create_from('user:[email protected]')]
        }
        expected_outstanding_proj = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }

        expected_violations = set([
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='org whitelist',
                resource_id=self.org789.id,
                resource_type=self.org789.type,
                violation_type='ADDED',
                role=org_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding_org['roles/owner'])),
            scanner_rules.RuleViolation(
                rule_index=1,
                rule_name='project whitelist',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='ADDED',
                role=project_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding_proj['roles/editor'])),
        ])

        self.assertItemsEqual(expected_violations, actual_violations)
示例#13
0
    def test_org_proj_rules_vs_policy_has_violations(self):
        """Test rules on org and project with whitelist, blacklist, required.

        Test whitelist, blacklist, and required rules against an org that has
        1 blacklist violation and a project that has 1 whitelist violation and
        1 required violation.

        Setup:
            * Create a RulesEngine with RULES3 rule set.
            * Create policy.

        Expected result:
            * Find 3 rule violations.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook(test_rules.RULES3,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[], [self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        org_policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': [
                    'user:[email protected]',
                    'user:[email protected]',
                ]
            }]
        }

        project_policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': [
                    'user:[email protected]',
                    'user:[email protected]',
                ]
            }]
        }

        actual_violations = set(
            itertools.chain(
                rules_engine.find_policy_violations(self.org789, org_policy),
                rules_engine.find_policy_violations(self.project1,
                                                    project_policy),
            ))

        # expected
        expected_outstanding_org = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }
        expected_outstanding_project = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')],
            'roles/viewer':
            [IamPolicyMember.create_from('user:[email protected]')]
        }

        expected_violations = set([
            scanner_rules.RuleViolation(
                rule_index=1,
                rule_name='my blacklist rule',
                resource_id=self.org789.id,
                resource_type=self.org789.type,
                violation_type='ADDED',
                role=org_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding_org['roles/editor'])),
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='my whitelist rule',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='ADDED',
                role=project_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding_project['roles/editor'])),
            scanner_rules.RuleViolation(
                rule_index=2,
                rule_name='my required rule',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='REMOVED',
                role='roles/viewer',
                members=tuple(expected_outstanding_project['roles/viewer'])),
        ])

        self.assertItemsEqual(expected_violations, actual_violations)
示例#14
0
    def test_whitelist_blacklist_rules_vs_policy_has_violations(self):
        """Test a ruleset with whitelist and blacklist violating rules.

        Setup:
            * Mock find_ancestors().
            * Create a RulesEngine with RULES2 rule set.
            * Create policy.

        Expected result:
            * Find 1 rule violation.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path,
                                          self.fake_timestamp)
        # TODO: mock the rules local path to return RULES2
        rules_engine.rule_book = ire.IamRuleBook(test_rules.RULES2,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        find_ancestor_mock = mock.MagicMock(side_effect=[[self.org789], []])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': [
                    'user:[email protected]', 'user:[email protected]',
                    'user:[email protected]'
                ]
            }]
        }

        actual_violations = set(
            itertools.chain(
                rules_engine.find_policy_violations(self.project1, policy),
                rules_engine.find_policy_violations(self.project2, policy)))

        # expected
        expected_outstanding1 = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }
        expected_outstanding2 = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }

        expected_violations = set([
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='my rule',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='ADDED',
                role=policy['bindings'][0]['role'],
                members=tuple(expected_outstanding1['roles/editor'])),
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='my rule',
                resource_type=self.project2.type,
                resource_id=self.project2.id,
                violation_type='ADDED',
                role=policy['bindings'][0]['role'],
                members=tuple(expected_outstanding1['roles/editor'])),
            scanner_rules.RuleViolation(
                rule_index=1,
                rule_name='my other rule',
                resource_type=self.project2.type,
                resource_id=self.project2.id,
                violation_type='ADDED',
                role=policy['bindings'][0]['role'],
                members=tuple(expected_outstanding2['roles/editor'])),
            scanner_rules.RuleViolation(
                rule_index=2,
                rule_name='required rule',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='REMOVED',
                role='roles/viewer',
                members=tuple([
                    IamPolicyMember.create_from(
                        'user:[email protected]')
                ]))
        ])

        self.assertItemsEqual(expected_violations, actual_violations)
示例#15
0
    def test_wildcard_resources_with_project_whitelist(self):
        """Test whitelisted wildcard resources.

        Setup:
            * Create a RulesEngine with RULES9 rule set.
            * Create policy.

        Expected result:
            * Find 2 rule violations:
               - A policy binding that violates the org whitelist.
               - A policy binding that violates the org whitelist, even though
                 the project whitelist allows it.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = ire.IamRulesEngine(rules_local_path)
        rules_engine.rule_book = ire.IamRuleBook({}, test_rules.RULES9,
                                                 self.fake_timestamp)
        rules_engine.rule_book.org_res_rel_dao = mock.MagicMock()
        # have to return 2 [self.org789] because the find_ancestors() call is
        # called twice, once for each find_violations().
        find_ancestor_mock = mock.MagicMock(
            side_effect=[[self.org789], [self.org789]])
        rules_engine.rule_book.org_res_rel_dao.find_ancestors = \
            find_ancestor_mock

        project_policy = {
            'bindings': [
                {
                    'role':
                    'roles/owner',
                    'members': [
                        'user:[email protected]',
                        'user:[email protected]',
                        'user:[email protected]',
                    ]
                },
                {
                    'role': 'roles/editor',
                    'members': [
                        'user:[email protected]',
                    ]
                },
            ]
        }

        actual_violations = set(
            rules_engine.find_policy_violations(self.project1, project_policy))

        # expected
        # [email protected] not in any whitelists
        # [email protected] is allowed by the project whitelist
        # but we still alert due to the org whitelist.
        expected_outstanding_proj = {
            'roles/owner': [
                IamPolicyMember.create_from('user:[email protected]'),
                IamPolicyMember.create_from(
                    'user:[email protected]'),
            ],
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }

        expected_violations = set([
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='org whitelist',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='ADDED',
                role=project_policy['bindings'][0]['role'],
                members=tuple(expected_outstanding_proj['roles/owner'])),
            scanner_rules.RuleViolation(
                rule_index=0,
                rule_name='org whitelist',
                resource_id=self.project1.id,
                resource_type=self.project1.type,
                violation_type='ADDED',
                role=project_policy['bindings'][1]['role'],
                members=tuple(expected_outstanding_proj['roles/editor'])),
        ])

        self.assertItemsEqual(expected_violations, actual_violations)