Пример #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_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)
Пример #3
0
    def test_policy_binding_matches_whitelist_rules(self):
        """Test that a policy binding matches the whitelist rules.

        Setup:
            * Create a test policy binding.
            * Create a test rule binding.
            * Create a whitelist rule with the test rules.

        Expected results:
            All policy binding members are in the whitelist.
        """
        test_binding = {
            'role':
            'roles/owner',
            'members': [
                'user:[email protected]',
                'user:[email protected]',
                'group:[email protected]',
                'serviceAccount:[email protected]',
            ]
        }
        rule_bindings = [{
            'role':
            'roles/owner',
            'members': [
                'user:*@company.com',
                'user:abc@*.somewhere.com',
                'group:*@googlegroups.com',
                'serviceAccount:*@*.gserviceaccount.com',
            ]
        }]

        rule = scanner_rules.Rule(
            'test rule',
            0, [IamPolicyBinding.create_from(b) for b in rule_bindings],
            mode='whitelist')
        resource_rule = ire.ResourceRules(rules=[rule])
        results = list(
            resource_rule.find_mismatches(self.project1, test_binding))

        self.assertEqual(0, len(results))
Пример #4
0
    def test_policy_binding_mismatches_required_rules(self):
        """Test that a required list of members mismatches policy binding.

        Setup:
            * Create a test policy binding.
            * Create a test rule binding.
            * Create a required rule with the test rules.

        Expected results:
            All required members are found in the policy.
        """
        test_binding = {
            'role':
            'roles/owner',
            'members': [
                'user:[email protected]',
                'group:[email protected]',
                'serviceAccount:[email protected]',
            ]
        }
        rule_bindings = [{
            'role':
            'roles/owner',
            'members': [
                'user:[email protected]',
                'user:[email protected]',
            ]
        }]

        rule = scanner_rules.Rule(
            'test rule',
            0, [IamPolicyBinding.create_from(b) for b in rule_bindings],
            mode='required')
        resource_rule = ire.ResourceRules(resource=self.project1)
        resource_rule.rules.add(rule)
        results = list(
            resource_rule.find_mismatches(self.project1, test_binding))

        self.assertEqual(1, len(results))
Пример #5
0
    def test_policy_binding_does_not_match_blacklist_rules(self):
        """Test that a policy binding does not match the blacklist.

        Setup:
            * Create a test policy binding.
            * Create a test rule binding.
            * Create a blacklist rule with the test rules.

        Expected results:
            No policy bindings found in the blacklist.
        """
        test_binding = {
            'role': 'roles/owner',
            'members': [
                'user:[email protected]',
            ]
        }
        rule_bindings = [{
            'role':
            'roles/owner',
            'members': [
                'user:*@company.com',
                'user:abc@*.somewhere.com',
                'group:*@googlegroups.com',
                'serviceAccount:*@*.gserviceaccount.com',
            ]
        }]

        rule = scanner_rules.Rule(
            'test rule',
            0, [IamPolicyBinding.create_from(b) for b in rule_bindings],
            mode='blacklist')
        resource_rule = ire.ResourceRules(rules=[rule])
        results = list(
            resource_rule.find_mismatches(self.project1, test_binding))

        self.assertEqual(0, len(results))
Пример #6
0
    def add_rule(self, rule_def, rule_index):
        """Add a rule to the rule book.

        The rule supplied to this method is the dictionary parsed from
        the rules definition file.

        For example, this rule...

            # rules yaml:
            rules:
              - name: a rule
                mode: whitelist
                resource:
                  - type: project
                    applies_to: self
                    resource_ids:
                      - my-project-123
                inherit_from_parents: true
                bindings:
                  - role: roles/editor
                    members:
                      - users:[email protected]

        ... gets parsed into:

            {
                'name': 'a rule',
                'mode': 'whitelist',
                'resource': {
                    'type': 'project',
                    'applies_to': self,
                    'resource_ids': ['my-project-id']
                },
                'inherit_from_parents': true,
                'bindings': [
                    {
                        'role': 'roles/editor',
                        'members': ['users:[email protected]']
                    }
                ]
            }

        Args:
            rule_def (dict): Contains rule definition properties.
            rule_index (int): The index of the rule from the rule definitions.
                Assigned automatically when the rule book is built.
        """
        self._rules_sema.acquire()

        try:
            resources = rule_def.get('resource')

            for resource in resources:
                resource_ids = resource.get('resource_ids')
                resource_type = None
                # TODO: collect these errors and output them in a log.
                # TODO: log the error and keep going
                try:
                    resource_type = resource_mod.ResourceType.verify(
                        resource.get('type'))
                except resource_errors.InvalidResourceTypeError:
                    raise audit_errors.InvalidRulesSchemaError(
                        'Missing resource type in rule {}'.format(rule_index))

                if not resource_ids or len(resource_ids) < 1:
                    raise audit_errors.InvalidRulesSchemaError(
                        'Missing resource ids in rule {}'.format(rule_index))

                # For each resource id associated with the rule, create a
                # mapping of resource => rules.
                for resource_id in resource_ids:
                    gcp_resource = resource_util.create_resource(
                        resource_id=resource_id, resource_type=resource_type)

                    rule_bindings = [
                        iam_policy.IamPolicyBinding.create_from(b)
                        for b in rule_def.get('bindings')
                    ]
                    rule = scanner_rules.Rule(rule_name=rule_def.get('name'),
                                              rule_index=rule_index,
                                              bindings=rule_bindings,
                                              mode=rule_def.get('mode'))

                    rule_applies_to = resource.get('applies_to')
                    rule_key = (gcp_resource, rule_applies_to)

                    # See if we have a mapping of the resource and rule
                    resource_rules = self.resource_rules_map.get(rule_key)

                    # If no mapping exists, create it.
                    if not resource_rules:
                        resource_rules = ResourceRules(
                            resource=gcp_resource,
                            applies_to=rule_applies_to,
                            inherit_from_parents=rule_def.get(
                                'inherit_from_parents', False))
                        self.resource_rules_map[rule_key] = resource_rules

                    # If the rule isn't in the mapping, add it.
                    if rule not in resource_rules.rules:
                        resource_rules.rules.add(rule)
        finally:
            self._rules_sema.release()
Пример #7
0
 def test_invalid_rule_mode_raises_when_create_rule(self):
     """Test that creating a Rule with invalid rule mode raises error."""
     with self.assertRaises(InvalidRulesSchemaError):
         scanner_rules.Rule('exception', 0, [])