Beispiel #1
0
    def _get_policy_data(self, service):
        file_policy_data = {}
        mgr_policy_data = {}
        policy_data = {}

        # Check whether policy file exists.
        if os.path.isfile(self.path):
            try:
                with open(self.path, 'r') as policy_file:
                    file_policy_data = policy_file.read()
                file_policy_data = json.loads(file_policy_data)
            except (IOError, ValueError) as e:
                msg = "Failed to read policy file for service. "
                if isinstance(e, IOError):
                    msg += "Please check that policy path exists."
                else:
                    msg += "JSON may be improperly formatted."
                LOG.debug(msg)
                file_policy_data = {}

        # Check whether policy actions are defined in code. Nova and Keystone,
        # for example, define their default policy actions in code.
        mgr = stevedore.named.NamedExtensionManager(
            'oslo.policy.policies',
            names=[service],
            on_load_failure_callback=None,
            invoke_on_load=True,
            warn_on_missing_entrypoint=False)

        if mgr:
            policy_generator = {policy.name: policy.obj for policy in mgr}
            if policy_generator and service in policy_generator:
                for rule in policy_generator[service]:
                    mgr_policy_data[rule.name] = str(rule.check)

        # If data from both file and code exist, combine both together.
        if file_policy_data and mgr_policy_data:
            # Add the policy actions from code first.
            for action, rule in mgr_policy_data.items():
                policy_data[action] = rule
            # Overwrite with any custom policy actions defined in policy.json.
            for action, rule in file_policy_data.items():
                policy_data[action] = rule
        elif file_policy_data:
            policy_data = file_policy_data
        elif mgr_policy_data:
            policy_data = mgr_policy_data
        else:
            error_message = 'Policy file for {0} service neither found in '\
                            'code nor at {1}.'.format(service, self.path)
            raise rbac_exceptions.RbacParsingException(error_message)

        try:
            policy_data = json.dumps(policy_data)
        except ValueError:
            error_message = 'Policy file for {0} service is invalid.'.format(
                service)
            raise rbac_exceptions.RbacParsingException(error_message)

        return policy_data
    def get_rules(self):
        rules = policy.Rules()
        # Check whether policy file exists and attempt to read it.
        for path in self.policy_files[self.service]:
            try:
                with open(path, 'r') as fp:
                    for k, v in policy.Rules.load(fp.read()).items():
                        if k not in rules:
                            rules[k] = v
                        # If the policy name and rule are the same, no
                        # ambiguity, so no reason to warn.
                        elif str(v) != str(rules[k]):
                            msg = ("The same policy name: %s was found in "
                                   "multiple policies files for service %s. "
                                   "This can lead to policy rule ambiguity. "
                                   "Using rule: %s; Rule from file: %s")
                            LOG.warning(msg, k, self.service, rules[k], v)
            except (ValueError, IOError):
                LOG.warning("Failed to read policy file '%s' for service %s.",
                            path, self.service)

        # Check whether policy actions are defined in code. Nova and Keystone,
        # for example, define their default policy actions in code.
        mgr = stevedore.named.NamedExtensionManager(
            'oslo.policy.policies',
            names=[self.service],
            invoke_on_load=True,
            warn_on_missing_entrypoint=False)

        if mgr:
            policy_generator = {plc.name: plc.obj for plc in mgr}
            if self.service in policy_generator:
                for rule in policy_generator[self.service]:
                    if rule.name not in rules:
                        if CONF.patrole.validate_deprecated_rules:
                            # NOTE (sergey.vilgelm):
                            # The `DocumentedRuleDefault` object has no
                            # `deprecated_rule` attribute in Pike
                            if getattr(rule, 'deprecated_rule', False):
                                rule = self._handle_deprecated_rule(rule)
                        rules[rule.name] = rule.check
                    elif str(rule.check) != str(rules[rule.name]):
                        msg = ("The same policy name: %s was found in the "
                               "policies files and in the code for service "
                               "%s. This can lead to policy rule ambiguity. "
                               "Using rule: %s; Rule from code: %s")
                        LOG.warning(msg, rule.name, self.service,
                                    rules[rule.name], rule.check)

        if not rules:
            msg = (
                'Policy files for {0} service were not found among the '
                'registered in-code policies or in any of the possible policy '
                'files: {1}.'.format(self.service, [
                    loc % self.service
                    for loc in CONF.patrole.custom_policy_files
                ]))
            raise rbac_exceptions.RbacParsingException(msg)

        return rules
