Multi role RBAC validation

This patchset replaces ``CONF.patrole.rbac_test_role`` with
``CONF.patrole.rbac_test_roles``, where instead of single role
we can specify list of roles to be assigned to test user.

Change-Id: Ia68bcbdbb523dfe7c4abd6107fb4c426a566ae9d
diff --git a/patrole_tempest_plugin/rbac_rule_validation.py b/patrole_tempest_plugin/rbac_rule_validation.py
index c85376f..575e2c3 100644
--- a/patrole_tempest_plugin/rbac_rule_validation.py
+++ b/patrole_tempest_plugin/rbac_rule_validation.py
@@ -17,6 +17,7 @@
 import logging
 import sys
 
+from oslo_log import versionutils
 from oslo_utils import excutils
 import six
 
@@ -47,7 +48,7 @@
 
     * an OpenStack service,
     * a policy action (``rule``) enforced by that service, and
-    * the test role defined by ``[patrole] rbac_test_role``
+    * the test roles defined by ``[patrole] rbac_test_roles``
 
     determines whether the test role has sufficient permissions to perform an
     API call that enforces the ``rule``.
@@ -142,7 +143,15 @@
                                                         expected_error_codes)
 
     def decorator(test_func):
-        role = CONF.patrole.rbac_test_role
+        roles = CONF.patrole.rbac_test_roles
+        # TODO(vegasq) drop once CONF.patrole.rbac_test_role is removed
+        if CONF.patrole.rbac_test_role:
+            msg = ('CONF.patrole.rbac_test_role is deprecated in favor of '
+                   'CONF.patrole.rbac_test_roles and will be removed in '
+                   'future.')
+            versionutils.report_deprecated_feature(LOG, msg)
+            if not roles:
+                roles.append(CONF.patrole.rbac_test_role)
 
         @functools.wraps(test_func)
         def wrapper(*args, **kwargs):
@@ -200,10 +209,10 @@
                                 service)
 
                 if allowed:
-                    msg = ("Role %s was not allowed to perform the following "
-                           "actions: %s. Expected allowed actions: %s. "
-                           "Expected disallowed actions: %s." % (
-                               role, sorted(rules),
+                    msg = ("User with roles %s was not allowed to perform the "
+                           "following actions: %s. Expected allowed actions: "
+                           "%s. Expected disallowed actions: %s." % (
+                               roles, sorted(rules),
                                sorted(set(rules) - set(disallowed_rules)),
                                sorted(disallowed_rules)))
                     LOG.error(msg)
@@ -236,7 +245,7 @@
                     msg = (
                         "OverPermission: Role %s was allowed to perform the "
                         "following disallowed actions: %s" % (
-                            role, sorted(disallowed_rules)
+                            roles, sorted(disallowed_rules)
                         )
                     )
                     LOG.error(msg)
@@ -328,7 +337,12 @@
         LOG.error(msg)
         raise rbac_exceptions.RbacResourceSetupFailed(msg)
 
-    role = CONF.patrole.rbac_test_role
+    roles = CONF.patrole.rbac_test_roles
+    # TODO(vegasq) drop once CONF.patrole.rbac_test_role is removed
+    if CONF.patrole.rbac_test_role:
+        if not roles:
+            roles.append(CONF.patrole.rbac_test_role)
+
     # Test RBAC against custom requirements. Otherwise use oslo.policy.
     if CONF.patrole.test_custom_requirements:
         authority = requirements_authority.RequirementsAuthority(
@@ -339,14 +353,14 @@
         authority = policy_authority.PolicyAuthority(
             project_id, user_id, service,
             extra_target_data=formatted_target_data)
-    is_allowed = authority.allowed(rule, role)
+    is_allowed = authority.allowed(rule, roles)
 
     if is_allowed:
         LOG.debug("[Policy action]: %s, [Role]: %s is allowed!", rule,
-                  role)
+                  roles)
     else:
         LOG.debug("[Policy action]: %s, [Role]: %s is NOT allowed!",
-                  rule, role)
+                  rule, roles)
 
     return is_allowed