requirements authority: Use better exception/return code
This patch set makes some minor modifications to the requirements
authority module:
* return {} instead of None in RequirementsParser.parse since
its return type is dict
* raise RbacParsingException if an invalid rule is passed to
RequirementsAuthority.allowed since KeyError is a builtin type
and is not specific enough
* change the exception message raise for the above case -- "API"
is not the right word; the word should be "rule name" as that
is what is being keyed into the roles_dict
Change-Id: Ia4408c0745d2b5ddb1c73c1eb9a6316ae0c1f646
diff --git a/patrole_tempest_plugin/requirements_authority.py b/patrole_tempest_plugin/requirements_authority.py
index 4697c3b..4d6f25b 100644
--- a/patrole_tempest_plugin/requirements_authority.py
+++ b/patrole_tempest_plugin/requirements_authority.py
@@ -18,9 +18,10 @@
from oslo_log import log as logging
from tempest import config
-from tempest.lib import exceptions
+from tempest.lib import exceptions as lib_exc
from patrole_tempest_plugin.rbac_authority import RbacAuthority
+from patrole_tempest_plugin import rbac_exceptions
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -81,7 +82,7 @@
except yaml.parser.ParserError:
LOG.error("Error while parsing the requirements YAML file. Did "
"you pass a valid component name from the test case?")
- return None
+ return {}
class RequirementsAuthority(RbacAuthority):
@@ -98,10 +99,10 @@
Defaults to ``[patrole].custom_requirements_file``.
:param str component: Name of the OpenStack service to be validated.
"""
- filepath = filepath or CONF.patrole.custom_requirements_file
-
+ self.filepath = filepath or CONF.patrole.custom_requirements_file
if component is not None:
- self.roles_dict = RequirementsParser(filepath).parse(component)
+ self.roles_dict = RequirementsParser(self.filepath).parse(
+ component)
else:
self.roles_dict = None
@@ -116,33 +117,34 @@
:returns: True if ``role`` is allowed to perform ``rule_name``, else
False.
:rtype: bool
- :raises KeyError: If ``rule_name`` does not exist among the keyed
- policy names in the custom requirements file.
+ :raises RbacParsingException: If ``rule_name`` does not exist among the
+ keyed policy names in the custom requirements file.
"""
- if self.roles_dict is None:
- raise exceptions.InvalidConfiguration(
+ 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]
-
- 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
except KeyError:
- raise KeyError("'%s' API is not defined in the requirements YAML "
- "file" % rule_name)
+ 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