Beispiel #3
0
 def _try_rule(self, apply_rule, target, access_data, o):
     if apply_rule not in self.rules:
         message = "Policy action: {0} not found in policy file: {1}."\
                   .format(apply_rule, self.path)
         LOG.debug(message)
         raise rbac_exceptions.RbacParsingException(message)
     else:
         rule = self.rules[apply_rule]
         return rule(target, access_data, o)
 def _try_rule(self, apply_rule, target, access_data, o):
     if apply_rule not in self.rules:
         message = ("Policy action \"{0}\" not found in policy file: {1} or"
                    " among registered policy in code defaults for service."
                    ).format(apply_rule, self.path)
         LOG.debug(message)
         raise rbac_exceptions.RbacParsingException(message)
     else:
         rule = self.rules[apply_rule]
         return rule(target, access_data, o)
 def _try_rule(self, apply_rule, target, access_data, o):
     if apply_rule not in self.rules:
         message = ('Policy action "{0}" not found in policy files: '
                    '{1} or among registered policy in code defaults for '
                    '{2} service.').format(apply_rule,
                                           self.policy_files[self.service],
                                           self.service)
         LOG.debug(message)
         raise rbac_exceptions.RbacParsingException(message)
     else:
         rule = self.rules[apply_rule]
         return rule(target, access_data, o)
Beispiel #6
0
    def allowed(self, rule_name, roles):
        """Checks if a given rule in a policy is allowed with given role.

        :param string rule_name: Rule to be checked using provided requirements
            file specified by ``[patrole].custom_requirements_file``. Must be
            a key present in this file, under the appropriate component.
        :param List[string] roles: Roles to validate against custom
            requirements file.
        :returns: True if ``role`` is allowed to perform ``rule_name``, else
            False.
        :rtype: bool
        :raises RbacParsingException: If ``rule_name`` does not exist among the
            keyed policy names in the custom requirements file.
        """
        if not self.roles_dict:
            raise lib_exc.InvalidConfiguration(
                "Roles dictionary parsed from requirements YAML file is "
                "empty. Ensure the requirements YAML file is correctly "
                "formatted.")
        try:
            requirement_roles = self.roles_dict[rule_name]
        except KeyError:
            raise rbac_exceptions.RbacParsingException(
                "'%s' rule name is not defined in the requirements YAML file: "
                "%s" % (rule_name, self.filepath))

        for role_reqs in requirement_roles:
            required_roles = [
                role for role in role_reqs if not role.startswith("!")
            ]
            forbidden_roles = [
                role[1:] for role in role_reqs if role.startswith("!")
            ]

            # User must have all required roles
            required_passed = all([r in roles for r in required_roles])
            # User must not have any forbidden roles
            forbidden_passed = all([r not in forbidden_roles for r in roles])

            if required_passed and forbidden_passed:
                return True

        return False
Beispiel #7
0
    def _get_policy_data(self):
        file_policy_data = {}
        mgr_policy_data = {}
        policy_data = {}

        # Check whether policy file exists and attempt to read it.
        for path in self.policy_files[self.service]:
            try:
                with open(path, 'r') as fp:
                    for k, v in json.load(fp).items():
                        if k not in file_policy_data:
                            file_policy_data[k] = v
                        else:
                            # If the policy name and rule are the same, no
                            # ambiguity, so no reason to warn.
                            if v != file_policy_data[k]:
                                LOG.warning(
                                    "The same policy name: %s was found in "
                                    "multiple policies files for service %s. "
                                    "This can lead to policy rule ambiguity. "
                                    "Using rule: %s", k, self.service,
                                    file_policy_data[k])
            except (IOError, ValueError) as e:
                msg = "Failed to read policy file for service. "
                if isinstance(e, IOError):
                    msg += "Please check that policy path exists."
                else:
                    msg += "JSON may be improperly formatted."
                LOG.debug(msg)

        # Check whether policy actions are defined in code. Nova and Keystone,
        # for example, define their default policy actions in code.
        mgr = stevedore.named.NamedExtensionManager(
            'oslo.policy.policies',
            names=[self.service],
            on_load_failure_callback=None,
            invoke_on_load=True,
            warn_on_missing_entrypoint=False)

        if mgr:
            policy_generator = {plc.name: plc.obj for plc in mgr}
            if policy_generator and self.service in policy_generator:
                for rule in policy_generator[self.service]:
                    mgr_policy_data[rule.name] = str(rule.check)

        # If data from both file and code exist, combine both together.
        if file_policy_data and mgr_policy_data:
            # Add the policy actions from code first.
            for action, rule in mgr_policy_data.items():
                policy_data[action] = rule
            # Overwrite with any custom policy actions defined in policy.json.
            for action, rule in file_policy_data.items():
                policy_data[action] = rule
        elif file_policy_data:
            policy_data = file_policy_data
        elif mgr_policy_data:
            policy_data = mgr_policy_data
        else:
            error_message = (
                'Policy files for {0} service were not found among the '
                'registered in-code policies or in any of the possible policy '
                'files: {1}.'.format(self.service, [
                    loc % self.service
                    for loc in CONF.patrole.custom_policy_files
                ]))
            raise rbac_exceptions.RbacParsingException(error_message)

        try:
            policy_data = json.dumps(policy_data)
        except (TypeError, ValueError):
            error_message = 'Policy files for {0} service are invalid.'.format(
                self.service)
            raise rbac_exceptions.RbacParsingException(error_message)

        return policy_data