Enhance validation decorator with error code
Rather than wrapping each API call in a try/except block in the event
that a 404 rather than a 403 is thrown due to lack of permissions, the
decorator rbac_rule_validation.action is enhanced with the a new kwarg
called 'expected_error_code'.
The decorator now handles any error code that is passed in, and raises
the Forbidden exception even if the error code is not 403.
This commit also refactors the tests that use the try/except block to
handle non-403 error codes.
Change-Id: I9d263e21110fb9f988a6d4d781bf54e81f485f14
Implements: blueprint enhance-validation-decorator-with-error-code
diff --git a/patrole_tempest_plugin/rbac_rule_validation.py b/patrole_tempest_plugin/rbac_rule_validation.py
index a6490e7..33ee666 100644
--- a/patrole_tempest_plugin/rbac_rule_validation.py
+++ b/patrole_tempest_plugin/rbac_rule_validation.py
@@ -26,7 +26,7 @@
LOG = logging.getLogger(__name__)
-def action(service, rule):
+def action(service, rule, expected_error_code=403):
def decorator(func):
def wrapper(*args, **kwargs):
try:
@@ -43,6 +43,8 @@
authority = rbac_auth.RbacAuthority(tenant_id, user_id, service)
allowed = authority.get_permission(rule, CONF.rbac.rbac_test_role)
+ expected_exception, irregular_msg = _get_exception_type(
+ expected_error_code)
try:
func(*args)
@@ -52,7 +54,7 @@
raise exceptions.NotFound(
"%s RbacInvalidService was: %s" %
(msg, e))
- except exceptions.Forbidden as e:
+ except expected_exception as e:
if allowed:
msg = ("Role %s was not allowed to perform %s." %
(CONF.rbac.rbac_test_role, rule))
@@ -60,6 +62,8 @@
raise exceptions.Forbidden(
"%s exception was: %s" %
(msg, e))
+ if irregular_msg:
+ LOG.warning(irregular_msg.format(rule, service))
except rbac_exceptions.RbacActionFailed as e:
if allowed:
msg = ("Role %s was not allowed to perform %s." %
@@ -80,3 +84,23 @@
switchToRbacRole=False)
return wrapper
return decorator
+
+
+def _get_exception_type(expected_error_code):
+ expected_exception = None
+ irregular_msg = None
+ supported_error_codes = [403, 404]
+ if expected_error_code == 403:
+ expected_exception = exceptions.Forbidden
+ elif expected_error_code == 404:
+ expected_exception = exceptions.NotFound
+ irregular_msg = ("NotFound exception was caught for policy action "
+ "{0}. The service {1} throws a 404 instead of a 403, "
+ "which is irregular.")
+ else:
+ msg = ("Please pass an expected error code. Currently "
+ "supported codes: {0}".format(str(supported_error_codes)))
+ LOG.error(msg)
+ raise rbac_exceptions.RbacInvalidErrorCode()
+
+ return expected_exception, irregular_msg