def test_enforcer_force_reload_without_overwrite(self): self.create_config_file('policy.d/a.conf', POLICY_A_CONTENTS) self.create_config_file('policy.d/b.conf', POLICY_B_CONTENTS) # Prepare in memory fake policies. self.enforcer.set_rules({'test': _parser.parse_rule('role:test')}, use_conf=True) self.enforcer.set_rules({'default': _parser.parse_rule('role:fakeZ')}, overwrite=False, # Keeps 'test' role. use_conf=True) self.enforcer.overwrite = False self.enforcer._is_directory_updated = lambda x, y: True # Call enforce(), it will load rules from # policy configuration files, to merge with # existing fake ones. self.assertTrue(self.enforcer.enforce('test', {}, {'roles': ['test']})) # The existing rules have a same key with # new loaded ones will be overwrote. self.assertFalse(self.enforcer.enforce('default', {}, {'roles': ['fakeZ']})) # Check against rule dict again from # enforcer object directly. self.assertIn('test', self.enforcer.rules) self.assertIn('default', self.enforcer.rules) self.assertIn('admin', self.enforcer.rules) loaded_rules = jsonutils.loads(str(self.enforcer.rules)) self.assertEqual(3, len(loaded_rules)) self.assertIn('role:test', loaded_rules['test']) self.assertIn('role:fakeB', loaded_rules['default']) self.assertIn('is_admin:True', loaded_rules['admin'])
def test_enforcer_force_reload_without_overwrite(self): self.create_config_file('policy.d/a.conf', POLICY_A_CONTENTS) self.create_config_file('policy.d/b.conf', POLICY_B_CONTENTS) # Prepare in memory fake policies. self.enforcer.set_rules({'test': _parser.parse_rule('role:test')}, use_conf=True) self.enforcer.set_rules( {'default': _parser.parse_rule('role:fakeZ')}, overwrite=False, # Keeps 'test' role. use_conf=True) self.enforcer.overwrite = False # Call enforce(), it will load rules from # policy configuration files, to merge with # existing fake ones. self.assertTrue(self.enforcer.enforce('test', {}, {'roles': ['test']})) # The existing rules have a same key with # new loaded ones will be overwrote. self.assertFalse( self.enforcer.enforce('default', {}, {'roles': ['fakeZ']})) # Check against rule dict again from # enforcer object directly. self.assertIn('test', self.enforcer.rules) self.assertIn('default', self.enforcer.rules) self.assertIn('admin', self.enforcer.rules) loaded_rules = jsonutils.loads(str(self.enforcer.rules)) self.assertEqual(3, len(loaded_rules)) self.assertIn('role:test', loaded_rules['test']) self.assertIn('role:fakeB', loaded_rules['default']) self.assertIn('is_admin:True', loaded_rules['admin'])
def test_enforcer_force_reload_with_overwrite(self, opts_registered=0): self.create_config_file(os.path.join('policy.d', 'a.conf'), POLICY_A_CONTENTS) self.create_config_file(os.path.join('policy.d', 'b.conf'), POLICY_B_CONTENTS) # Prepare in memory fake policies. self.enforcer.set_rules({'test': _parser.parse_rule('role:test')}, use_conf=True) self.enforcer.set_rules( {'default': _parser.parse_rule('role:fakeZ')}, overwrite=False, # Keeps 'test' role. use_conf=True) self.enforcer.overwrite = True # Call enforce(), it will load rules from # policy configuration files, to overwrite # existing fake ones. self.assertFalse(self.enforcer.enforce('test', {}, {'roles': ['test']})) self.assertTrue( self.enforcer.enforce('default', {}, {'roles': ['fakeB']})) # Check against rule dict again from # enforcer object directly. self.assertNotIn('test', self.enforcer.rules) self.assertIn('default', self.enforcer.rules) self.assertIn('admin', self.enforcer.rules) loaded_rules = jsonutils.loads(str(self.enforcer.rules)) self.assertEqual(2 + opts_registered, len(loaded_rules)) self.assertIn('role:fakeB', loaded_rules['default']) self.assertIn('is_admin:True', loaded_rules['admin'])
def test_enforcer_force_reload_with_overwrite(self, opts_registered=0): self.create_config_file( os.path.join('policy.d', 'a.conf'), POLICY_A_CONTENTS) self.create_config_file( os.path.join('policy.d', 'b.conf'), POLICY_B_CONTENTS) # Prepare in memory fake policies. self.enforcer.set_rules({'test': _parser.parse_rule('role:test')}, use_conf=True) self.enforcer.set_rules({'default': _parser.parse_rule('role:fakeZ')}, overwrite=False, # Keeps 'test' role. use_conf=True) self.enforcer.overwrite = True # Call enforce(), it will load rules from # policy configuration files, to overwrite # existing fake ones. self.assertFalse(self.enforcer.enforce('test', {}, {'roles': ['test']})) self.assertTrue(self.enforcer.enforce('default', {}, {'roles': ['fakeB']})) # Check against rule dict again from # enforcer object directly. self.assertNotIn('test', self.enforcer.rules) self.assertIn('default', self.enforcer.rules) self.assertIn('admin', self.enforcer.rules) loaded_rules = jsonutils.loads(str(self.enforcer.rules)) self.assertEqual(2 + opts_registered, len(loaded_rules)) self.assertIn('role:fakeB', loaded_rules['default']) self.assertIn('is_admin:True', loaded_rules['admin'])
def test_parse_rule_string(self, mock_parse_list_rule, mock_parse_text_rule): result = _parser.parse_rule('a string') self.assertEqual('text rule', result) self.assertFalse(mock_parse_list_rule.called) mock_parse_text_rule.assert_called_once_with('a string')
def from_dict(cls, rules_dict, default_rule=None): """Allow loading of rule data from a dictionary.""" # Parse the rules stored in the dictionary rules = dict((k, _parser.parse_rule(v)) for k, v in rules_dict.items()) return cls(rules, default_rule)
def enforce(self, action, target, creds, **kwargs): LOG.debug('Evaluating against System Authz Policy') sys_rst = self._enforce(action, target, creds, rule_dict= self.sys_rules, **kwargs) if not sys_rst: return sys_rst LOG.debug('Evaluating against Domain Authz Policy') # We can always get scope_domain_id from creds. domain_id = creds['domain_id'] p_ref = self.policy_api.get_enabled_policy_in_domain(domain_id) if p_ref: try: r_dict = self.policy_api.get_rule(p_ref['id'], action[0], action[1]) rule = _parser.parse_rule(r_dict['condition']) return self._enforce(rule, target, creds, **kwargs) except exception.RuleNotFound: LOG.debug('Tenant domain has an enabled policy, but rule' ' on target service and permission has not been' ' specified. Using the corresponding rule in' ' default policy.') return self._enforce(action, target, creds, rule_dict=self.dflt_rules, **kwargs) else: LOG.debug('Tenant domain has no enabled policy. Using' ' the corresponding rule in default policy.') return self._enforce(action, target, creds, rule_dict=self.dflt_rules, **kwargs)
def load_json(cls, data, default_rule=None): """Allow loading of JSON rule data.""" # Suck in the JSON data and parse the rules rules = dict((k, _parser.parse_rule(v)) for k, v in jsonutils.loads(data).items()) return cls(rules, default_rule)
def from_dict(cls, rules_dict, default_rule=None): """Allow loading of rule data from a dictionary.""" # Parse the rules stored in the dictionary rules = dict() for k, v in rules_dict.items(): LOG.debug('Processing policy: "%s": "%s"', k, v) rules[k] = _parser.parse_rule(v) return cls(rules, default_rule)
def load_json(cls, data, default_rule=None): """Allow loading of JSON rule data.""" data = jsonutils.loads(data) # Parse the rules stored in JSON data loaded rules = {} for serv in data.iterkeys(): rules[serv] = dict((k, _parser.parse_rule(v)) for k, v in data[serv].items()) return cls(rules, default_rule)
def load(cls, data, default_rule=None): """Allow loading of YAML/JSON rule data. .. versionadded:: 1.5.0 """ parsed_file = parse_file_contents(data) # Parse the rules rules = {k: _parser.parse_rule(v) for k, v in parsed_file.items()} return cls(rules, default_rule)
def load(cls, data, default_rule=None): """Allow loading of YAML/JSON rule data. .. versionadded:: 1.5.0 """ try: parsed = yaml.safe_load(data) except yaml.YAMLError as e: # For backwards-compatibility, convert yaml error to ValueError, # which is what JSON loader raised. raise ValueError(six.text_type(e)) # Parse the rules rules = {k: _parser.parse_rule(v) for k, v in parsed.items()} return cls(rules, default_rule)
def __init__(self, name, check_str, description=None, deprecated_rule=None, deprecated_for_removal=False, deprecated_reason=None, deprecated_since=None, scope_types=None): self.name = name self.check_str = check_str self.check = _parser.parse_rule(check_str) self.description = description self.deprecated_rule = copy.deepcopy(deprecated_rule) or [] self.deprecated_for_removal = deprecated_for_removal self.deprecated_reason = deprecated_reason self.deprecated_since = deprecated_since if self.deprecated_rule: if not isinstance(self.deprecated_rule, DeprecatedRule): raise ValueError( 'deprecated_rule must be a DeprecatedRule object.') if (deprecated_for_removal or deprecated_rule) and (deprecated_reason is None or deprecated_since is None): raise ValueError( '%(name)s deprecated without deprecated_reason or ' 'deprecated_since. Both must be supplied if deprecating a ' 'policy' % {'name': self.name}) if scope_types: msg = 'scope_types must be a list of strings.' if not isinstance(scope_types, list): raise ValueError(msg) for scope_type in scope_types: if not isinstance(scope_type, six.string_types): raise ValueError(msg) if scope_types.count(scope_type) > 1: raise ValueError( 'scope_types must be a list of unique strings.') self.scope_types = scope_types
def set_rules(self, rules): policy = zun_policy._ENFORCER policy.set_rules({k: _parser.parse_rule(v) for k, v in rules.items()})
def set_rules(self, rules): self._add_default_rules(rules) policy = zun_policy._ENFORCER policy.set_rules({k: _parser.parse_rule(v) for k, v in rules.items()})
def load_rules(self, force_reload=False): """Loads policy_path's rules. Policy file is cached and will be reloaded if modified. :param force_reload: Whether to reload rules from config file. """ if force_reload: self.use_conf = force_reload if self.use_conf: if not self.policy_path: try: self.policy_path = self._get_policy_path(self.policy_file) except cfg.ConfigFilesNotFoundError: if not self._informed_no_policy_file: LOG.debug('The policy file %s could not be found.', self.policy_file) self._informed_no_policy_file = True if self.policy_path: self._load_policy_file(self.policy_path, force_reload, overwrite=self.overwrite) for path in self.conf.oslo_policy.policy_dirs: try: path = self._get_policy_path(path) except cfg.ConfigFilesNotFoundError: continue if (force_reload or self._is_directory_updated( self._policy_dir_mtimes, path)): self._walk_through_policy_directory( path, self._load_policy_file, force_reload, False) for default in self.registered_rules.values(): if default.deprecated_rule: deprecated_msg = ( 'Policy "%(old_name)s":"%(old_check_str)s" was ' 'deprecated in %(release)s in favor of "%(name)s":' '"%(check_str)s". Reason: %(reason)s. Either ensure ' 'your deployment is ready for the new default or ' 'copy/paste the deprecated policy into your policy ' 'file and maintain it manually.' % { 'old_name': default.deprecated_rule.name, 'old_check_str': default.deprecated_rule.check_str, 'release': default.deprecated_since, 'name': default.name, 'check_str': default.check_str, 'reason': default.deprecated_reason }) if default.deprecated_rule.name != default.name and ( default.deprecated_rule.name in self.rules): # Print a warning because the actual policy name is # changing. If deployers are relying on an override for # foo:bar and it's getting renamed to foo:create_bar # then they need to be able to see that before they # roll out the next release. warnings.warn(deprecated_msg) if (default.deprecated_rule.check_str != default.check_str and default.name not in self.rules): # In this case, the default check_str is changing. We # need to let operators know that this is going to # change. If they don't want to override it, they are # going to have to make sure the right infrastructure # exists before they upgrade. This overrides the new # check with an OrCheck that combines the new and old # check_str attributes from the new and deprecated # policies. This will make it so that deployments don't # break on upgrade, but they receive log messages # telling them stuff is going to change if they don't # maintain the policy manually or add infrastructure to # their deployment to support the new policy. default.check = _parser.parse_rule( default.check_str + ' or ' + default.deprecated_rule.check_str) warnings.warn(deprecated_msg) if default.deprecated_for_removal and (default.name in self.file_rules): # If a policy is going to be removed altogether, then we # need to make sure we let operators know so they can clean # up their policy files, if they are overriding it. warnings.warn( 'Policy "%(policy)s":"%(check_str)s" was ' 'deprecated for removal in %(release)s. Reason: ' '%(reason)s. Its value may be silently ignored in ' 'the future.' % { 'policy': default.name, 'check_str': default.check_str, 'release': default.deprecated_since, 'reason': default.deprecated_reason }) if default.name not in self.rules: self.rules[default.name] = default.check # Detect and log obvious incorrect rule definitions self.check_rules()
def set_rules(self, rules): policy = commissaire_openstack_policy._ENFORCER policy.set_rules({k: _parser.parse_rule(v) for k, v in rules.items()})
def __init__(self, name, check_str, description=None): self.name = name self.check_str = check_str self.check = _parser.parse_rule(check_str) self.description = description
def __init__(self, name, check_str): self.name = name self.check = _parser.parse_rule(check_str)
def test_parse_rule_list(self, mock_parse_list_rule, mock_parse_text_rule): result = _parser.parse_rule([['a'], ['list']]) self.assertEqual('list rule', result) self.assertFalse(mock_parse_text_rule.called) mock_parse_list_rule.assert_called_once_with([['a'], ['list']])
def set_rules(self, rules): policy = watcher_policy._ENFORCER policy.set_rules({k: _parser.parse_rule(v) for k, v in rules.items()})