Merge "Corrects compute microversion docstrings"
diff --git a/HACKING.rst b/HACKING.rst
index 722759f..bb337b0 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -1,4 +1,6 @@
-patrole Style Commandments
-===============================================
+Patrole Style Commandments
+==========================
 
-Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/
+Read the OpenStack Style Commandments: `<http://docs.openstack.org/developer/hacking/>`__
+
+Also review Tempest's Style Commandments: `<https://docs.openstack.org/developer/tempest/HACKING.html>`__
diff --git a/README.rst b/README.rst
index d9a6507..c527c3b 100644
--- a/README.rst
+++ b/README.rst
@@ -1,10 +1,11 @@
-=======
-patrole
-=======
+========
+Overview
+========
 
-Patrole is a tool for verifying that Role-Based Access Control is being enforced.
+Patrole is a tool for verifying that Role-Based Access Control is being
+correctly enforced.
 
-Patrole allows users to run API tests using specified RBAC roles.  This allows
+Patrole allows users to run API tests using specified RBAC roles. This allows
 deployments to verify that only intended roles have access to those APIs.
 This is critical to ensure security, especially in large deployments with
 custom roles.
@@ -15,18 +16,144 @@
 * Bugs: http://bugs.launchpad.net/patrole
 
 Features
---------
-
-Patrole offers RBAC testing for various OpenStack RBAC policies.  It includes
+========
+Patrole offers RBAC testing for various OpenStack RBAC policies. It includes
 a decorator that wraps around tests which verifies that when the test calls the
-corresponding api endpoint, access is only granted for correct roles.
+corresponding API endpoint, access is only granted for correct roles.
+
+Currently, Patrole supports policies contained in code and in policy.json files.
+If both exist, the policy actions in the policy.json are prioritized.
+
+.. _test-flows:
+
+Test Flows
+----------
 
 There are several possible test flows.
 
-If the rbac_test_role is allowed to access the endpoint
- - The test passes if no 403 forbidden or RbacActionFailed exception is raised.
+If the ``rbac_test_role`` is allowed to access the endpoint:
 
-If the rbac_test_role is not allowed to access the endpoint
- - If the endpoint returns a 403 forbidden exception the test will pass
- - If the endpoint returns something other than a 403 forbidden to indicate
-   that the role is not allowed, the test will raise an RbacActionFailed exception.
+* The test passes if no 403 ``Forbidden`` or ``RbacActionFailed`` exception is raised.
+
+If the ``rbac_test_role`` is not allowed to access the endpoint:
+
+* If the endpoint returns a 403 `Forbidden` exception the test will pass.
+* If the endpoint returns successfully, then the test will fail with an
+  ``RbacOverPermission`` exception.
+* If the endpoint returns something other than a 403 ``Forbidden`` to indicate
+  that the role is not allowed, the test will raise an ``RbacActionFailed`` exception.
+
+.. note::
+
+    Certain services like Neutron *intentionally* raise a 404 instead of a 403
+    for security concerns. Patrole accomodates this behavior by anticipating
+    a 404 instead of a 403, if specified through a special argument. For more
+    information about Neutron's policy enforcement, see:
+    `<https://docs.openstack.org/developer/neutron/devref/policy.html#request-authorization>`__.
+
+How It Works
+============
+Patrole leverages oslo_policy (OpenStack's policy enforcement engine) to
+determine whether a given role is allowed to perform a policy action given a
+specific rule and OpenStack service. This is done before test execution inside
+the ``rbac_rule_validation.action`` decorator. Then, inside the test, the API
+that does policy enforcement for the same rule is called. The outcome is
+compared against the result from oslo_policy and a pass or fail is determined
+as outlined above: :ref:`test-flows`.
+
+.. note::
+
+    Currently, Patrole does not support checking multiple rules against a single
+    API call. Even though some APIs enforce multiple rules (some indirectly),
+    it is increasingly difficult to maintain the tests if multiple policy
+    actions are expected to be called.
+
+Test Execution Workflow
+-----------------------
+
+The workflow is as follows:
+
+#. Each test uses the ``rbac_rule_validation.action`` decorator, like below: ::
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:stop")
+    @decorators.idempotent_id('ab4a17d2-166f-4a6d-9944-f17baa576cf2')
+    def test_stop_server(self):
+        # Set the primary credential's role to "rbac_test_role".
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        # Call the API that enforces the policy action specified by "rule".
+        self._test_stop_server()
+
+   The ``service`` attribute accepts an OpenStack service and the ``rule`` attribute
+   accepts a valid OpenStack policy action, like "os_compute_api:servers:stop".
+
+#. The ``rbac_rule_validation.action`` decorator passes these attributes,
+   along with user_id and project_id information derived from the primary
+   Tempest credential (``self.os.credentials.user_id`` and ``self.os.credentials.project_id``),
+   to the ``rbac_policy_parser``.
+
+#. The logic in ``rbac_policy_parser`` then passes all this information along
+   and the role in ``CONF.rbac.rbac_test_role`` to oslo_policy to determine whether
+   the ``rbac_test_role`` is authorized to perform the policy action for the given
+   service.
+
+#. After all of the logic above has executed inside the rbac decorator, the
+   test is executed. The test then sets up test-level resources, if necessary,
+   with **admin** credentials implicitly. This is accomplished through
+   ``rbac_utils.switch_role(toggle_rbac_role=False)``: ::
+
+    @classmethod
+    def setup_clients(cls):
+        super(BaseV2ComputeRbacTest, cls).setup_clients()
+        cls.auth_provider = cls.os.auth_provider
+        cls.rbac_utils = rbac_utils()
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
+
+   This code has *already* executed when the test class is instantiated, because
+   it is located in the base rbac test class. Whenever ``cls.rbac_utils.switch_role``
+   is called, one of two behaviors are possible:
+
+    #. The primary credential's role is changed to admin if ``toggle_rbac_role=False``
+    #. The primary credential's role is changed to ``rbac_test_role`` if
+       ``toggle_rbac_role=True``
+
+   Thus, at the *beginning* of every test and during ``resource_setup`` and
+   ``resource_cleanup``, the primary credential has the admin role.
+
+#. After preliminary test-level setup is performed, like creating a server, a
+   second call to ``self.rbac_utils.switch_role`` is done: ::
+
+    self.rbac_utils.switch_role(cls, toggle_rbac_role=True)
+
+   Now the primary credential has the role specified by ``rbac_test_role``.
+
+#. The API endpoint in which  policy enforcement of "os_compute_api:servers:stop"
+   is performed can now be called.
+
+   .. note:
+
+        To determine whether a policy action is enforced, refer to the relevant
+        controller code to make sure that the policy action is indeed enforced.
+
+#. Now that a call is made to "stop_server" with the primary credentials having
+   the role specified by ``rbac_test_role``, either the nova contoller will allow
+   or disallow the action to be performed. Since the "stop_server" policy action in
+   nova is defined as "base.RULE_ADMIN_OR_OWNER", the API will most likely
+   return a successful status code. For more information about this policy action,
+   see `<https://github.com/openstack/nova/blob/master/nova/policies/servers.py>`__.
+
+#. As mentioned above, the result from the API call and the result from oslo_policy
+   are compared for consistency.
+
+#. Finally, after the test has executed, but before ``tearDown`` or ``resource_cleanup``
+   is called, ``self.rbac_utils.switch_role(cls, toggle_rbac_role=False)`` is
+   called, so that the primary credential yet again has admin permissions for
+   test clean up. This call is always performed in the "finally" block inside
+   the ``rbac_rule_validation`` decorator.
+
+.. warning::
+
+    Failure to call ``self.rbac_utils.switch_role(cls, toggle_rbac_role=True)``
+    inside a test with the ``rbac_rule_validation`` decorator applied results
+    in a ``RbacResourceSetupFailed`` being raised, causing the test to fail.
diff --git a/contrib/post_test_hook.sh b/contrib/post_test_hook.sh
index b864a9b..e934cc4 100644
--- a/contrib/post_test_hook.sh
+++ b/contrib/post_test_hook.sh
@@ -26,11 +26,9 @@
 
 TEMPEST_CONFIG=$BASE/new/tempest/etc/tempest.conf
 TEMPEST_COMMAND="sudo -H -u tempest tox"
-# TODO(felipemonteiro): This regex does a negative lookahead to exclude slow
-# tests that contain the @test.attr(type='slow') decorator above them. Slower
-# tests will execute those tests in a separate gate, which will require
-# future modification of this script.
+
 DEVSTACK_GATE_TEMPEST_REGEX="(?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)"
+DEVSTACK_MULTINODE_GATE_TEMPEST_REGEX="(?=.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)"
 
 # Import devstack function 'iniset'.
 source $BASE/new/devstack/functions
@@ -43,23 +41,47 @@
     RBAC_ROLE="Member"
 fi
 
-# Set rbac_flag=True under [rbac] section in tempest.conf
-iniset $TEMPEST_CONFIG rbac rbac_flag True
-# Set rbac_test_role=$RBAC_ROLE under [rbac] section in tempest.conf
-iniset $TEMPEST_CONFIG rbac rbac_test_role $RBAC_ROLE
-# Set additional, necessary CONF values
-iniset $TEMPEST_CONFIG auth use_dynamic_credentials True
-iniset $TEMPEST_CONFIG auth tempest_roles Member
-iniset $TEMPEST_CONFIG identity auth_version v3
+# Second argument is expected to contain value indicating whether the
+# environment is "multinode" or not (empty string).
+TYPE=$2
 
-# Give permissions back to Tempest.
-sudo chown -R tempest:stack $BASE/new/tempest
-sudo chown -R tempest:stack $BASE/data/tempest
+function set_uuid_tokens() {
+    # Use uuid tokens for faster test runs
+    KEYSTONE_CONF=/etc/keystone/keystone.conf
+    iniset $KEYSTONE_CONF token provider uuid
+    sudo service apache2 restart
+}
 
-set -o errexit
+function setup_config() {
+    # Set enable_rbac=True under [rbac] section in tempest.conf
+    iniset $TEMPEST_CONFIG rbac enable_rbac True
+    # Set rbac_test_role=$RBAC_ROLE under [rbac] section in tempest.conf
+    iniset $TEMPEST_CONFIG rbac rbac_test_role $RBAC_ROLE
+    # Set strict_policy_check=False under [rbac] section in tempest.conf
+    iniset $TEMPEST_CONFIG rbac strict_policy_check False
+    # Set additional, necessary CONF values
+    iniset $TEMPEST_CONFIG auth tempest_roles Member
+}
 
-# cd into Tempest directory before executing tox.
-cd $BASE/new/tempest
+function run_tests() {
+    # Give permissions back to Tempest.
+    sudo chown -R tempest:stack $BASE/new/tempest
+    sudo chown -R tempest:stack $BASE/data/tempest
 
-$TEMPEST_COMMAND -eall-plugin -- $DEVSTACK_GATE_TEMPEST_REGEX --concurrency=$TEMPEST_CONCURRENCY
-sudo -H -u tempest .tox/all-plugin/bin/tempest list-plugins
+    set -o errexit
+
+    # cd into Tempest directory before executing tox.
+    cd $BASE/new/tempest
+
+    if [[ "$TYPE" == "multinode" ]]; then
+        $TEMPEST_COMMAND -eall-plugin -- $DEVSTACK_MULTINODE_GATE_TEMPEST_REGEX --concurrency=$TEMPEST_CONCURRENCY
+    else
+        $TEMPEST_COMMAND -eall-plugin -- $DEVSTACK_GATE_TEMPEST_REGEX --concurrency=$TEMPEST_CONCURRENCY
+    fi
+
+    sudo -H -u tempest .tox/all-plugin/bin/tempest list-plugins
+}
+
+set_uuid_tokens
+setup_config
+run_tests
diff --git a/doc/source/index.rst b/doc/source/index.rst
index fbe592c..35e8439 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -3,7 +3,7 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to patrole's documentation!
+Patrole - an OpenStack Tempest Plugin for RBAC Testing
 ========================================================
 
 Contents:
@@ -22,4 +22,3 @@
 * :ref:`genindex`
 * :ref:`modindex`
 * :ref:`search`
-
diff --git a/doc/source/installation.rst b/doc/source/installation.rst
index 00cc57b..e342dd8 100644
--- a/doc/source/installation.rst
+++ b/doc/source/installation.rst
@@ -3,24 +3,24 @@
 ============
 
 Installation Information
-########################
+========================
 
 At the command line::
 
-    $ pip install patrole
+    $ sudo pip install patrole
 
 Or, if you have virtualenvwrapper installed::
 
     $ mkvirtualenv patrole
-    $ pip install patrole
+    $ sudo pip install patrole
 
 Or to install from the source::
 
     $ navigate to patrole directory
-    $ pip install -e .
+    $ sudo pip install -e .
 
 Configuration Information
-#########################
+=========================
 
 tempest.conf
 ++++++++++++
@@ -28,29 +28,35 @@
 To run the RBAC tempest api test, you have to make the following changes to
 the tempest.conf file.
 
-#. [auth] section updates ::
+#. ``auth`` section updates ::
 
-       # Set tempest role to admin so all APIs are accessible
-       tempest_roles = admin
+    # Allows test cases to create/destroy projects and users. This option
+    # requires that OpenStack Identity API admin credentials are known. If
+    # false, isolated test cases and parallel execution, can still be
+    # achieved configuring a list of test accounts (boolean value)
+    use_dynamic_credentials = True
 
-       # Allows test cases to create/destroy tenants and users. This
-       # option enables isolated test cases and better parallel
-       # execution, but also requires that OpenStack Identity API
-       # admin credentials are known. (boolean value)
-       allow_tenant_isolation = True
+#. ``rbac`` section updates ::
 
-       # Allows test cases to create/destroy projects and users. This option
-       # requires that OpenStack Identity API admin credentials are known. If
-       # false, isolated test cases and parallel execution, can still be
-       # achieved configuring a list of test accounts (boolean value)
-       use_dynamic_credentials = False
+    # The role that you want the RBAC tests to use for RBAC testing
+    # This needs to be edited to run the test as a different role.
+    rbac_test_role = _member_
 
-#. [rbac] section updates ::
+    # Enables RBAC Tempest tests if set to True. Otherwise, they are
+    # skipped.
+    enable_rbac = True
 
-       # The role that you want the RBAC tests to use for RBAC testing
-       # This needs to be edited to run the test as a different role. 
-       rbac_test_role = _member_
+    # If set to true, tests throw a RbacParsingException for policies
+    # not found in the policy.json. Otherwise, they throw a
+    # skipException.
+    strict_policy_check = False
 
-       # Enables RBAC Tempest tests if set to True. Otherwise, they are
-       # skipped.
-       rbac_flag = True
+    # The following config options set the location of the service's
+    # policy file. For services that have their policy in code (e.g.,
+    # Nova), this would be the location of a custom policy.json, if
+    # one exists.
+    cinder_policy_file = /etc/cinder/policy.json
+    glance_policy_file = /etc/glance/policy.json
+    keystone_policy_file = /etc/keystone/policy.json
+    neutron_policy_file = /etc/neutron/policy.json
+    nova_policy_file = /etc/nova/policy.json
diff --git a/doc/source/usage.rst b/doc/source/usage.rst
index 5d6c0b9..c2fc6d3 100644
--- a/doc/source/usage.rst
+++ b/doc/source/usage.rst
@@ -1,10 +1,36 @@
+..
+
 ========
 Usage
 ========
 
-To use run patrole tests in Tempest::
+Running Patrole Tests in Tempest
+================================
 
-    If patrole is installed correctly tests are run like any others.
+If Patrole is installed correctly, then the API tests can be executed
+from inside the tempest root directory as follows: ::
 
-    To change the role that the patrole tests are being run as edit rbac_role
-    in the rbac section of tempest.conf.
+    tox -eall-plugin -- patrole_tempest_plugin.tests.api
+
+To execute patrole tests for a specific module, run: ::
+
+    tox -eall-plugin -- patrole_tempest_plugin.tests.api.compute
+
+To change the role that the patrole tests are being run as, edit
+``rbac_test_role`` in the ``rbac`` section of tempest.conf: ::
+
+    [rbac]
+    rbac_test_role = Member
+    ...
+
+.. note::
+
+    The ``rbac_test_role`` is service-specific. Member, for example,
+    is an arbitrary role, but by convention is used to designate the default
+    non-admin role in the system. Most patrole tests should be run with
+    **admin** and **Member** roles. However, some services, like Heat, take
+    advantage of a role called **heat_stack_user**, as it appears frequently
+    in Heat's policy.json.
+
+For more information about the Member role,
+please see: `<https://ask.openstack.org/en/question/4759/member-vs-_member_/>`__.
diff --git a/patrole_tempest_plugin/README.rst b/patrole_tempest_plugin/README.rst
index b016b88..d678422 100644
--- a/patrole_tempest_plugin/README.rst
+++ b/patrole_tempest_plugin/README.rst
@@ -1,6 +1,5 @@
-===============================================
-Tempest Integration of patrole
-===============================================
+==============================
+Tempest Integration of Patrole
+==============================
 
-This directory contains Tempest tests to cover the patrole project.
-
+This directory contains Tempest tests to cover the Patrole project.
diff --git a/patrole_tempest_plugin/config.py b/patrole_tempest_plugin/config.py
index 1edf877..cb00269 100644
--- a/patrole_tempest_plugin/config.py
+++ b/patrole_tempest_plugin/config.py
@@ -23,7 +23,27 @@
                default='admin',
                help="The current RBAC role against which to run"
                     " Patrole tests."),
-    cfg.BoolOpt('rbac_flag',
+    cfg.BoolOpt('enable_rbac',
                 default=True,
-                help="Enables RBAC tests.")
+                help="Enables RBAC tests."),
+    cfg.BoolOpt('strict_policy_check',
+                default=False,
+                help="If true, throws RbacParsingException for"
+                     " policies which don't exist. If false, "
+                     "throws skipException."),
+    cfg.StrOpt('cinder_policy_file',
+               default='/etc/cinder/policy.json',
+               help="Location of the neutron policy file."),
+    cfg.StrOpt('glance_policy_file',
+               default='/etc/glance/policy.json',
+               help="Location of the glance policy file."),
+    cfg.StrOpt('keystone_policy_file',
+               default='/etc/keystone/policy.json',
+               help="Location of the keystone policy file."),
+    cfg.StrOpt('neutron_policy_file',
+               default='/etc/neutron/policy.json',
+               help="Location of the neutron policy file."),
+    cfg.StrOpt('nova_policy_file',
+               default='/etc/nova/policy.json',
+               help="Location of the nova policy file.")
 ]
diff --git a/patrole_tempest_plugin/rbac_auth.py b/patrole_tempest_plugin/rbac_auth.py
deleted file mode 100644
index 687c0a8..0000000
--- a/patrole_tempest_plugin/rbac_auth.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import testtools
-
-from oslo_log import log as logging
-
-from patrole_tempest_plugin import rbac_exceptions
-from patrole_tempest_plugin import rbac_policy_parser
-
-LOG = logging.getLogger(__name__)
-
-
-class RbacAuthority(object):
-    def __init__(self, tenant_id, user_id, service=None):
-        self.policy_parser = rbac_policy_parser.RbacPolicyParser(
-            tenant_id, user_id, service)
-
-    def get_permission(self, rule_name, role):
-        try:
-            is_allowed = self.policy_parser.allowed(rule_name, role)
-            if is_allowed:
-                LOG.debug("[Action]: %s, [Role]: %s is allowed!", rule_name,
-                          role)
-            else:
-                LOG.debug("[Action]: %s, [Role]: %s is NOT allowed!",
-                          rule_name, role)
-            return is_allowed
-        except rbac_exceptions.RbacParsingException as e:
-            raise testtools.TestCase.skipException(str(e))
-        return False
diff --git a/patrole_tempest_plugin/rbac_exceptions.py b/patrole_tempest_plugin/rbac_exceptions.py
index 967342b..aa3135e 100644
--- a/patrole_tempest_plugin/rbac_exceptions.py
+++ b/patrole_tempest_plugin/rbac_exceptions.py
@@ -34,3 +34,7 @@
 
 class RbacParsingException (exceptions.TempestException):
     message = "Attempted to test an invalid policy file or action"
+
+
+class RbacInvalidErrorCode (exceptions.TempestException):
+    message = "Unsupported error code passed in test"
diff --git a/patrole_tempest_plugin/rbac_policy_parser.py b/patrole_tempest_plugin/rbac_policy_parser.py
index 62113ac..8256889 100644
--- a/patrole_tempest_plugin/rbac_policy_parser.py
+++ b/patrole_tempest_plugin/rbac_policy_parser.py
@@ -14,16 +14,19 @@
 #    under the License.
 
 import copy
+import json
 import os
 
+from oslo_config import cfg
 from oslo_log import log as logging
-from oslo_policy import generator
 from oslo_policy import policy
+import stevedore
 
 from tempest.common import credentials_factory as credentials
 
 from patrole_tempest_plugin import rbac_exceptions
 
+CONF = cfg.CONF
 LOG = logging.getLogger(__name__)
 
 
@@ -37,7 +40,8 @@
     each role, whether a given rule is allowed using oslo policy.
     """
 
-    def __init__(self, tenant_id, user_id, service=None, path=None):
+    def __init__(self, project_id, user_id, service=None,
+                 extra_target_data={}):
         """Initialization of Rbac Policy Parser.
 
         Parses a policy file to create a dictionary, mapping policy actions to
@@ -54,11 +58,12 @@
         the custom policy file over the default policy implementation is
         prioritized.
 
-        :param tenant_id: type uuid
+        :param project_id: type uuid
         :param user_id: type uuid
         :param service: type string
         :param path: type string
         """
+
         # First check if the service is valid
         service = service.lower().strip() if service else None
         self.admin_mgr = credentials.AdminManager()
@@ -69,34 +74,19 @@
             LOG.debug(str(service) + " is NOT a valid service.")
             raise rbac_exceptions.RbacInvalidService
 
-        # Use default path if no path provided
-        if path is None:
-            self.path = os.path.join('/etc', service, 'policy.json')
-        else:
-            self.path = path
-
-        policy_data = "{}"
-
-        # Check whether policy file exists.
-        if os.path.isfile(self.path):
-            policy_data = open(self.path, 'r').read()
-        # Otherwise use oslo_policy to fetch the rules for provided service.
-        else:
-            policy_generator = generator._get_policies_dict([service])
-            if policy_generator and service in policy_generator:
-                policy_data = "{\n"
-                for r in policy_generator[service]:
-                    policy_data = policy_data + r.__str__() + ",\n"
-                policy_data = policy_data[:-2] + "\n}"
-            # Otherwise raise an exception.
-            else:
-                raise rbac_exceptions.RbacParsingException(
-                    'Policy file for service: {0}, {1} not found.'
-                    .format(service, self.path))
-
-        self.rules = policy.Rules.load(policy_data, "default")
-        self.tenant_id = tenant_id
+        # Use default path in /etc/<service_name/policy.json if no path
+        # is provided.
+        path = getattr(CONF.rbac, '%s_policy_file' % str(service), None)
+        if not path:
+            LOG.info("No config option found for %s,"
+                     " using default path" % str(service))
+            path = os.path.join('/etc', service, 'policy.json')
+        self.path = path
+        self.rules = policy.Rules.load(self._get_policy_data(service),
+                                       'default')
+        self.project_id = project_id
         self.user_id = user_id
+        self.extra_target_data = extra_target_data
 
     def allowed(self, rule_name, role):
         is_admin_context = self._is_admin_context(role)
@@ -104,9 +94,69 @@
             access=self._get_access_token(role),
             apply_rule=rule_name,
             is_admin=is_admin_context)
-
         return is_allowed
 
+    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 _is_admin_context(self, role):
         """Checks whether a role has admin context.
 
@@ -118,7 +168,7 @@
             return self._allowed(
                 access=self._get_access_token(role),
                 apply_rule='context_is_admin')
-        return role == 'admin'
+        return role == CONF.identity.admin_role
 
     def _get_access_token(self, role):
         access_token = {
@@ -128,8 +178,8 @@
                         "name": role
                     }
                 ],
-                "project_id": self.tenant_id,
-                "tenant_id": self.tenant_id,
+                "project_id": self.project_id,
+                "tenant_id": self.project_id,
                 "user_id": self.user_id
             }
         }
@@ -163,21 +213,18 @@
                   "tenant_id": access_data['project_id'],
                   "network:tenant_id": access_data['project_id'],
                   "user_id": access_data['user_id']}
+        if self.extra_target_data:
+            target.update(self.extra_target_data)
 
         result = self._try_rule(apply_rule, target, access_data, o)
         return result
 
     def _try_rule(self, apply_rule, target, access_data, o):
-        try:
-            rule = self.rules[apply_rule]
-            return rule(target, access_data, o)
-        except KeyError as e:
+        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)
-        except Exception as e:
-            message = "Unknown exception: {0} for policy action: {1} in "\
-                      "policy file: {2}.".format(e, apply_rule, self.path)
-            LOG.debug(message)
-            raise rbac_exceptions.RbacParsingException(message)
+        else:
+            rule = self.rules[apply_rule]
+            return rule(target, access_data, o)
diff --git a/patrole_tempest_plugin/rbac_rule_validation.py b/patrole_tempest_plugin/rbac_rule_validation.py
index a6490e7..8de3d97 100644
--- a/patrole_tempest_plugin/rbac_rule_validation.py
+++ b/patrole_tempest_plugin/rbac_rule_validation.py
@@ -14,69 +14,198 @@
 #    under the License.
 
 import logging
+import sys
+import testtools
+
+import six
 
 from tempest import config
 from tempest.lib import exceptions
 from tempest import test
 
-from patrole_tempest_plugin import rbac_auth
 from patrole_tempest_plugin import rbac_exceptions
+from patrole_tempest_plugin import rbac_policy_parser
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
 
 
-def action(service, rule):
+def action(service, rule='', admin_only=False, expected_error_code=403,
+           extra_target_data={}):
+    """A decorator which does a policy check and matches it against test run.
+
+    A decorator which allows for positive and negative RBAC testing. Given
+    an OpenStack service and a policy action enforced by that service, an
+    oslo.policy lookup is performed by calling `authority.get_permission`.
+    The following cases are possible:
+
+    * If `allowed` is True and the test passes, this is a success.
+    * If `allowed` is True and the test fails, this is a failure.
+    * If `allowed` is False and the test passes, this is a failure.
+    * If `allowed` is False and the test fails, this is a success.
+
+    :param service: A OpenStack service: for example, "nova" or "neutron".
+    :param rule: A policy action defined in a policy.json file (or in code).
+    :param admin_only: Skips over oslo.policy check because the policy action
+                       defined by `rule` is not enforced by the service's
+                       policy enforcement logic. For example, Keystone v2
+                       performs an admin check for most of its endpoints. If
+                       True, `rule` is effectively ignored.
+    :param expected_error_code: Overrides default value of 403 (Forbidden)
+                                with endpoint-specific error code. Currently
+                                only supports 403 and 404. Support for 404
+                                is needed because some services, like Neutron,
+                                intentionally throw a 404 for security reasons.
+
+    :raises NotFound: if `service` is invalid or
+                      if Tempest credentials cannot be found.
+    :raises Forbidden: for bullet (2) above.
+    :raises RbacOverPermission: for bullet (3) above.
+    """
     def decorator(func):
+        role = CONF.rbac.rbac_test_role
+
         def wrapper(*args, **kwargs):
-            try:
-                caller_ref = None
-                if args and isinstance(args[0], test.BaseTestCase):
-                    caller_ref = args[0]
-                tenant_id = caller_ref.auth_provider.credentials.tenant_id
-                user_id = caller_ref.auth_provider.credentials.user_id
-            except AttributeError as e:
-                msg = ("{0}: tenant_id/user_id not found in "
-                       "cls.auth_provider.credentials".format(e))
-                LOG.error(msg)
-                raise rbac_exceptions.RbacResourceSetupFailed(msg)
+            if args and isinstance(args[0], test.BaseTestCase):
+                test_obj = args[0]
+            else:
+                raise rbac_exceptions.RbacResourceSetupFailed(
+                    '`rbac_rule_validation` decorator can only be applied to '
+                    'an instance of `tempest.test.BaseTestCase`.')
 
-            authority = rbac_auth.RbacAuthority(tenant_id, user_id, service)
-            allowed = authority.get_permission(rule, CONF.rbac.rbac_test_role)
+            if admin_only:
+                LOG.info("As admin_only is True, only admin role should be "
+                         "allowed to perform the API. Skipping oslo.policy "
+                         "check for policy action {0}.".format(rule))
+                allowed = CONF.rbac.rbac_test_role == CONF.identity.admin_role
+            else:
+                allowed = _is_authorized(test_obj, service, rule,
+                                         extra_target_data)
+
+            expected_exception, irregular_msg = _get_exception_type(
+                expected_error_code)
 
             try:
-                func(*args)
+                func(*args, **kwargs)
             except rbac_exceptions.RbacInvalidService as e:
                 msg = ("%s is not a valid service." % service)
                 LOG.error(msg)
                 raise exceptions.NotFound(
-                    "%s RbacInvalidService was: %s" %
-                    (msg, e))
-            except exceptions.Forbidden as e:
+                    "%s RbacInvalidService was: %s" % (msg, e))
+            except (expected_exception, rbac_exceptions.RbacActionFailed) as e:
+                if irregular_msg:
+                    LOG.warning(irregular_msg.format(rule, service))
                 if allowed:
                     msg = ("Role %s was not allowed to perform %s." %
-                           (CONF.rbac.rbac_test_role, rule))
+                           (role, rule))
                     LOG.error(msg)
                     raise exceptions.Forbidden(
-                        "%s exception was: %s" %
-                        (msg, e))
-            except rbac_exceptions.RbacActionFailed as e:
-                if allowed:
-                    msg = ("Role %s was not allowed to perform %s." %
-                           (CONF.rbac.rbac_test_role, rule))
-                    LOG.error(msg)
-                    raise exceptions.Forbidden(
-                        "%s RbacActionFailed was: %s" %
-                        (msg, e))
+                        "%s exception was: %s" % (msg, e))
+            except Exception as e:
+                exc_info = sys.exc_info()
+                error_details = exc_info[1].__str__()
+                msg = ("%s An unexpected exception has occurred: Expected "
+                       "exception was %s, which was not thrown."
+                       % (error_details, expected_exception.__name__))
+                LOG.error(msg)
+                six.reraise(exc_info[0], exc_info[0](msg), exc_info[2])
             else:
                 if not allowed:
                     LOG.error("Role %s was allowed to perform %s" %
-                              (CONF.rbac.rbac_test_role, rule))
+                              (role, rule))
                     raise rbac_exceptions.RbacOverPermission(
                         "OverPermission: Role %s was allowed to perform %s" %
-                        (CONF.rbac.rbac_test_role, rule))
+                        (role, rule))
             finally:
-                caller_ref.rbac_utils.switch_role(caller_ref,
-                                                  switchToRbacRole=False)
-        return wrapper
+                test_obj.rbac_utils.switch_role(test_obj,
+                                                toggle_rbac_role=False)
+
+        _wrapper = testtools.testcase.attr(role)(wrapper)
+        return _wrapper
     return decorator
+
+
+def _is_authorized(test_obj, service, rule_name, extra_target_data):
+    try:
+        project_id = test_obj.auth_provider.credentials.project_id
+        user_id = test_obj.auth_provider.credentials.user_id
+    except AttributeError as e:
+        msg = ("{0}: project_id/user_id not found in "
+               "cls.auth_provider.credentials".format(e))
+        LOG.error(msg)
+        raise rbac_exceptions.RbacResourceSetupFailed(msg)
+
+    try:
+        role = CONF.rbac.rbac_test_role
+        formatted_target_data = _format_extra_target_data(
+            test_obj, extra_target_data)
+        policy_parser = rbac_policy_parser.RbacPolicyParser(
+            project_id, user_id, service,
+            extra_target_data=formatted_target_data)
+        is_allowed = policy_parser.allowed(rule_name, role)
+
+        if is_allowed:
+            LOG.debug("[Action]: %s, [Role]: %s is allowed!", rule_name,
+                      role)
+        else:
+            LOG.debug("[Action]: %s, [Role]: %s is NOT allowed!",
+                      rule_name, role)
+        return is_allowed
+    except rbac_exceptions.RbacParsingException as e:
+        if CONF.rbac.strict_policy_check:
+            raise e
+        else:
+            raise testtools.TestCase.skipException(str(e))
+    return False
+
+
+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
+
+
+def _format_extra_target_data(test_obj, extra_target_data):
+    """Formats the "extra_target_data" dictionary with correct test data.
+
+    Before being formatted, "extra_target_data" is a dictionary that maps a
+    policy string like "trust.trustor_user_id" to a nested list of BaseTestCase
+    attributes. For example, the attribute list in:
+
+        "trust.trustor_user_id": "os.auth_provider.credentials.user_id"
+
+    is parsed by iteratively calling `getattr` until the value of "user_id"
+    is resolved. The resulting dictionary returns:
+
+        "trust.trustor_user_id": "the user_id of the `primary` credential"
+
+    :param test_obj: type BaseTestCase (tempest base test class)
+    :param extra_target_data: dictionary with unresolved string literals that
+                              reference nested BaseTestCase attributes
+    :returns: dictionary with resolved BaseTestCase attributes
+    """
+    attr_value = test_obj
+    formatted_target_data = {}
+
+    for user_attribute, attr_string in extra_target_data.items():
+        attrs = attr_string.split('.')
+        for attr in attrs:
+            attr_value = getattr(attr_value, attr)
+        formatted_target_data[user_attribute] = attr_value
+
+    return formatted_target_data
diff --git a/patrole_tempest_plugin/rbac_utils.py b/patrole_tempest_plugin/rbac_utils.py
index abbb435..4cddb8d 100644
--- a/patrole_tempest_plugin/rbac_utils.py
+++ b/patrole_tempest_plugin/rbac_utils.py
@@ -13,14 +13,15 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
+import sys
 import time
 
-from tempest.common import credentials_factory
-from tempest import config
-from tempest.test import BaseTestCase
-
 from oslo_log import log as logging
+import oslo_utils.uuidutils as uuid_utils
+import six
+
+from tempest.common import credentials_factory as credentials
+from tempest import config
 
 from patrole_tempest_plugin import rbac_exceptions
 
@@ -41,65 +42,134 @@
 @six.add_metaclass(Singleton)
 class RbacUtils(object):
 
-    def __init__(cls):
-        creds_provider = credentials_factory.get_credentials_provider(
-            name=__name__,
-            force_tenant_isolation=True,
-            identity_version=BaseTestCase.get_identity_version())
+    # References the last value of `toggle_rbac_role` that was passed to
+    # `switch_role`. Used for ensuring that `switch_role` is correctly used
+    # in a test file, so that false positives are prevented. The key used
+    # to index into the dictionary is the module path plus class name, which is
+    # unique.
+    switch_role_history = {}
+    admin_role_id = None
+    rbac_role_id = None
 
-        cls.creds_client = creds_provider.creds_client
-        cls.available_roles = cls.creds_client.roles_client.list_roles()
-        cls.admin_role_id = cls.rbac_role_id = None
-        for item in cls.available_roles['roles']:
-            if item['name'] == CONF.rbac.rbac_test_role:
-                cls.rbac_role_id = item['id']
-            if item['name'] == 'admin':
-                cls.admin_role_id = item['id']
+    def switch_role(self, test_obj, toggle_rbac_role=False):
+        self.user_id = test_obj.auth_provider.credentials.user_id
+        self.project_id = test_obj.auth_provider.credentials.tenant_id
+        self.token = test_obj.auth_provider.get_token()
+        self.identity_version = test_obj.get_identity_version()
 
-    def switch_role(cls, test_obj, switchToRbacRole=None):
-        LOG.debug('Switching role to: %s', switchToRbacRole)
-        # Check if admin and rbac roles exist.
-        if not cls.admin_role_id or not cls.rbac_role_id:
-            msg = ("Defined 'rbac_role' or 'admin' role does not exist"
-                   " in the system.")
+        if not credentials.is_admin_available(
+                identity_version=self.identity_version):
+            msg = "Missing Identity Admin API credentials in configuration."
             raise rbac_exceptions.RbacResourceSetupFailed(msg)
 
-        if not isinstance(switchToRbacRole, bool):
-            msg = ("Wrong value for parameter 'switchToRbacRole' is passed."
-                   " It should be either 'True' or 'False'.")
-            raise rbac_exceptions.RbacResourceSetupFailed(msg)
+        self.roles_client = test_obj.os_admin.roles_v3_client
+
+        LOG.debug('Switching role to: %s', toggle_rbac_role)
 
         try:
-            user_id = test_obj.auth_provider.credentials.user_id
-            project_id = test_obj.auth_provider.credentials.tenant_id
+            if not self.admin_role_id or not self.rbac_role_id:
+                self._get_roles()
 
-            cls._clear_user_roles(user_id, project_id)
+            rbac_utils._validate_switch_role(self, test_obj, toggle_rbac_role)
 
-            if switchToRbacRole:
-                cls.creds_client.roles_client.create_user_role_on_project(
-                    project_id, user_id, cls.rbac_role_id)
+            if toggle_rbac_role:
+                self._add_role_to_user(self.rbac_role_id)
             else:
-                cls.creds_client.roles_client.create_user_role_on_project(
-                    project_id, user_id, cls.admin_role_id)
-
+                self._add_role_to_user(self.admin_role_id)
         except Exception as exp:
             LOG.error(exp)
             raise
-
         finally:
-            if BaseTestCase.get_identity_version() != 'v3':
-                test_obj.auth_provider.clear_auth()
-                # Sleep to avoid 401 errors caused by rounding in timing of
-                # fernet token creation.
+            # NOTE(felipemonteiro): These two comments below are copied from
+            # tempest.api.identity.v2/v3.test_users.
+            #
+            # Reset auth again to verify the password restore does work.
+            # Clear auth restores the original credentials and deletes
+            # cached auth data.
+            test_obj.auth_provider.clear_auth()
+            # Fernet tokens are not subsecond aware and Keystone should only be
+            # precise to the second. Sleep to ensure we are passing the second
+            # boundary before attempting to authenticate. If token is of type
+            # uuid, then do not sleep.
+            if not uuid_utils.is_uuid_like(self.token):
                 time.sleep(1)
-                test_obj.auth_provider.set_auth()
+            test_obj.auth_provider.set_auth()
 
-    def _clear_user_roles(cls, user_id, tenant_id):
-        roles = cls.creds_client.roles_client.list_user_roles_on_project(
-            tenant_id, user_id)['roles']
+    def _add_role_to_user(self, role_id):
+        role_already_present = self._clear_user_roles(role_id)
+        if role_already_present:
+            return
+
+        self.roles_client.create_user_role_on_project(
+            self.project_id, self.user_id, role_id)
+
+    def _clear_user_roles(self, role_id):
+        roles = self.roles_client.list_user_roles_on_project(
+            self.project_id, self.user_id)['roles']
+
+        # If the user already has the role that is required, return early.
+        role_ids = [role['id'] for role in roles]
+        if role_ids == [role_id]:
+            return True
 
         for role in roles:
-            cls.creds_client.roles_client.delete_role_from_user_on_project(
-                tenant_id, user_id, role['id'])
+            self.roles_client.delete_role_from_user_on_project(
+                self.project_id, self.user_id, role['id'])
+
+        return False
+
+    def _validate_switch_role(self, test_obj, toggle_rbac_role):
+        """Validates that the rbac role passed to `switch_role` is legal.
+
+        Throws an error for the following improper usages of `switch_role`:
+            * `switch_role` is not called with a boolean value
+            * `switch_role` is never called in a test file, except in tearDown
+            * `switch_role` is called with the same boolean value twice
+        """
+        if not isinstance(toggle_rbac_role, bool):
+            raise rbac_exceptions.RbacResourceSetupFailed(
+                'toggle_rbac_role must be a boolean value.')
+
+        # The unique key is the combination of module path plus class name.
+        class_name = test_obj.__name__ if isinstance(test_obj, type) else \
+            test_obj.__class__.__name__
+        module_name = test_obj.__module__
+        key = '%s.%s' % (module_name, class_name)
+
+        self.switch_role_history.setdefault(key, None)
+
+        if self.switch_role_history[key] == toggle_rbac_role:
+            # If an exception was thrown, like a skipException or otherwise,
+            # then this is a legitimate reason why `switch_role` was not
+            # called, so only raise an exception if no current exception is
+            # being handled.
+            if sys.exc_info()[0] is None:
+                self.switch_role_history[key] = False
+                error_message = '`toggle_rbac_role` must not be called with '\
+                    'the same bool value twice. Make sure that you included '\
+                    'a rbac_utils.switch_role method call inside the test.'
+                LOG.error(error_message)
+                raise rbac_exceptions.RbacResourceSetupFailed(error_message)
+        else:
+            self.switch_role_history[key] = toggle_rbac_role
+
+    def _get_roles(self):
+        available_roles = self.roles_client.list_roles()
+        admin_role_id = rbac_role_id = None
+
+        for role in available_roles['roles']:
+            if role['name'] == CONF.rbac.rbac_test_role:
+                rbac_role_id = role['id']
+            if role['name'] == CONF.identity.admin_role:
+                admin_role_id = role['id']
+
+        if not admin_role_id or not rbac_role_id:
+            msg = "Role with name 'admin' does not exist in the system."\
+                if not admin_role_id else "Role defined by rbac_test_role "\
+                "does not exist in the system."
+            raise rbac_exceptions.RbacResourceSetupFailed(msg)
+
+        self.admin_role_id = admin_role_id
+        self.rbac_role_id = rbac_role_id
 
 rbac_utils = RbacUtils
diff --git a/patrole_tempest_plugin/tests/api/compute/admin/__init__.py b/patrole_tempest_plugin/tests/api/compute/admin/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/patrole_tempest_plugin/tests/api/compute/admin/__init__.py
+++ /dev/null
diff --git a/patrole_tempest_plugin/tests/api/compute/rbac_base.py b/patrole_tempest_plugin/tests/api/compute/rbac_base.py
index 625b5cf..bc02dbf 100644
--- a/patrole_tempest_plugin/tests/api/compute/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/compute/rbac_base.py
@@ -11,11 +11,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
-
 from tempest.api.compute import base as compute_base
 from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 
 from patrole_tempest_plugin.rbac_utils import rbac_utils
 
@@ -29,45 +28,26 @@
     @classmethod
     def skip_checks(cls):
         super(BaseV2ComputeRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
+        if not CONF.rbac.enable_rbac:
             raise cls.skipException(
                 '%s skipped as RBAC flag not enabled' % cls.__name__)
 
     @classmethod
     def setup_clients(cls):
         super(BaseV2ComputeRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
+        cls.auth_provider = cls.os_primary.auth_provider
         cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
-
-
-class BaseV2ComputeAdminRbacTest(compute_base.BaseV2ComputeAdminTest):
-
-    credentials = ['admin', 'primary']
-
-    @classmethod
-    def skip_checks(cls):
-        super(BaseV2ComputeAdminRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
-            raise cls.skipException(
-                '%s skipped as RBAC flag not enabled' % cls.__name__)
-
-    @classmethod
-    def setup_clients(cls):
-        super(BaseV2ComputeAdminRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
-        cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
 
     @classmethod
     def resource_setup(cls):
-        super(BaseV2ComputeAdminRbacTest, cls).resource_setup()
+        super(BaseV2ComputeRbacTest, cls).resource_setup()
         cls.flavors = []
 
     @classmethod
     def resource_cleanup(cls):
         cls.clear_flavors()
-        super(BaseV2ComputeAdminRbacTest, cls).resource_cleanup()
+        super(BaseV2ComputeRbacTest, cls).resource_cleanup()
 
     @classmethod
     def clear_flavors(cls):
diff --git a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_password_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_admin_password_rbac.py
similarity index 69%
rename from patrole_tempest_plugin/tests/api/compute/admin/test_admin_password_rbac.py
rename to patrole_tempest_plugin/tests/api/compute/test_admin_password_rbac.py
index 561bdae..08a06e6 100644
--- a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_password_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_admin_password_rbac.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
-
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
@@ -26,32 +24,29 @@
 CONF = config.CONF
 
 
-class PasswordAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
-
-    @classmethod
-    def setup_clients(cls):
-        super(PasswordAdminRbacTest, cls).setup_clients()
-        cls.client = cls.servers_client
+class AdminPasswordRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def skip_checks(cls):
-        super(PasswordAdminRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        super(AdminPasswordRbacTest, cls).skip_checks()
+        if not CONF.compute_feature_enabled.change_password:
+            raise cls.skipException('Change password not available.')
+
+    @classmethod
+    def setup_clients(cls):
+        super(AdminPasswordRbacTest, cls).setup_clients()
+        cls.client = cls.servers_client
 
     @classmethod
     def resource_setup(cls):
-        super(PasswordAdminRbacTest, cls).resource_setup()
+        super(AdminPasswordRbacTest, cls).resource_setup()
         cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id']
 
-    @testtools.skipUnless(CONF.compute_feature_enabled.change_password,
-                          'Change password not available.')
     @rbac_rule_validation.action(
         service="nova", rule="os_compute_api:os-admin-password")
     @decorators.idempotent_id('908a7d59-3a66-441c-94cf-38e57ed14956')
     def test_change_server_password(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.change_password(
             self.server_id,
             adminPass=data_utils.rand_password())
diff --git a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_server_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_admin_server_actions_rbac.py
similarity index 75%
rename from patrole_tempest_plugin/tests/api/compute/admin/test_admin_server_actions_rbac.py
rename to patrole_tempest_plugin/tests/api/compute/test_admin_server_actions_rbac.py
index 89190fc..a2d23af 100644
--- a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_server_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_admin_server_actions_rbac.py
@@ -15,31 +15,31 @@
 
 from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-
 CONF = config.CONF
 
 
-class ServersAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
+class AdminServerActionsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(ServersAdminRbacTest, cls).setup_clients()
+        super(AdminServerActionsRbacTest, cls).setup_clients()
         cls.client = cls.servers_client
 
     @classmethod
     def skip_checks(cls):
-        super(ServersAdminRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        super(AdminServerActionsRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('os-admin-actions', 'compute'):
+            msg = "%s skipped as os-admin-actions not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @classmethod
     def resource_setup(cls):
-        super(ServersAdminRbacTest, cls).resource_setup()
+        super(AdminServerActionsRbacTest, cls).resource_setup()
         cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id']
 
     @rbac_rule_validation.action(
@@ -47,7 +47,7 @@
         rule="os_compute_api:os-admin-actions:reset_state")
     @decorators.idempotent_id('ae84dd0b-f364-462e-b565-3457f9c019ef')
     def test_reset_server_state(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.reset_state(self.server_id, state='error')
         self.addCleanup(self.client.reset_state,
                         self.server_id,
@@ -58,7 +58,7 @@
         rule="os_compute_api:os-admin-actions:inject_network_info")
     @decorators.idempotent_id('ce48c340-51c1-4cff-9b6e-0cc5ef008630')
     def test_inject_network_info(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.inject_network_info(self.server_id)
 
     @rbac_rule_validation.action(
@@ -66,5 +66,5 @@
         rule="os_compute_api:os-admin-actions:reset_network")
     @decorators.idempotent_id('2911a242-15c4-4fcb-80d5-80a8930661b0')
     def test_reset_network(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.reset_network(self.server_id)
diff --git a/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py
index e2122c4..f355358 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py
@@ -13,27 +13,38 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class AgentsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def skip_checks(cls):
         super(AgentsRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
+        if not test.is_extension_enabled('os-agents', 'compute'):
             raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+                '%s skipped as os-agents not enabled' % cls.__name__)
 
     @rbac_rule_validation.action(
         service="nova", rule="os_compute_api:os-agents")
     @decorators.idempotent_id('d1bc6d97-07f5-4f45-ac29-1c619a6a7e27')
     def test_list_agents_rbac(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.agents_client.list_agents()
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:os-agents")
+    @decorators.idempotent_id('77d6cae4-1ced-47f7-af2e-3d6a45958fd6')
+    def test_create_agent(self):
+        params = {'hypervisor': 'kvm', 'os': 'win', 'architecture': 'x86',
+                  'version': '7.0', 'url': 'xxx://xxxx/xxx/xxx',
+                  'md5hash': 'add6bb58e139be103324d04d82d8f545'}
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        body = self.agents_client.create_agent(**params)['agent']
+        self.addCleanup(self.agents_client.delete_agent,
+                        body['agent_id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py
index 7c3d653..db504c0 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_aggregates_rbac.py
@@ -13,30 +13,28 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class AggregatesRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def skip_checks(cls):
         super(AggregatesRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-aggregates', 'compute'):
+            msg = "%s skipped as os-aggregates not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @classmethod
     def setup_clients(cls):
         super(AggregatesRbacTest, cls).setup_clients()
-        cls.hosts_client = cls.os.hosts_client
+        cls.hosts_client = cls.os_primary.hosts_client
 
     def _create_aggregate(self):
         agg_name = data_utils.rand_name('aggregate')
@@ -60,7 +58,7 @@
         service="nova", rule="os_compute_api:os-aggregates:create")
     @decorators.idempotent_id('ba754393-896e-434a-9704-452ff4a84f3f')
     def test_create_aggregate_rbac(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_aggregate()
 
     @rbac_rule_validation.action(
@@ -68,14 +66,14 @@
     @decorators.idempotent_id('8fb0b749-b120-4727-b3fb-bcfa3fa6f55b')
     def test_show_aggregate_rbac(self):
         aggregate_id = self._create_aggregate()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.aggregates_client.show_aggregate(aggregate_id)
 
     @rbac_rule_validation.action(
         service="nova", rule="os_compute_api:os-aggregates:index")
     @decorators.idempotent_id('146284da-5dd6-4c97-b598-42b480f014c6')
     def test_list_aggregate_rbac(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.aggregates_client.list_aggregates()['aggregates']
 
     @rbac_rule_validation.action(
@@ -83,7 +81,7 @@
     @decorators.idempotent_id('c94e0d69-99b6-477e-b301-2cd0e9d0ad81')
     def test_update_aggregate_rbac(self):
         aggregate_id = self._create_aggregate()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         new_name = data_utils.rand_name('aggregate')
         self.aggregates_client.update_aggregate(aggregate_id, name=new_name)
 
@@ -92,7 +90,7 @@
     @decorators.idempotent_id('5a50c5a6-0f12-4405-a1ce-2288ae895ea6')
     def test_delete_aggregate_rbac(self):
         aggregate_id = self._create_aggregate()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.aggregates_client.delete_aggregate(aggregate_id)
 
     @rbac_rule_validation.action(
@@ -100,7 +98,7 @@
     @decorators.idempotent_id('97e6e9df-5291-4faa-8147-755b2d1f1ce2')
     def test_add_host_to_aggregate_rbac(self):
         aggregate_id = self._create_aggregate()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._add_host_to_aggregate(aggregate_id)
 
     @rbac_rule_validation.action(
@@ -109,7 +107,7 @@
     def test_remove_host_from_aggregate_rbac(self):
         aggregate_id = self._create_aggregate()
         host_name = self._add_host_to_aggregate(aggregate_id)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.aggregates_client.remove_host(aggregate_id, host=host_name)
 
     @rbac_rule_validation.action(
@@ -119,7 +117,7 @@
         aggregate_id = self._create_aggregate()
         rand_key = data_utils.rand_name('key')
         rand_val = data_utils.rand_name('val')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.aggregates_client.set_metadata(
             aggregate_id,
             metadata={rand_key: rand_val})
diff --git a/patrole_tempest_plugin/tests/api/compute/test_assisted_volume_snapshot_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_assisted_volume_snapshot_rbac.py
index 9998bea..37e8573 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_assisted_volume_snapshot_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_assisted_volume_snapshot_rbac.py
@@ -49,7 +49,7 @@
         RBAC test for assisted volume snapshot role-create
         """
         self._create_and_attach()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.assisted_volume_snapshot_client.\
             create_volume_attachments(self.volume['id'],
                                       data_utils.rand_uuid())
@@ -68,6 +68,6 @@
         snapshot_id = data_utils.rand_uuid()
         self.assisted_volume_snapshot_client.\
             create_volume_attachments(self.volume['id'], snapshot_id)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.assisted_volume_snapshot_client.\
             delete_volume_attachments(snapshot_id, self.volume['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_attach_interfaces_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_attach_interfaces_rbac.py
index bfaeea6..90b60c9 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_attach_interfaces_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_attach_interfaces_rbac.py
@@ -17,6 +17,7 @@
 from tempest import config
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
@@ -34,9 +35,10 @@
     @classmethod
     def skip_checks(cls):
         super(AttachInterfacesRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-attach-interfaces', 'compute'):
+            msg = ("%s skipped as os-attach-interfaces not "
+                   "enabled." % cls.__name__)
+            raise cls.skipException(msg)
         if not CONF.compute_feature_enabled.interface_attach:
             raise cls.skipException(
                 "%s skipped as interface attachment is not available"
@@ -72,7 +74,7 @@
         service="nova",
         rule="os_compute_api:os-attach-interfaces")
     def test_list_interfaces(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_interfaces(self.server['id'])['interfaceAttachments']
 
     @decorators.idempotent_id('d2d3a24d-4738-4bce-a287-36d664746cde')
@@ -80,7 +82,7 @@
         service="nova",
         rule="os_compute_api:os-attach-interfaces:create")
     def test_create_interface(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._attach_interface_to_server()
 
     @decorators.idempotent_id('55b05692-ed44-4608-a84c-cd4219c82799')
@@ -89,5 +91,5 @@
         rule="os_compute_api:os-attach-interfaces:delete")
     def test_delete_interface(self):
         interface = self._attach_interface_to_server()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_interface(self.server['id'], interface['port_id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py
index 5078d43..0743d7c 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_availability_zone_rbac.py
@@ -11,34 +11,38 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class NovaAvailabilityZoneRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def skip_checks(cls):
         super(NovaAvailabilityZoneRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-availability-zone', 'compute'):
+            msg = ("%s skipped as os-availability-zone not "
+                   "enabled." % cls.__name__)
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(NovaAvailabilityZoneRbacTest, cls).setup_clients()
+        cls.client = cls.availability_zone_client
 
     @rbac_rule_validation.action(service="nova", rule="os_compute_api:"
                                  "os-availability-zone:list")
     @decorators.idempotent_id('cd34e7ea-d26e-4fa3-a8d0-f8883726ce3d')
     def test_get_availability_zone_list_rbac(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.os.availability_zone_client.list_availability_zones()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_availability_zones()
 
     @rbac_rule_validation.action(service="nova", rule="os_compute_api:"
                                  "os-availability-zone:detail")
     @decorators.idempotent_id('2f61c191-6ece-4f21-b487-39d749e3d38e')
     def test_get_availability_zone_list_detail_rbac(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.os.availability_zone_client.list_availability_zones(detail=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_availability_zones(detail=True)
diff --git a/patrole_tempest_plugin/tests/api/compute/test_config_drive_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_config_drive_rbac.py
index e46d1ba..794e0d2 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_config_drive_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_config_drive_rbac.py
@@ -40,7 +40,7 @@
         service="nova",
         rule="os_compute_api:os-config-drive")
     def test_create_test_server_with_config_drive(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # NOTE(felipemonteiro): This policy action is always enforced,
         # regardless whether the config_drive flag is set to true or false.
         # However, it has been explicitly set to true below, in case that this
diff --git a/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py
index eceef12..fe9cb11 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib import decorators
 from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
@@ -39,11 +40,12 @@
         super(DeferredDeleteRbacTest, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
+    @decorators.idempotent_id('189bfed4-1e6d-475c-bb8c-d57e60895391')
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:os-deferred-delete")
     def test_force_delete_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Force-deleting a server enforces os-deferred-delete according to the
         # following API: https://github.com/openstack/nova/blob/master/nova/api
         # /openstack/compute/deferred_delete.py
diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py
index 1704644..2019331 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_flavor_access_rbac.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from oslo_config import cfg
-from oslo_log import log
 
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
@@ -24,19 +23,18 @@
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
 CONF = cfg.CONF
-LOG = log.getLogger(__name__)
 
 
-class FlavorAccessAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
+class FlavorAccessRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(FlavorAccessAdminRbacTest, cls).setup_clients()
+        super(FlavorAccessRbacTest, cls).setup_clients()
         cls.client = cls.flavors_client
 
     @classmethod
     def skip_checks(cls):
-        super(FlavorAccessAdminRbacTest, cls).skip_checks()
+        super(FlavorAccessRbacTest, cls).skip_checks()
         if not test.is_extension_enabled('OS-FLV-EXT-DATA', 'compute'):
             msg = "%s skipped as OS-FLV-EXT-DATA extension not enabled."\
                   % cls.__name__
@@ -44,7 +42,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(FlavorAccessAdminRbacTest, cls).resource_setup()
+        super(FlavorAccessRbacTest, cls).resource_setup()
         cls.flavor_id = cls._create_flavor(is_public=False)['id']
         cls.public_flavor_id = CONF.compute.flavor_ref
         cls.tenant_id = cls.auth_provider.credentials.tenant_id
@@ -56,7 +54,7 @@
     def test_show_flavor(self):
         # NOTE(felipemonteiro): show_flavor enforces the specified policy
         # action, but only works if a public flavor is passed.
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_flavor(self.public_flavor_id)['flavor']
 
     @decorators.idempotent_id('39cb5c8f-9990-436f-9282-fc76a41d9bac')
@@ -64,7 +62,7 @@
         service="nova",
         rule="os_compute_api:os-flavor-access:add_tenant_access")
     def test_add_flavor_access(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.add_flavor_access(
             flavor_id=self.flavor_id, tenant_id=self.tenant_id)[
             'flavor_access']
@@ -81,6 +79,6 @@
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.client.remove_flavor_access,
                         flavor_id=self.flavor_id, tenant_id=self.tenant_id)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.remove_flavor_access(
             flavor_id=self.flavor_id, tenant_id=self.tenant_id)
diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py
index d742bec..0ee8d9a 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_flavor_extra_specs_rbac.py
@@ -22,30 +22,30 @@
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
 
-class FlavorExtraSpecsAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
+class FlavorExtraSpecsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(FlavorExtraSpecsAdminRbacTest, cls).setup_clients()
+        super(FlavorExtraSpecsRbacTest, cls).setup_clients()
         cls.client = cls.flavors_client
 
     @classmethod
     def skip_checks(cls):
-        super(FlavorExtraSpecsAdminRbacTest, cls).skip_checks()
+        super(FlavorExtraSpecsRbacTest, cls).skip_checks()
         if not test.is_extension_enabled('os-flavor-extra-specs', 'compute'):
             msg = "os-flavor-extra-specs extension not enabled."
             raise cls.skipException(msg)
 
     @classmethod
     def resource_setup(cls):
-        super(FlavorExtraSpecsAdminRbacTest, cls).resource_setup()
+        super(FlavorExtraSpecsRbacTest, cls).resource_setup()
         cls.flavor = cls._create_flavor()
 
     @classmethod
     def resource_cleanup(cls):
         cls.client.delete_flavor(cls.flavor['id'])
         cls.client.wait_for_resource_deletion(cls.flavor['id'])
-        super(FlavorExtraSpecsAdminRbacTest, cls).resource_cleanup()
+        super(FlavorExtraSpecsRbacTest, cls).resource_cleanup()
 
     def _set_flavor_extra_spec(self):
         rand_key = data_utils.rand_name('key')
@@ -64,7 +64,7 @@
         rule="os_compute_api:os-flavor-extra-specs:show")
     def test_show_flavor_extra_spec(self):
         key = self._set_flavor_extra_spec()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_flavor_extra_spec(self.flavor['id'], key)[key]
 
     @decorators.idempotent_id('fcffeca2-ed04-4e85-bf93-02fb5643f22b')
@@ -72,7 +72,7 @@
         service="nova",
         rule="os_compute_api:os-flavor-extra-specs:create")
     def test_set_flavor_extra_spec(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._set_flavor_extra_spec()
 
     @decorators.idempotent_id('42b85279-6bfa-4f58-b7a2-258c284f03c5')
@@ -81,7 +81,7 @@
         rule="os_compute_api:os-flavor-extra-specs:update")
     def test_update_flavor_extra_spec(self):
         key = self._set_flavor_extra_spec()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         update_val = data_utils.rand_name('val')
         self.client.update_flavor_extra_spec(self.flavor['id'], key,
                                              **{key: update_val})[key]
@@ -92,7 +92,7 @@
         rule="os_compute_api:os-flavor-extra-specs:delete")
     def test_unset_flavor_extra_spec(self):
         key = self._set_flavor_extra_spec()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.unset_flavor_extra_spec(self.flavor['id'], key)
 
     @decorators.idempotent_id('02c3831a-3ce9-476e-a722-d805ac2da621')
@@ -101,5 +101,5 @@
         rule="os_compute_api:os-flavor-extra-specs:index")
     def test_list_flavor_extra_specs(self):
         self._set_flavor_extra_spec()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_flavor_extra_specs(self.flavor['id'])['extra_specs']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py
new file mode 100644
index 0000000..7f070eb
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py
@@ -0,0 +1,44 @@
+#    Copyright 2017 AT&T Corporation.
+#    All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base
+
+
+class FlavorRxtxRbacTest(rbac_base.BaseV2ComputeRbacTest):
+
+    @classmethod
+    def setup_clients(cls):
+        super(FlavorRxtxRbacTest, cls).setup_clients()
+        cls.client = cls.flavors_client
+
+    @classmethod
+    def skip_checks(cls):
+        super(FlavorRxtxRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('os-flavor-rxtx', 'compute'):
+            msg = "os-flavor-rxtx extension not enabled."
+            raise cls.skipException(msg)
+
+    @decorators.idempotent_id('0278677c-6e69-4293-a387-b485781e61a1')
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:os-flavor-rxtx")
+    def test_create_flavor_rxtx(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        # Enforces os_compute_api:os-flavor-rxtx.
+        self.client.list_flavors(detail=True)['flavors']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py
index 8f82462..75cc8f4 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_floating_ip_pools_rbac.py
@@ -34,7 +34,7 @@
     @classmethod
     def setup_clients(cls):
         super(FloatingIpPoolsRbacTest, cls).setup_clients()
-        cls.client = cls.os.floating_ip_pools_client
+        cls.client = cls.os_primary.floating_ip_pools_client
 
     @classmethod
     def skip_checks(cls):
@@ -49,5 +49,5 @@
         service="nova",
         rule="os_compute_api:os-floating-ip-pools")
     def test_list_floating_ip_pools(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_floating_ip_pools()['floating_ip_pools']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_floating_ips_bulk_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_floating_ips_bulk_rbac.py
index f6a46c5..bff0612 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_floating_ips_bulk_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_floating_ips_bulk_rbac.py
@@ -34,7 +34,7 @@
     @classmethod
     def setup_clients(cls):
         super(FloatingIpsBulkRbacTest, cls).setup_clients()
-        cls.client = cls.os.floating_ips_bulk_client
+        cls.client = cls.os_primary.floating_ips_bulk_client
 
     @classmethod
     def skip_checks(cls):
@@ -49,5 +49,5 @@
         service="nova",
         rule="os_compute_api:os-floating-ips-bulk")
     def test_list_floating_ips_bulk(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_floating_ips_bulk()['floating_ip_info']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py
index 0de24be..0bd00a4 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_floating_ips_rbac.py
@@ -49,5 +49,5 @@
         service="nova",
         rule="os_compute_api:os-floating-ips")
     def test_list_floating_ips(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_floating_ips()['floating_ips']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py
index 6532731..0b7f2d1 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_hosts_rbac.py
@@ -13,33 +13,31 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
 
-
-class HostsAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
+class HostsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(HostsAdminRbacTest, cls).setup_clients()
-        cls.client = cls.os.hosts_client
+        super(HostsRbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.hosts_client
 
     @classmethod
     def skip_checks(cls):
-        super(HostsAdminRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        super(HostsRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('os-hosts', 'compute'):
+            msg = "%s skipped as os-hosts not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @decorators.idempotent_id('035b7935-2fae-4218-8d37-27fa83097494')
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:os-hosts")
     def test_list_hosts(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_hosts()['hosts']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py
index d4b97a5..ecd0fd3 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_hypervisor_rbac.py
@@ -20,16 +20,16 @@
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
 
-class HypervisorAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
+class HypervisorRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(HypervisorAdminRbacTest, cls).setup_clients()
+        super(HypervisorRbacTest, cls).setup_clients()
         cls.client = cls.hypervisor_client
 
     @classmethod
     def skip_checks(cls):
-        super(HypervisorAdminRbacTest, cls).skip_checks()
+        super(HypervisorRbacTest, cls).skip_checks()
         if not test.is_extension_enabled('os-hypervisors', 'compute'):
             msg = "%s skipped as os-hypervisors extension not enabled." \
                   % cls.__name__
@@ -40,5 +40,5 @@
         service="nova",
         rule="os_compute_api:os-hypervisors")
     def test_list_hypervisors(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_hypervisors()['hypervisors']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_images_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_images_rbac.py
new file mode 100644
index 0000000..b848509
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_images_rbac.py
@@ -0,0 +1,167 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base
+
+CONF = config.CONF
+
+
+class ImagesV235RbacTest(rbac_base.BaseV2ComputeRbacTest):
+    """RBAC tests for the Nova images client.
+
+    These APIs are proxy calls to the Image service. Consequently, no nova
+    policy actions are enforced; instead, only glance policy actions are
+    enforced. As such, these tests check that only glance policy actions are
+    executed.
+    """
+
+    # These tests will fail with a 404 starting from microversion 2.36.
+    min_microversion = '2.10'
+    max_microversion = '2.35'
+
+    @classmethod
+    def skip_checks(cls):
+        super(ImagesV235RbacTest, cls).skip_checks()
+        if not CONF.service_available.glance:
+            skip_msg = ("%s skipped as glance is not available" % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(ImagesV235RbacTest, cls).setup_clients()
+        cls.client = cls.compute_images_client
+        cls.glance_image_client = cls.os_primary.image_client_v2
+
+    @classmethod
+    def resource_setup(cls):
+        super(ImagesV235RbacTest, cls).resource_setup()
+        cls.image = cls.glance_image_client.create_image(
+            name=data_utils.rand_name('image'))
+
+    @classmethod
+    def resource_cleanup(cls):
+        cls.glance_image_client.delete_image(cls.image['id'])
+        super(ImagesV235RbacTest, cls).resource_cleanup()
+
+    @decorators.idempotent_id('b861f302-b72b-4055-81db-c62ff30b136d')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="get_images")
+    def test_list_images(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_images()
+
+    @decorators.idempotent_id('4365ae0f-15ee-4b54-a527-1679faaed140')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="get_images")
+    def test_list_images_with_details(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_images(detail=True)
+
+    @decorators.idempotent_id('886dfcae-51bf-4610-9e52-82d7189524c2')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="get_image")
+    def test_show_image_details(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_image(self.image['id'])
+
+    @decorators.idempotent_id('dbe09d4c-e615-48cb-b908-a06a0f410a8e')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="get_image")
+    def test_show_image_metadata_item(self):
+        self.client.set_image_metadata(self.image['id'], meta={'foo': 'bar'})
+        self.addCleanup(self.client.delete_image_metadata_item,
+                        self.image['id'], key='foo')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_image_metadata_item(self.image['id'], key='foo')
+
+    @decorators.idempotent_id('59f66079-d564-47e8-81b0-03c2e84d339e')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="get_image")
+    def test_list_image_metadata(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_image_metadata(self.image['id'])
+
+    @decorators.idempotent_id('5888c7aa-0803-46d4-a3fb-5d4729465cd5')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="delete_image")
+    def test_delete_image(self):
+        image = self.glance_image_client.create_image(
+            name=data_utils.rand_name('image'))
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.glance_image_client.delete_image, image['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_image(image['id'])
+
+    @decorators.idempotent_id('575604aa-909f-4b1b-a5a5-cfae1f63044b')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="modify_image")
+    def test_create_image_metadata(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        # NOTE(felipemonteiro): Although the name of the client function
+        # appears wrong, it's actually correct: update_image_metadata does an
+        # http post.
+        self.client.update_image_metadata(self.image['id'],
+                                          meta={'foo': 'bar'})
+        self.addCleanup(self.client.delete_image_metadata_item,
+                        self.image['id'], key='foo')
+
+    @decorators.idempotent_id('fb8c4eb6-00e5-454c-b8bc-0e801ec369f1')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="modify_image")
+    def test_update_image_metadata(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.set_image_metadata(self.image['id'], meta={'foo': 'bar'})
+        self.addCleanup(self.client.delete_image_metadata_item,
+                        self.image['id'], key='foo')
+
+    @decorators.idempotent_id('9c7c2036-af9b-49a8-8ba1-09b027ee5def')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="modify_image")
+    def test_update_image_metadata_item(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.set_image_metadata_item(self.image['id'],
+                                            meta={'foo': 'bar'}, key='foo')
+        self.addCleanup(self.client.delete_image_metadata_item,
+                        self.image['id'], key='foo')
+
+    @decorators.idempotent_id('5f0dc4e6-0761-4613-9bde-0a6acdc78f46')
+    @rbac_rule_validation.action(
+        service="glance",
+        rule="modify_image")
+    def test_delete_image_metadata_item(self):
+        self.client.set_image_metadata(self.image['id'], meta={'foo': 'bar'})
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_image_metadata_item,
+                        self.image['id'], key='foo')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_image_metadata_item(self.image['id'], key='foo')
diff --git a/patrole_tempest_plugin/tests/api/compute/test_instance_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_instance_actions_rbac.py
index dcf3c90..bd1e5c8 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_instance_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_instance_actions_rbac.py
@@ -46,7 +46,7 @@
         service="nova",
         rule="os_compute_api:os-instance-actions")
     def test_list_instance_actions(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_instance_actions(self.server['id'])
 
     @decorators.idempotent_id('eb04c439-4215-4029-9ccb-5b3c041bfc25')
@@ -54,7 +54,7 @@
         service="nova",
         rule="os_compute_api:os-instance-actions:events")
     def test_get_instance_action(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         instance_action = self.client.show_instance_action(
             self.server['id'], self.request_id)['instanceAction']
         if 'events' not in instance_action:
diff --git a/patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py
index e252054..cff3167 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_instance_usages_audit_log_rbac.py
@@ -20,12 +20,12 @@
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
 
-class InstanceUsagesAuditLogAdminRbacTest(
-        rbac_base.BaseV2ComputeAdminRbacTest):
+class InstanceUsagesAuditLogRbacTest(
+        rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def skip_checks(cls):
-        super(InstanceUsagesAuditLogAdminRbacTest, cls).skip_checks()
+        super(InstanceUsagesAuditLogRbacTest, cls).skip_checks()
         if not test.is_extension_enabled('os-instance-usage-audit-log',
                                          'compute'):
             msg = "os-instance-usage-audit-log extension not enabled."
@@ -33,13 +33,13 @@
 
     @classmethod
     def setup_clients(cls):
-        super(InstanceUsagesAuditLogAdminRbacTest, cls).setup_clients()
+        super(InstanceUsagesAuditLogRbacTest, cls).setup_clients()
         cls.client = cls.instance_usages_audit_log_client
 
     @decorators.idempotent_id('c80246c0-5c13-4ab0-97ba-91551cd53dc1')
     @rbac_rule_validation.action(
         service="nova", rule="os_compute_api:os-instance-usage-audit-log")
     def test_list_instance_usage_audit_logs(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_instance_usage_audit_logs()
         ["instance_usage_audit_logs"]
diff --git a/patrole_tempest_plugin/tests/api/compute/test_ips_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_ips_rbac.py
index 8ecc08c..600cfbe 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_ips_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_ips_rbac.py
@@ -15,6 +15,7 @@
 
 from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
@@ -32,9 +33,9 @@
     @classmethod
     def skip_checks(cls):
         super(IpsRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-ips', 'compute'):
+            msg = "%s skipped as os-ips not enabled." % cls.__name__
+            raise cls.skipException(msg)
         if not CONF.service_available.neutron:
             raise cls.skipException(
                 '%s skipped as Neutron is required' % cls.__name__)
@@ -54,7 +55,7 @@
         service="nova",
         rule="os_compute_api:ips:index")
     def test_list_addresses(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_addresses(self.server['id'])['addresses']
 
     @decorators.idempotent_id('fa43e7e5-0db9-48eb-9c6b-c11eb766b8e4')
@@ -64,6 +65,6 @@
     def test_list_addresses_by_network(self):
         addresses = self.client.list_addresses(self.server['id'])['addresses']
         address = next(iter(addresses))
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_addresses_by_network(
             self.server['id'], address)[address]
diff --git a/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py
index df470c6..f7b2ace 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py
@@ -41,7 +41,7 @@
         service="nova",
         rule="os_compute_api:os-keypairs:create")
     def test_create_keypair(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_keypair()
 
     @decorators.idempotent_id('85a5eb99-40ec-4e77-9358-bee2cdf9d7df')
@@ -50,7 +50,7 @@
         rule="os_compute_api:os-keypairs:show")
     def test_show_keypair(self):
         kp_name = self._create_keypair()['keypair']['name']
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_keypair(kp_name)
 
     @decorators.idempotent_id('6bff9f1c-b809-43c1-8d63-61fbd19d49d3')
@@ -59,7 +59,7 @@
         rule="os_compute_api:os-keypairs:delete")
     def test_delete_keypair(self):
         kp_name = self._create_keypair()['keypair']['name']
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_keypair(kp_name)
 
     @decorators.idempotent_id('6bb31346-ff7f-4b10-978e-170ac5fcfa3e')
@@ -67,5 +67,5 @@
         service="nova",
         rule="os_compute_api:os-keypairs:index")
     def test_index_keypair(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_keypairs()
diff --git a/patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py
index fb631e6..f16a635 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_limits_rbac.py
@@ -11,14 +11,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class LimitsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
@@ -30,13 +28,13 @@
     @classmethod
     def skip_checks(cls):
         super(LimitsRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-limits', 'compute'):
+            msg = "%s skipped as os-limits not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @rbac_rule_validation.action(service="nova",
                                  rule="os_compute_api:limits")
     @decorators.idempotent_id('3fb60f83-9a5f-4fdd-89d9-26c3710844a1')
     def test_show_limits(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_limits()
diff --git a/patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py
index 251b750..b6c6c5f 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_migrations_rbac.py
@@ -13,33 +13,31 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
 
-
-class MigrationsAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
+class MigrationsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(MigrationsAdminRbacTest, cls).setup_clients()
+        super(MigrationsRbacTest, cls).setup_clients()
         cls.client = cls.migrations_client
 
     @classmethod
     def skip_checks(cls):
-        super(MigrationsAdminRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        super(MigrationsRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('os-migrations', 'compute'):
+            msg = "%s skipped as os-migrations not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @decorators.idempotent_id('5795231c-3729-448c-a072-9a225db1a328')
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:os-migrations:index")
     def test_list_services(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_migrations()['migrations']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_multinic_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_multinic_rbac.py
new file mode 100644
index 0000000..7e353be
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_multinic_rbac.py
@@ -0,0 +1,69 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest import config
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base
+
+CONF = config.CONF
+
+
+class MultinicV210RbacTest(rbac_base.BaseV2ComputeRbacTest):
+
+    min_microversion = '2.10'
+    max_microversion = '2.36'
+
+    @classmethod
+    def setup_clients(cls):
+        super(MultinicV210RbacTest, cls).setup_clients()
+        cls.client = cls.servers_client
+
+    @classmethod
+    def skip_checks(cls):
+        super(MultinicV210RbacTest, cls).skip_checks()
+        if not CONF.service_available.neutron:
+            raise cls.skipException("Neutron is required")
+        if not CONF.compute_feature_enabled.interface_attach:
+            raise cls.skipException("Interface attachment is not available.")
+
+    @classmethod
+    def setup_credentials(cls):
+        # This test class requires network and subnet
+        cls.set_network_resources(network=True, subnet=True)
+        super(MultinicV210RbacTest, cls).setup_credentials()
+
+    @classmethod
+    def resource_setup(cls):
+        super(MultinicV210RbacTest, cls).resource_setup()
+        cls.server = cls.create_test_server(wait_until='ACTIVE')
+
+    @rbac_rule_validation.action(
+        service="nova", rule="os_compute_api:os-multinic")
+    @decorators.idempotent_id('bd3e2c74-130a-40f0-8085-124d93fe67da')
+    def test_add_fixed_ip(self):
+        """Add fixed IP to server."""
+        interfaces = (self.interfaces_client.list_interfaces(self.server['id'])
+                      ['interfaceAttachments'])
+        if interfaces:
+            network_id = interfaces[0]['net_id']
+        else:
+            network_id = self.interfaces_client.create_interface(
+                self.server['id'])['interfaceAttachment']['net_id']
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.add_fixed_ip(self.server['id'],
+                                 networkId=network_id)
diff --git a/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py
index a7f8447..f6706a7 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py
@@ -28,7 +28,7 @@
     def setup_clients(cls):
         super(QuotaSetsRbacTest, cls).setup_clients()
         cls.client = cls.quotas_client
-        cls.projects_client = cls.os.projects_client
+        cls.projects_client = cls.os_primary.projects_client
 
     @classmethod
     def skip_checks(cls):
@@ -60,7 +60,7 @@
         default_quota_set.pop('id')
         new_quota_set = {'injected_file_content_bytes': 20480}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.update_quota_set(self.tenant_id,
                                      force=True,
                                      **new_quota_set)['quota_set']
@@ -72,7 +72,7 @@
         service="nova",
         rule="os_compute_api:os-quota-sets:defaults")
     def test_show_default_quota_set(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_default_quota_set(self.tenant_id)['quota_set']
 
     @decorators.idempotent_id('e8169ac4-c402-4864-894e-aba74e3a459c')
@@ -80,7 +80,7 @@
         service="nova",
         rule="os_compute_api:os-quota-sets:show")
     def test_show_quota_set(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_quota_set(self.tenant_id)['quota_set']
 
     @decorators.idempotent_id('4e240644-bf61-4872-9c32-8289ee2fdbbd')
@@ -94,7 +94,7 @@
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.projects_client.delete_project, project_id)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_quota_set(project_id)
 
     @decorators.idempotent_id('ac9184b6-f3b3-4e17-a632-4b92c6500f86')
@@ -102,5 +102,5 @@
         service="nova",
         rule="os_compute_api:os-quota-sets:detail")
     def test_show_quota_set_details(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_quota_set(self.tenant_id, detail=True)['quota_set']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_rescue_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_rescue_rbac.py
index c5fe31a..277ba1b 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_rescue_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_rescue_rbac.py
@@ -13,14 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class RescueRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
@@ -32,9 +30,9 @@
     @classmethod
     def skip_checks(cls):
         super(RescueRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-rescue', 'compute'):
+            msg = "%s skipped as os-rescue not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @classmethod
     def resource_setup(cls):
@@ -46,5 +44,5 @@
         rule="os_compute_api:os-rescue")
     @decorators.idempotent_id('fbbb2afc-ed0e-4552-887d-ac00fb5d436e')
     def test_rescue_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.rescue_server(self.server['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py
index d65e7e3..f45632e 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py
@@ -26,5 +26,5 @@
         rule="os_compute_api:os-security-groups")
     @decorators.idempotent_id('4ac58e49-48c1-4fca-a6c3-3f95fb99eb77')
     def test_server_security_groups(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.security_groups_client.list_security_groups()
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py
index 7ee3c7e..86b650e 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py
@@ -18,6 +18,8 @@
 
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -36,17 +38,34 @@
     def setup_clients(cls):
         super(ServerActionsRbacTest, cls).setup_clients()
         cls.client = cls.servers_client
+        cls.snapshots_client = cls.snapshots_extensions_client
 
     @classmethod
     def resource_setup(cls):
         cls.set_validation_resources()
         super(ServerActionsRbacTest, cls).resource_setup()
+        # Create test server
         cls.server_id = cls.create_test_server(wait_until='ACTIVE',
                                                validatable=True)['id']
         cls.flavor_ref = CONF.compute.flavor_ref
         cls.flavor_ref_alt = CONF.compute.flavor_ref_alt
         cls.image_ref = CONF.compute.image_ref
 
+        # Create a volume
+        volume_name = data_utils.rand_name(cls.__name__ + '-volume')
+        name_field = 'name'
+        if not CONF.volume_feature_enabled.api_v2:
+            name_field = 'display_name'
+
+        params = {name_field: volume_name,
+                  'imageRef': CONF.compute.image_ref,
+                  'size': CONF.volume.volume_size}
+        volume = cls.volumes_client.create_volume(**params)['volume']
+        waiters.wait_for_volume_resource_status(cls.volumes_client,
+                                                volume['id'], 'available')
+        cls.volumes.append(volume)
+        cls.volume_id = volume['id']
+
     def setUp(self):
         super(ServerActionsRbacTest, self).setUp()
         try:
@@ -64,6 +83,56 @@
             self.__class__.server_id = self.rebuild_server(
                 self.server_id, validatable=True)
 
+    @classmethod
+    def resource_cleanup(cls):
+        # If a test case creates an image from a server that is created with
+        # a volume, a volume snapshot will automatically be created by default.
+        # We need to delete the volume snapshot.
+        try:
+            body = cls.snapshots_extensions_client.list_snapshots()
+            volume_snapshots = body['snapshots']
+        except Exception:
+            LOG.info("Cannot retrieve snapshots for cleanup.")
+        else:
+            for snapshot in volume_snapshots:
+                if snapshot['volumeId'] == cls.volume_id:
+                    # Wait for snapshot status to become 'available' before
+                    # deletion
+                    waiters.wait_for_volume_resource_status(
+                        cls.snapshots_client, snapshot['id'], 'available')
+                    test_utils.call_and_ignore_notfound_exc(
+                        cls.snapshots_client.delete_snapshot, snapshot['id'])
+
+            for snapshot in volume_snapshots:
+                if snapshot['volumeId'] == cls.volume_id:
+                    test_utils.call_and_ignore_notfound_exc(
+                        cls.snapshots_client.wait_for_resource_deletion,
+                        snapshot['id'])
+
+        super(ServerActionsRbacTest, cls).resource_cleanup()
+
+    def _create_test_server_with_volume(self, volume_id):
+        # Create a server with the volume created earlier
+        server_name = data_utils.rand_name(self.__class__.__name__ + "-server")
+        bd_map_v2 = [{'uuid': volume_id,
+                      'source_type': 'volume',
+                      'destination_type': 'volume',
+                      'boot_index': 0,
+                      'delete_on_termination': True}]
+        device_mapping = {'block_device_mapping_v2': bd_map_v2}
+
+        # Since the server is booted from volume, the imageRef does not need
+        # to be specified.
+        server = self.client.create_server(name=server_name,
+                                           imageRef='',
+                                           flavorRef=CONF.compute.flavor_ref,
+                                           **device_mapping)['server']
+
+        waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
+
+        self.servers.append(server)
+        return server
+
     def _test_start_server(self):
         self.client.start_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id,
@@ -94,7 +163,7 @@
         rule="os_compute_api:servers:stop")
     @decorators.idempotent_id('ab4a17d2-166f-4a6d-9944-f17baa576cf2')
     def test_stop_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._test_stop_server()
 
     @test.attr(type='slow')
@@ -104,7 +173,7 @@
     @decorators.idempotent_id('8876bfa9-4d10-406e-a335-a57e451abb12')
     def test_start_server(self):
         self._test_stop_server()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._test_start_server()
 
     @test.attr(type='slow')
@@ -115,7 +184,7 @@
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
     def test_resize_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._test_resize_server(self.flavor_ref_alt)
 
     @test.attr(type='slow')
@@ -127,7 +196,7 @@
                           'Resize is not available.')
     def test_revert_resize_server(self):
         self._test_resize_server(self.flavor_ref_alt)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._test_revert_resize_server()
 
     @test.attr(type='slow')
@@ -139,7 +208,7 @@
                           'Resize is not available.')
     def test_confirm_resize_server(self):
         self._test_resize_server(self.flavor_ref_alt)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.addCleanup(
             lambda: (self._test_resize_server(self.flavor_ref),
                      self._test_confirm_resize_server())
@@ -151,7 +220,7 @@
         rule="os_compute_api:servers:rebuild")
     @decorators.idempotent_id('54b1a30b-c96c-472c-9c83-ccaf6ec7e20b')
     def test_rebuild_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.rebuild_server(self.server_id, self.image_ref)
         waiters.wait_for_server_status(self.client, self.server_id,
                                        'ACTIVE')
@@ -161,7 +230,7 @@
         rule="os_compute_api:servers:reboot")
     @decorators.idempotent_id('19f27856-56e1-44f8-8615-7257f6b85cbb')
     def test_reboot_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.reboot_server(self.server_id, type='HARD')
         waiters.wait_for_server_status(self.client, self.server_id,
                                        'ACTIVE')
@@ -171,7 +240,7 @@
         rule="os_compute_api:servers:index")
     @decorators.idempotent_id('631f0d86-7607-4198-8312-9da2f05464a4')
     def test_server_index(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_servers(minimal=True)
 
     @rbac_rule_validation.action(
@@ -179,7 +248,7 @@
         rule="os_compute_api:servers:detail")
     @decorators.idempotent_id('96093480-3ce5-4a8b-b569-aed870379c24')
     def test_server_detail(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_servers(detail=True)
 
     @rbac_rule_validation.action(
@@ -187,7 +256,7 @@
         rule="os_compute_api:servers:detail:get_all_tenants")
     @decorators.idempotent_id('a9e5a1c0-acfe-49a2-b2b1-fd8b19d61f71')
     def test_server_detail_all_tenants(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_servers(detail=True, all_tenants=1)
 
     @rbac_rule_validation.action(
@@ -195,7 +264,7 @@
         rule="os_compute_api:servers:index:get_all_tenants")
     @decorators.idempotent_id('4b93ba56-69e6-41f5-82c4-84a5c4c42091')
     def test_server_index_all_tenants(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_servers(minimal=True, all_tenants=1)
 
     @rbac_rule_validation.action(
@@ -203,9 +272,32 @@
         rule="os_compute_api:servers:show")
     @decorators.idempotent_id('eaaf4f51-31b5-497f-8f0f-f527e5f70b83')
     def test_show_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_server(self.server_id)
 
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:create_image")
+    @decorators.idempotent_id('ba0ac859-99f4-4055-b5e0-e0905a44d331')
+    def test_create_image(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+
+        # This function will also call show image
+        self.create_image_from_server(self.server_id,
+                                      wait_until='ACTIVE')
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:create_image:allow_volume_backed")
+    @decorators.idempotent_id('8b869f73-49b3-4cc4-a0ce-ef64f8e1d6f9')
+    def test_create_image_volume_backed(self):
+        server = self._create_test_server_with_volume(self.volume_id)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+
+        # This function will also call show image
+        self.create_image_from_server(server['id'],
+                                      wait_until='ACTIVE')
+
 
 class ServerActionsV216RbacTest(rbac_base.BaseV2ComputeRbacTest):
 
@@ -249,10 +341,39 @@
         rule="os_compute_api:servers:show:host_status")
     @decorators.idempotent_id('736da575-86f8-4b2a-9902-dd37dc9a409b')
     def test_show_server_host_status(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         server = self.client.show_server(self.server_id)['server']
 
         if 'host_status' not in server:
             LOG.info("host_status attribute not returned when role doesn't "
                      "have permission to access it.")
             raise rbac_exceptions.RbacActionFailed
+
+
+class ServerActionsV214RbacTest(rbac_base.BaseV2ComputeRbacTest):
+
+    min_microversion = '2.14'
+    max_microversion = 'latest'
+
+    @classmethod
+    def setup_clients(cls):
+        super(ServerActionsV214RbacTest, cls).setup_clients()
+        cls.client = cls.servers_client
+
+    @classmethod
+    def resource_setup(cls):
+        cls.set_validation_resources()
+        super(ServerActionsV214RbacTest, cls).resource_setup()
+        cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id']
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:os-evacuate")
+    @decorators.idempotent_id('78ecef3c-faff-412a-83be-47651963eb21')
+    def test_evacuate_server(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.assertRaisesRegex(lib_exc.NotFound,
+                               "Compute host fake-host not found.",
+                               self.client.evacuate_server,
+                               self.server_id,
+                               host='fake-host')
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_diagnostics_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_diagnostics_rbac.py
index dd98b11..2a309e3 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_diagnostics_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_diagnostics_rbac.py
@@ -13,14 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class ServerDiagnosticsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
@@ -32,9 +30,10 @@
     @classmethod
     def skip_checks(cls):
         super(ServerDiagnosticsRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-server-diagnostics', 'compute'):
+            msg = ("%s skipped as os-server-diagnostics not "
+                   "enabled." % cls.__name__)
+            raise cls.skipException(msg)
 
     @classmethod
     def resource_setup(cls):
@@ -46,5 +45,5 @@
         rule="os_compute_api:os-server-diagnostics")
     @decorators.idempotent_id('5dabfcc4-bedb-417b-8247-b3ee7c5c0f3e')
     def test_show_server_diagnostics(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_server_diagnostics(self.server['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py
index 6d1fdbd..a75f550 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_groups_rbac.py
@@ -13,14 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class ServerGroupsRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
@@ -32,9 +30,9 @@
     @classmethod
     def skip_checks(cls):
         super(ServerGroupsRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-server-groups', 'compute'):
+            msg = "%s skipped as os-server-groups not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @classmethod
     def resource_setup(cls):
@@ -46,7 +44,7 @@
         rule="os_compute_api:os-server-groups:create")
     @decorators.idempotent_id('7f3eae94-6130-47e9-81ac-34009f55be2f')
     def test_create_server_group(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.create_test_server_group()
 
     @rbac_rule_validation.action(
@@ -55,7 +53,7 @@
     @decorators.idempotent_id('832d9be3-632e-47b2-93d2-5897db43e3e2')
     def test_delete_server_group(self):
         server_group = self.create_test_server_group()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_server_group(server_group['id'])
 
     @rbac_rule_validation.action(
@@ -63,7 +61,7 @@
         rule="os_compute_api:os-server-groups:index")
     @decorators.idempotent_id('5eccd67f-5945-483b-b1c8-de851ebfc1c1')
     def test_list_server_groups(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_server_groups()
 
     @rbac_rule_validation.action(
@@ -72,5 +70,5 @@
     @decorators.idempotent_id('62534e3f-7e99-4a3d-a08e-33e056460cf2')
     def test_show_server_group(self):
         server_group = self.create_test_server_group()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_server_group(server_group['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_migrations_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_migrations_rbac.py
new file mode 100644
index 0000000..38ef552
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_migrations_rbac.py
@@ -0,0 +1,100 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import testtools
+
+from tempest.common import waiters
+from tempest import config
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base as base
+
+CONF = config.CONF
+
+
+class MigrateServerV225RbacTest(base.BaseV2ComputeRbacTest):
+    min_microversion = '2.25'
+    max_microversion = 'latest'
+    block_migration = 'auto'
+
+    @classmethod
+    def skip_checks(cls):
+        super(MigrateServerV225RbacTest, cls).skip_checks()
+
+        if CONF.compute.min_compute_nodes < 2:
+            raise cls.skipException(
+                "Less than 2 compute nodes, skipping migration tests.")
+
+    @classmethod
+    def setup_clients(cls):
+        super(MigrateServerV225RbacTest, cls).setup_clients()
+        cls.client = cls.servers_client
+        cls.admin_servers_client = cls.os_admin.servers_client
+        cls.hosts_client = cls.os_primary.hosts_client
+
+    def _get_server_details(self, server_id):
+        body = self.client.show_server(server_id)['server']
+        return body
+
+    def _get_host_for_server(self, server_id):
+        return self._get_server_details(server_id)['OS-EXT-SRV-ATTR:host']
+
+    def _get_host_other_than(self, host):
+        for target_host in self._get_compute_hostnames():
+            if host != target_host:
+                return target_host
+
+    def _get_compute_hostnames(self):
+        body = self.hosts_client.list_hosts()['hosts']
+        return [
+            host_record['host_name']
+            for host_record in body
+            if host_record['service'] == 'compute'
+        ]
+
+    @test.attr(type='slow')
+    @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+                          'Cold migration not available.')
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:os-migrate-server:migrate")
+    @decorators.idempotent_id('c6f1607c-9fed-4c00-807e-9ba675b98b1b')
+    def test_cold_migration(self):
+        server = self.create_test_server(wait_until="ACTIVE")
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.migrate_server(server['id'])
+        waiters.wait_for_server_status(self.admin_servers_client,
+                                       server['id'], 'VERIFY_RESIZE')
+
+    @test.attr(type='slow')
+    @testtools.skipUnless(CONF.compute_feature_enabled.live_migration,
+                          'Live migration feature is not enabled.')
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:os-migrate-server:migrate_live")
+    @decorators.idempotent_id('33520834-72c8-4edb-a189-a2e0fc9eb0d3')
+    def test_migration_live(self):
+        server_id = self.create_test_server(wait_until="ACTIVE",
+                                            volume_backed=False)['id']
+        actual_host = self._get_host_for_server(server_id)
+        target_host = self._get_host_other_than(actual_host)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.live_migrate_server(
+            server_id, host=target_host, block_migration=self.block_migration)
+        waiters.wait_for_server_status(self.admin_servers_client,
+                                       server_id, "ACTIVE")
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_password_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_password_rbac.py
index 5ca7b16..0a0a660 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_password_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_password_rbac.py
@@ -38,12 +38,20 @@
     @classmethod
     def resource_setup(cls):
         super(ServerPasswordRbacTest, cls).resource_setup()
-        cls.server = cls.create_test_server()
+        cls.server = cls.create_test_server(wait_until="ACTIVE")
 
-    @decorators.idempotent_id('43ad7995-2f12-41cd-8ef1-bae9ffc36818')
+    @decorators.idempotent_id('aaf43f78-c178-4581-ac18-14afd3f1f6ba')
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:os-server-password")
-    def test_delete_password(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+    def test_delete_server_password(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_password(self.server['id'])
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:os-server-password")
+    @decorators.idempotent_id('f677971a-7d20-493c-977f-6ff0a74b5b2c')
+    def test_get_server_password(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_password(self.server['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py
new file mode 100644
index 0000000..b71887c
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py
@@ -0,0 +1,185 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_log import log
+
+from tempest.common import waiters
+from tempest import config
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions
+
+from patrole_tempest_plugin import rbac_exceptions
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base as base
+
+CONF = config.CONF
+LOG = log.getLogger(__name__)
+
+
+class ComputeServersRbacTest(base.BaseV2ComputeRbacTest):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ComputeServersRbacTest, cls).setup_clients()
+        cls.client = cls.servers_client
+        cls.networks_client = cls.os_primary.networks_client
+        cls.subnets_client = cls.os_primary.subnets_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(ComputeServersRbacTest, cls).resource_setup()
+
+        # Create a volume
+        volume_name = data_utils.rand_name(cls.__name__ + '-volume')
+        name_field = 'name'
+        if not CONF.volume_feature_enabled.api_v2:
+            name_field = 'display_name'
+
+        params = {name_field: volume_name,
+                  'imageRef': CONF.compute.image_ref,
+                  'size': CONF.volume.volume_size}
+
+        volume = cls.volumes_client.create_volume(**params)['volume']
+        waiters.wait_for_volume_resource_status(cls.volumes_client,
+                                                volume['id'], 'available')
+        cls.volumes.append(volume)
+        cls.volume_id = volume['id']
+
+    def _create_network_resources(self):
+        # Create network
+        network_name = data_utils.rand_name(
+            self.__class__.__name__ + '-network')
+
+        network = self.networks_client.create_network(
+            **{'name': network_name})['network']
+
+        # Create subnet for the network
+        subnet_name = data_utils.rand_name(self.__class__.__name__ + '-subnet')
+        subnet = self.subnets_client.create_subnet(
+            name=subnet_name,
+            network_id=network['id'],
+            cidr=CONF.network.project_network_cidr,
+            ip_version=4)['subnet']
+
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.networks_client.delete_network, network['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.subnets_client.delete_subnet, subnet['id'])
+
+        return network
+
+    def _create_test_server_with_volume(self, volume_id):
+        # Create a server with the volume created earlier
+        server_name = data_utils.rand_name(self.__class__.__name__ + "-server")
+        bd_map_v2 = [{'uuid': volume_id,
+                      'source_type': 'volume',
+                      'destination_type': 'volume',
+                      'boot_index': 0,
+                      'delete_on_termination': True}]
+        device_mapping = {'block_device_mapping_v2': bd_map_v2}
+
+        # Since the server is booted from volume, the imageRef does not need
+        # to be specified.
+        server = self.client.create_server(name=server_name,
+                                           imageRef='',
+                                           flavorRef=CONF.compute.flavor_ref,
+                                           **device_mapping)['server']
+
+        waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
+
+        self.servers.append(server)
+        return server
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:create")
+    @decorators.idempotent_id('4f34c73a-6ddc-4677-976f-71320fa855bd')
+    def test_create_server(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.create_test_server(wait_until='ACTIVE')
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:create:forced_host")
+    @decorators.idempotent_id('0ae3c401-52ab-41bc-ab96-c598a65d9ae5')
+    def test_create_server_forced_host(self):
+        # Retrieve 'nova' zone host information from availiability_zone_list
+        zones = self.availability_zone_client.list_availability_zones(
+            detail=True)['availabilityZoneInfo']
+        hosts = [zone['hosts'] for zone in zones if zone['zoneName'] == 'nova']
+
+        # We just need any host out of the hosts list to build the
+        # availability_zone attribute. So, picking the first one is fine.
+        # The first key of the dictionary specifies the host name.
+        host = hosts[0].keys()[0]
+        availability_zone = 'nova:' + host
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.create_test_server(wait_until='ACTIVE',
+                                availability_zone=availability_zone)
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:create:attach_volume")
+    @decorators.idempotent_id('eeddac5e-15aa-454f-838d-db608aae4dd8')
+    def test_create_server_attach_volume(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._create_test_server_with_volume(self.volume_id)
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:create:attach_network")
+    @decorators.idempotent_id('b44cd4ff-50a4-42ce-ada3-724e213cd540')
+    def test_create_server_attach_network(self):
+        network = self._create_network_resources()
+        network_id = {'uuid': network['id']}
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        server = self.create_test_server(wait_until='ACTIVE',
+                                         networks=[network_id])
+
+        # The network resources created is for this test case only. We will
+        # clean them up after this test case. In order to do that,
+        # we need to clean up the server first.
+        self.addCleanup(waiters.wait_for_server_termination,
+                        self.client, server['id'])
+        self.addCleanup(self.client.delete_server, server['id'])
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:delete")
+    @decorators.idempotent_id('062e3440-e873-4b41-9317-bf6d8be50c12')
+    def test_delete_server(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_server(server['id'])
+        waiters.wait_for_server_termination(self.client, server['id'])
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:servers:update")
+    @decorators.idempotent_id('077b17cb-5621-43b9-8adf-5725f0d7a863')
+    def test_update_server(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+        new_name = data_utils.rand_name('server')
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        try:
+            self.client.update_server(server['id'], name=new_name)
+        except exceptions.ServerFault as e:
+            # Some other policy may have blocked it.
+            LOG.info("ServerFault exception caught. Some other policy "
+                     "blocked updating of server")
+            raise rbac_exceptions.RbacActionFailed(e)
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py
index 6d88557..4de63ce 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py
@@ -54,7 +54,7 @@
         service="nova",
         rule="os_compute_api:os-server-tags:index")
     def test_list_tags(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_tags(self.server['id'])['tags']
 
     @decorators.idempotent_id('9297c99e-94eb-429f-93cf-9b1838e33622')
@@ -63,7 +63,7 @@
         rule="os_compute_api:os-server-tags:show")
     def test_check_tag_existence(self):
         tag_name = self._add_tag_to_server()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.check_tag_existence(self.server['id'], tag_name)
 
     @decorators.idempotent_id('0d84ee94-d3ca-4635-8edf-b7f67ab8e4a3')
@@ -71,7 +71,7 @@
         service="nova",
         rule="os_compute_api:os-server-tags:update")
     def test_update_tag(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._add_tag_to_server()
 
     @decorators.idempotent_id('115c2694-00aa-41ee-99f6-9eab4040c182')
@@ -80,7 +80,7 @@
         rule="os_compute_api:os-server-tags:delete")
     def test_delete_tag(self):
         tag_name = self._add_tag_to_server()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_tag(self.server['id'], tag_name)
 
     @decorators.idempotent_id('a8e19b87-6580-4bc8-9933-e62561ff667d')
@@ -88,7 +88,7 @@
         service="nova",
         rule="os_compute_api:os-server-tags:update_all")
     def test_update_all_tags(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         new_tag_name = data_utils.rand_name('tag')
         self.client.update_all_tags(self.server['id'], [new_tag_name])['tags']
 
@@ -97,5 +97,5 @@
         service="nova",
         rule="os_compute_api:os-server-tags:delete_all")
     def test_delete_all_tags(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_all_tags(self.server['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_usage_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_usage_rbac.py
index 27cbbf3..8f836a6 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_usage_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_usage_rbac.py
@@ -13,14 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class ServerUsageRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
@@ -32,9 +30,9 @@
     @classmethod
     def skip_checks(cls):
         super(ServerUsageRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('OS-SRV-USG', 'compute'):
+            msg = "%s skipped as OS-SRV-USG not enabled." % cls.__name__
+            raise cls.skipException(msg)
 
     @classmethod
     def resource_setup(cls):
@@ -46,5 +44,5 @@
         rule="os_compute_api:os-server-usage")
     @decorators.idempotent_id('f0437ead-b9fb-462a-9f3d-ce53fac9d57a')
     def test_show_server_diagnostics(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_server(self.server['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_virtual_interfaces_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_virtual_interfaces_rbac.py
new file mode 100644
index 0000000..a0a000c
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_virtual_interfaces_rbac.py
@@ -0,0 +1,46 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base as base
+
+CONF = config.CONF
+
+
+class ServerVirtualInterfacesRbacTest(base.BaseV2ComputeRbacTest):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ServerVirtualInterfacesRbacTest, cls).setup_clients()
+        cls.client = cls.servers_client
+
+    @rbac_rule_validation.action(
+        service="nova",
+        rule="os_compute_api:os-virtual-interfaces")
+    @decorators.idempotent_id('fc719ae3-0f73-4689-8378-1b841f0f2818')
+    def test_list_virtual_interfaces(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+
+        if CONF.service_available.neutron:
+            msg = "Listing virtual interfaces is not supported by this cloud."
+            with self.assertRaisesRegex(exceptions.BadRequest, msg):
+                self.client.list_virtual_interfaces(server['id'])
+        else:
+            self.client.list_virtual_interfaces(server['id'])
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py
index 7556234..160affd 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_volume_attachments_rbac.py
@@ -31,7 +31,7 @@
     def setup_clients(cls):
         super(ServerVolumeAttachmentRbacTest, cls).setup_clients()
         cls.client = cls.servers_client
-        cls.volumes_client = cls.os.volumes_client
+        cls.volumes_client = cls.os_primary.volumes_client
 
     @classmethod
     def skip_checks(cls):
@@ -51,7 +51,7 @@
         rule="os_compute_api:os-volumes-attachments:index")
     @decorators.idempotent_id('529b668b-6edb-41d5-8886-d7dbd0614678')
     def test_list_volume_attachments(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_volume_attachments(self.server['id'])[
             'volumeAttachments']
 
@@ -60,7 +60,7 @@
         rule="os_compute_api:os-volumes-attachments:create")
     @decorators.idempotent_id('21c2c3fd-fbe8-41b1-8ef8-115ec47d54c1')
     def test_create_volume_attachment(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.attach_volume(self.server, self.volume)
 
     @rbac_rule_validation.action(
@@ -69,7 +69,7 @@
     @decorators.idempotent_id('997df9c2-6e54-47b6-ab74-e4fdb500f385')
     def test_show_volume_attachment(self):
         attachment = self.attach_volume(self.server, self.volume)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_volume_attachment(
             self.server['id'], attachment['id'])
 
@@ -81,7 +81,7 @@
     def test_update_volume_attachment(self):
         attachment = self.attach_volume(self.server, self.volume)
         alt_volume = self.create_volume()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.update_attached_volume(
             self.server['id'], attachment['id'], volumeId=alt_volume['id'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
@@ -103,7 +103,7 @@
     @decorators.idempotent_id('12b03e90-d087-46af-9c4d-507d021c4984')
     def test_delete_volume_attachment(self):
         self.attach_volume(self.server, self.volume)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.detach_volume(self.server['id'], self.volume['id'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 self.volume['id'], 'available')
diff --git a/patrole_tempest_plugin/tests/api/compute/test_services_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_services_rbac.py
index 01c19df..82de5a3 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_services_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_services_rbac.py
@@ -13,33 +13,31 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
 
-
-class ServicesAdminRbacTest(rbac_base.BaseV2ComputeAdminRbacTest):
+class ServicesRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(ServicesAdminRbacTest, cls).setup_clients()
+        super(ServicesRbacTest, cls).setup_clients()
         cls.client = cls.services_client
 
     @classmethod
     def skip_checks(cls):
-        super(ServicesAdminRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
+        super(ServicesRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('os-services', 'compute'):
             raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+                '%s skipped as os-services not enabled' % cls.__name__)
 
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:os-services")
     @decorators.idempotent_id('7472261b-9c6d-453a-bcb3-aecaa29ad281')
     def test_list_services(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_services()['services']
diff --git a/patrole_tempest_plugin/tests/api/compute/test_simple_tenant_usage_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_simple_tenant_usage_rbac.py
index 32bb407..5ecc32a 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_simple_tenant_usage_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_simple_tenant_usage_rbac.py
@@ -13,35 +13,34 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.compute import rbac_base
 
-CONF = config.CONF
-
 
 class SimpleTenantUsageRbacTest(rbac_base.BaseV2ComputeRbacTest):
 
     @classmethod
     def setup_clients(cls):
         super(SimpleTenantUsageRbacTest, cls).setup_clients()
-        cls.client = cls.os.tenant_usages_client
+        cls.client = cls.os_primary.tenant_usages_client
 
     @classmethod
     def skip_checks(cls):
         super(SimpleTenantUsageRbacTest, cls).skip_checks()
-        if not CONF.compute_feature_enabled.api_extensions:
-            raise cls.skipException(
-                '%s skipped as no compute extensions enabled' % cls.__name__)
+        if not test.is_extension_enabled('os-simple-tenant-usage', 'compute'):
+            msg = ("%s skipped as os-simple-tenant-usage not "
+                   "enabled." % cls.__name__)
+            raise cls.skipException(msg)
 
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:os-simple-tenant-usage:list")
     @decorators.idempotent_id('2aef094f-0452-4df6-a66a-0ec22a92b16e')
     def test_simple_tenant_usage_list(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_tenant_usages()
 
     @rbac_rule_validation.action(
@@ -53,5 +52,5 @@
         # the validation method in the API call throws an error.
         self.create_test_server(wait_until='ACTIVE')['id']
         tenant_id = self.auth_provider.credentials.tenant_id
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_tenant_usage(tenant_id=tenant_id)
diff --git a/patrole_tempest_plugin/tests/api/compute/test_suspend_server_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_suspend_server_rbac.py
index c7860db..8106a1a 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_suspend_server_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_suspend_server_rbac.py
@@ -59,7 +59,7 @@
         service="nova",
         rule="os_compute_api:os-suspend-server:suspend")
     def test_suspend_server(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.suspend_server(self.server['id'])
         waiters.wait_for_server_status(self.client, self.server['id'],
                                        'SUSPENDED')
@@ -72,7 +72,7 @@
         self.client.suspend_server(self.server['id'])
         waiters.wait_for_server_status(self.client, self.server['id'],
                                        'SUSPENDED')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.resume_server(self.server['id'])
         waiters.wait_for_server_status(self.client,
                                        self.server['id'],
diff --git a/patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py
index f6f3b0a..ee2b9a2 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_tenant_networks_rbac.py
@@ -35,7 +35,7 @@
     @classmethod
     def setup_clients(cls):
         super(TenantNetworksRbacTest, cls).setup_clients()
-        cls.client = cls.os.tenant_networks_client
+        cls.client = cls.os_primary.tenant_networks_client
 
     @classmethod
     def skip_checks(cls):
@@ -57,5 +57,5 @@
         service="nova",
         rule="os_compute_api:os-tenant-networks")
     def test_list_show_tenant_networks(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_tenant_networks()['networks']
diff --git a/patrole_tempest_plugin/tests/api/identity/v2/rbac_base.py b/patrole_tempest_plugin/tests/api/identity/v2/rbac_base.py
index ffee5c0..bc07675 100644
--- a/patrole_tempest_plugin/tests/api/identity/v2/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/identity/v2/rbac_base.py
@@ -23,25 +23,42 @@
 CONF = config.CONF
 
 
-class BaseIdentityV2AdminRbacTest(base.BaseIdentityV2AdminTest):
+class BaseIdentityV2AdminRbacTest(base.BaseIdentityV2Test):
+    """Base test class for the Identity v2 admin API.
+
+    Keystone's v2 API is split into two APIs: an admin and non-admin API. RBAC
+    testing is only provided for the admin API. Instead of policy enforcement,
+    these APIs execute ``self.assert_admin(request)``, which checks that the
+    request object has ``context_is_admin``. For more details, see the
+    implementation of ``assert_admin`` in ``keystone.common.wsgi``.
+    """
 
     credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
         super(BaseIdentityV2AdminRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
+        if not CONF.rbac.enable_rbac:
             raise cls.skipException(
-                "%s skipped as RBAC Flag not enabled" % cls.__name__)
+                "%s skipped as RBAC testing not enabled" % cls.__name__)
+        if not CONF.identity_feature_enabled.api_v2_admin:
+            raise cls.skipException('Identity v2 admin not available')
 
     @classmethod
     def setup_clients(cls):
         super(BaseIdentityV2AdminRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
-        cls.tenants_client = cls.os.tenants_client
-        cls.users_client = cls.os.users_client
+        cls.auth_provider = cls.os_primary.auth_provider
+
         cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
+
+        cls.client = cls.os_primary.identity_client
+        cls.endpoints_client = cls.os_primary.endpoints_client
+        cls.roles_client = cls.os_primary.roles_client
+        cls.services_client = cls.os_primary.identity_services_client
+        cls.tenants_client = cls.os_primary.tenants_client
+        cls.token_client = cls.os_primary.token_client
+        cls.users_client = cls.os_primary.users_client
 
     def _create_service(self):
         name = data_utils.rand_name('service')
@@ -73,7 +90,7 @@
     def _create_tenant(self):
         """Set up a test tenant."""
         name = data_utils.rand_name('test_tenant')
-        tenant = self.projects_client.create_tenant(
+        tenant = self.tenants_client.create_tenant(
             name=name,
             description=data_utils.rand_name('desc'))['tenant']
         # Delete the tenant at the end of the test
diff --git a/patrole_tempest_plugin/tests/api/identity/v2/test_endpoints_rbac.py b/patrole_tempest_plugin/tests/api/identity/v2/test_endpoints_rbac.py
index ccde9bd..f16d0aa 100644
--- a/patrole_tempest_plugin/tests/api/identity/v2/test_endpoints_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v2/test_endpoints_rbac.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
@@ -21,15 +20,13 @@
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v2 import rbac_base
 
-CONF = config.CONF
-
 
 class IdentityEndpointsV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
 
     @classmethod
     def setup_clients(cls):
         super(IdentityEndpointsV2AdminRbacTest, cls).setup_clients()
-        cls.endpoints_client = cls.os.endpoints_client
+        cls.endpoints_client = cls.os_primary.endpoints_client
 
     @classmethod
     def resource_setup(cls):
@@ -54,41 +51,41 @@
         return endpoint
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:create_endpoint")
+                                 admin_only=True)
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd124')
     def test_create_endpoint(self):
 
         """Create Endpoint Test
 
-        RBAC test for Identity Admin 2.0 create_endpoint
+        RBAC test for Identity v2 create_endpoint
         """
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_endpoint()
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:delete_endpoint")
+                                 admin_only=True)
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd125')
     def test_delete_endpoint(self):
 
         """Delete Endpoint Test
 
-        RBAC test for Identity Admin 2.0 delete_endpoint
+        RBAC test for Identity v2 delete_endpoint
         """
 
         endpoint = self._create_endpoint()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.endpoints_client.delete_endpoint(endpoint['endpoint']['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:list_endpoints")
+                                 admin_only=True)
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd126')
     def test_list_endpoints(self):
 
         """List Endpoints Test
 
-        RBAC test for Identity Admin 2.0 list_endpoint
+        RBAC test for Identity v2 list_endpoint
         """
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.endpoints_client.list_endpoints()
diff --git a/patrole_tempest_plugin/tests/api/identity/v2/test_projects_rbac.py b/patrole_tempest_plugin/tests/api/identity/v2/test_projects_rbac.py
index 9c4ab33..a557bb8 100644
--- a/patrole_tempest_plugin/tests/api/identity/v2/test_projects_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v2/test_projects_rbac.py
@@ -16,6 +16,7 @@
 from tempest import config
 from tempest.lib import decorators
 
+from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v2 import rbac_base
 
@@ -25,7 +26,7 @@
 class IdentityProjectV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:create_project")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-b348-080044d0d904')
     def test_create_project(self):
 
@@ -34,11 +35,11 @@
         RBAC test for Identity 2.0 create_tenant
         """
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_tenant()
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:update_project")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-b348-080044d0d905')
     def test_update_project(self):
 
@@ -48,12 +49,12 @@
         """
         tenant = self._create_tenant()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.tenants_client.update_tenant(tenant['id'],
                                           description="Changed description")
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:delete_project")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-b348-080044d0d906')
     def test_delete_project(self):
 
@@ -63,11 +64,11 @@
         """
         tenant = self._create_tenant()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.tenants_client.delete_tenant(tenant['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:get_project")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-b348-080044d0d907')
     def test_get_project(self):
 
@@ -78,25 +79,13 @@
 
         tenant = self._create_tenant()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.tenants_client.show_tenant(tenant['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:list_projects")
-    @decorators.idempotent_id('0f148510-63bf-11e6-b348-080044d0d908')
-    def test_get_all_projects(self):
-
-        """List All Projects Test
-
-        RBAC test for Identity 2.0 list_tenants
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.tenants_client.list_tenants()
-
-    @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:list_user_projects")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-b348-080044d0d909')
-    def test_list_users_for_tenant(self):
+    def test_list_project_users(self):
 
         """Get Users of a Project Test
 
@@ -104,5 +93,39 @@
         """
         tenant = self._create_tenant()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.tenants_client.list_tenant_users(tenant['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 admin_only=True)
+    @decorators.idempotent_id('0f148510-63bf-11e6-b348-080044d0d908')
+    def test_list_all_projects(self):
+
+        """List All Projects Test
+
+        RBAC test for Identity 2.0 list_tenants (admin endpoint)
+
+        There are two separate APIs for listing tenants in the Keystone
+        v2 API: one for admin and one for non-admin. The ``os_admin`` client
+        calls the admin endpoint and the ``os_primary`` client calls the
+        non-admin endpoint. To ensure that the admin endpoint only returns
+        admin-scoped tenants, raise ``RbacActionFailed`` exception otherwise.
+        """
+        tenants_client = self.os_admin.tenants_client if \
+            CONF.identity.admin_role == CONF.rbac.rbac_test_role else \
+            self.os_primary.tenants_client
+        admin_tenant_id = self.os_admin.auth_provider.credentials.project_id
+        non_admin_tenant_id = self.auth_provider.credentials.project_id
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        tenants = tenants_client.list_tenants()['tenants']
+
+        tenant_ids = [t['id'] for t in tenants]
+        if admin_tenant_id not in tenant_ids:
+            raise rbac_exceptions.RbacActionFailed(
+                "The admin tenant id was not returned by the call to "
+                "``list_tenants``.")
+        if non_admin_tenant_id in tenant_ids:
+            raise rbac_exceptions.RbacActionFailed(
+                "The non-admin tenant id was returned by the call to "
+                "``list_tenants``.")
diff --git a/patrole_tempest_plugin/tests/api/identity/v2/test_roles_rbac.py b/patrole_tempest_plugin/tests/api/identity/v2/test_roles_rbac.py
index 74a423e..a1ec5c6 100644
--- a/patrole_tempest_plugin/tests/api/identity/v2/test_roles_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v2/test_roles_rbac.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
@@ -21,15 +20,13 @@
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v2 import rbac_base
 
-CONF = config.CONF
 
-
-class IdentityRoleV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
+class IdentityRolesV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
 
     @classmethod
     def setup_clients(cls):
-        super(IdentityRoleV2AdminRbacTest, cls).setup_clients()
-        cls.roles_client = cls.os.roles_client
+        super(IdentityRolesV2AdminRbacTest, cls).setup_clients()
+        cls.roles_client = cls.os_primary.roles_client
 
     def _create_role(self):
         role = self.roles_client.create_role(
@@ -53,99 +50,99 @@
             tenant['id'], user['id'], role['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:create_role")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-8674-080044d0d904')
     def test_create_role(self):
 
         """Create Role Test
 
-        RBAC test for Identity Admin 2.0 role-create
+        RBAC test for Identity v2 role-create
         """
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_role()
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:delete_role")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-8674-080044d0d905')
     def test_delete_role(self):
 
         """Delete Role Test
 
-        RBAC test for Identity Admin 2.0 role-delete
+        RBAC test for Identity v2 delete_role
         """
         role = self._create_role()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.roles_client.delete_role(role['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:get_role")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-8674-080044d0d906')
     def test_show_role(self):
 
         """Get Role Test
 
-        RBAC test for Identity Admin 2.0
+        RBAC test for Identity v2 show_role
         """
         role = self._create_role()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.roles_client.show_role(role['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:list_roles")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-8674-080044d0d907')
     def test_list_roles(self):
 
         """List Roles Test
 
-        RBAC test for Identity Admin 2.0 role-list
+        RBAC test for Identity v2 list_roles
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.roles_client.list_roles()
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:add_role_to_user")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-8674-080044d0d908')
     def test_create_role_on_project(self):
 
         """Assign User Role Test
 
-        RBAC test for Identity Admin 2.0 create_user_role_on_project
+        RBAC test for Identity v2 create_user_role_on_project
         """
         tenant, user, role = self._create_tenant_user_and_role()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_role_on_project(tenant, user, role)
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:remove_role_from_user")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-8674-080044d0d909')
     def test_delete_role_from_user_on_project(self):
 
         """Remove User Roles Test
 
-        RBAC test for Identity Admin 2.0 delete_role_from_user_on_project
+        RBAC test for Identity v2 delete_role_from_user_on_project
         """
         tenant, user, role = self._create_tenant_user_and_role()
         self._create_role_on_project(tenant, user, role)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.roles_client.delete_role_from_user_on_project(
             tenant['id'], user['id'], role['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:get_user_roles")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-8674-080044d0d90a')
     def test_list_user_roles_on_project(self):
 
         """List User Roles Test
 
-        RBAC test for Identity Admin 2.0 list_user_roles_on_project
+        RBAC test for Identity v2 list_user_roles_on_project
         """
         tenant = self._create_tenant()
         user = self._create_user(tenantid=tenant['id'])
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.roles_client.list_user_roles_on_project(
             tenant['id'], user['id'])
diff --git a/patrole_tempest_plugin/tests/api/identity/v2/test_services_rbac.py b/patrole_tempest_plugin/tests/api/identity/v2/test_services_rbac.py
index 6ba60fa..ad47fd2 100644
--- a/patrole_tempest_plugin/tests/api/identity/v2/test_services_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v2/test_services_rbac.py
@@ -13,66 +13,63 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v2 import rbac_base
 
-CONF = config.CONF
-
 
 class IdentityServicesV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
 
     @classmethod
     def setup_clients(cls):
         super(IdentityServicesV2AdminRbacTest, cls).setup_clients()
-        cls.services_client = cls.os.identity_services_client
+        cls.services_client = cls.os_primary.identity_services_client
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:create_service")
+                                 admin_only=True)
     @decorators.idempotent_id('370050f6-d271-4fb4-abc5-4de1d6dfbad2')
     def test_create_service(self):
         """Create Service Test
 
-        RBAC test for Identity Admin 2.0 create_service
+        RBAC test for Identity v2 create_service
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_service()
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:delete_service")
+                                 admin_only=True)
     @decorators.idempotent_id('f6c64fc3-6a1f-423e-af91-e411add3a384')
     def test_delete_service(self):
         """Delete Service Test
 
-        RBAC test for Identity Admin 2.0 delete_service
+        RBAC test for Identity v2 delete_service
         """
         service_id = self._create_service()['OS-KSADM:service']['id']
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.services_client.delete_service(service_id)
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:get_service")
+                                 admin_only=True)
     @decorators.idempotent_id('504d62bb-97d7-445e-9d6d-b1945a7c9e08')
     def test_show_service(self):
         """Show Service Test
 
-        RBAC test for Identity Admin 2.0 show_service
+        RBAC test for Identity v2 show_service
         """
         service_id = self._create_service()['OS-KSADM:service']['id']
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.services_client.show_service(service_id)
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:list_services")
+                                 admin_only=True)
     @decorators.idempotent_id('d7dc461d-51ad-48e0-9cd2-33add1b88de9')
     def test_list_services(self):
         """List all the services
 
-        RBAC test for Identity Admin 2.0 list_service
+        RBAC test for Identity v2 list_service
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.services_client.list_services()
diff --git a/patrole_tempest_plugin/tests/api/identity/v2/test_users_rbac.py b/patrole_tempest_plugin/tests/api/identity/v2/test_users_rbac.py
index a94a811..f90680d 100644
--- a/patrole_tempest_plugin/tests/api/identity/v2/test_users_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v2/test_users_rbac.py
@@ -20,64 +20,64 @@
 from patrole_tempest_plugin.tests.api.identity.v2 import rbac_base
 
 
-class IdentityUserV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
+class IdentityUsersV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:create_user")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-1342-080044d0d904')
     def test_create_user(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_user()
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:update_user")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-1342-080044d0d905')
     def test_update_user(self):
         user = self._create_user()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.users_client.update_user(user['id'], email="changedUser@xyz.com")
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:set_user_enabled")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-1342-080044d0d9a1')
     def test_update_user_enabled(self):
         user = self._create_user()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.users_client.update_user_enabled(user['id'], enabled=True)
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:delete_user")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-1342-080044d0d906')
     def test_delete_user(self):
         user = self._create_user()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.users_client.delete_user(user['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:get_users")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-1342-080044d0d907')
     def test_list_users(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.users_client.list_users()
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:get_user")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-1342-080044d0d908')
     def test_show_user(self):
         user = self._create_user()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.users_client.show_user(user['id'])
 
     @rbac_rule_validation.action(service="keystone",
-                                 rule="identity:change_password")
+                                 admin_only=True)
     @decorators.idempotent_id('0f148510-63bf-11e6-1342-080044d0d909')
     def test_update_user_password(self):
         user = self._create_user()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.users_client.update_user_password(
             user['id'], password=data_utils.rand_password())
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py b/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
index 7a67459..927ec39 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
@@ -23,58 +23,238 @@
 CONF = config.CONF
 
 
-class BaseIdentityV3RbacAdminTest(base.BaseIdentityV3AdminTest):
+class BaseIdentityV3RbacTest(base.BaseIdentityV3Test):
 
     credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
-        super(BaseIdentityV3RbacAdminTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
+        super(BaseIdentityV3RbacTest, cls).skip_checks()
+        if not CONF.rbac.enable_rbac:
             raise cls.skipException(
-                "%s skipped as RBAC Flag not enabled" % cls.__name__)
+                "%s skipped as RBAC testing not enabled" % cls.__name__)
 
     @classmethod
     def setup_clients(cls):
-        super(BaseIdentityV3RbacAdminTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
-        cls.creds_client = cls.os.credentials_client
-        cls.services_client = cls.os.identity_services_v3_client
-        cls.endpoints_client = cls.os.endpoints_v3_client
-        cls.groups_client = cls.os.groups_client
-        cls.policies_client = cls.os.policies_client
-        cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
+        super(BaseIdentityV3RbacTest, cls).setup_clients()
+        cls.auth_provider = cls.os_primary.auth_provider
 
-    def _create_service(self):
-        """Creates a service for test."""
+        cls.rbac_utils = rbac_utils()
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
+
+        cls.creds_client = cls.os_primary.credentials_client
+        cls.consumers_client = cls.os_primary.oauth_consumers_client
+        cls.domains_client = cls.os_primary.domains_client
+        cls.endpoints_client = cls.os_primary.endpoints_v3_client
+        cls.groups_client = cls.os_primary.groups_client
+        cls.projects_client = cls.os_primary.projects_client
+        cls.policies_client = cls.os_primary.policies_client
+        cls.regions_client = cls.os_primary.regions_client
+        cls.role_assignments_client = cls.os_primary.role_assignments_client
+        cls.roles_client = cls.os_primary.roles_v3_client
+        cls.services_client = cls.os_primary.identity_services_v3_client
+        cls.trusts_client = cls.os_primary.trusts_client
+        cls.users_client = cls.os_primary.users_v3_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(BaseIdentityV3RbacTest, cls).resource_setup()
+        cls.credentials = []
+        cls.domains = []
+        cls.endpoints = []
+        cls.groups = []
+        cls.policies = []
+        cls.projects = []
+        cls.regions = []
+        cls.roles = []
+        cls.services = []
+        cls.trusts = []
+        cls.users = []
+
+    @classmethod
+    def resource_cleanup(cls):
+        for credential in cls.credentials:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.creds_client.delete_credential, credential['id'])
+
+        # Delete each domain at the end of the test, but each domain must be
+        # disabled first.
+        for domain in cls.domains:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.domains_client.update_domain, domain['id'], enabled=False)
+            test_utils.call_and_ignore_notfound_exc(
+                cls.domains_client.delete_domain, domain['id'])
+
+        for endpoint in cls.endpoints:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.endpoints_client.delete_endpoint, endpoint['id'])
+
+        for group in cls.groups:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.groups_client.delete_group, group['id'])
+
+        for policy in cls.policies:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.policies_client.delete_policy, policy['id'])
+
+        for project in cls.projects:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.projects_client.delete_project, project['id'])
+
+        for region in cls.regions:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.regions_client.delete_region, region['id'])
+
+        for role in cls.roles:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.roles_client.delete_role, role['id'])
+
+        for service in cls.services:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.services_client.delete_service, service['id'])
+
+        for trust in cls.trusts:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.trusts_client.delete_trust, trust['id'])
+
+        for user in cls.users:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.users_client.delete_user, user['id'])
+
+        super(BaseIdentityV3RbacTest, cls).resource_cleanup()
+
+    @classmethod
+    def setup_test_credential(cls, user=None):
+        """Creates a credential for test."""
+        keys = [data_utils.rand_uuid_hex(),
+                data_utils.rand_uuid_hex()]
+        blob = '{"access": "%s", "secret": "%s"}' % (keys[0], keys[1])
+
+        credential = cls.creds_client.create_credential(
+            user_id=user['id'],
+            project_id=user['project_id'],
+            blob=blob,
+            type='ec2')['credential']
+        cls.credentials.append(credential)
+
+        return credential
+
+    @classmethod
+    def setup_test_domain(cls):
+        """Set up a test domain."""
+        domain = cls.domains_client.create_domain(
+            name=data_utils.rand_name('test_domain'),
+            description=data_utils.rand_name('desc'))['domain']
+        cls.domains.append(domain)
+
+        return domain
+
+    @classmethod
+    def setup_test_endpoint(cls, service=None):
+        """Creates a service and an endpoint for test."""
+        interface = 'public'
+        url = data_utils.rand_url()
+        # Endpoint creation requires a service
+        if service is None:
+            service = cls.setup_test_service()
+
+        endpoint = cls.endpoints_client.create_endpoint(
+            service_id=service['id'],
+            interface=interface,
+            url=url)['endpoint']
+        cls.endpoints.append(endpoint)
+
+        return endpoint
+
+    @classmethod
+    def setup_test_group(cls):
+        """Creates a group for test."""
+        name = data_utils.rand_name('test_group')
+        group = cls.groups_client.create_group(name=name)['group']
+        cls.groups.append(group)
+
+        return group
+
+    @classmethod
+    def setup_test_policy(cls):
+        """Creates a policy for test."""
+        blob = data_utils.rand_name('test_blob')
+        policy_type = data_utils.rand_name('policy_type')
+
+        policy = cls.policies_client.create_policy(
+            blob=blob,
+            policy=policy_type,
+            type="application/json")['policy']
+        cls.policies.append(policy)
+
+        return policy
+
+    @classmethod
+    def setup_test_project(cls):
+        """Set up a test project."""
+        project = cls.projects_client.create_project(
+            name=data_utils.rand_name('test_project'),
+            description=data_utils.rand_name('desc'))['project']
+        cls.projects.append(project)
+
+        return project
+
+    @classmethod
+    def setup_test_region(cls):
+        """Creates a region for test."""
+        description = data_utils.rand_name('test_region_desc')
+
+        region = cls.regions_client.create_region(
+            description=description)['region']
+        cls.regions.append(region)
+
+        return region
+
+    @classmethod
+    def setup_test_role(cls):
+        """Set up a test role."""
+        name = data_utils.rand_name('test_role')
+        role = cls.roles_client.create_role(name=name)['role']
+        cls.roles.append(role)
+
+        return role
+
+    @classmethod
+    def setup_test_service(cls):
+        """Setup a test service."""
         name = data_utils.rand_name('service')
         serv_type = data_utils.rand_name('type')
         desc = data_utils.rand_name('description')
-        service = self.services_client \
-                      .create_service(name=name,
-                                      type=serv_type,
-                                      description=desc)['service']
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.services_client.delete_service, service['id'])
+
+        service = cls.services_client.create_service(
+            name=name,
+            type=serv_type,
+            description=desc)['service']
+        cls.services.append(service)
+
         return service
 
-    def _setup_test_project(self):
-        """Set up a test project."""
-        project = self.projects_client.create_project(
-            name=data_utils.rand_name('test_project'),
-            description=data_utils.rand_name('desc'))['project']
-        # Delete the project at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.projects_client.delete_project, project['id'])
-        return project
+    @classmethod
+    def setup_test_trust(cls, trustee_user_id, trustor_user_id, **kwargs):
+        """Setup a test trust."""
+        trust = cls.trusts_client.create_trust(
+            trustee_user_id=trustee_user_id, trustor_user_id=trustor_user_id,
+            impersonation=False, **kwargs)['trust']
+        cls.trusts.append(trust)
 
-    def _create_test_user(self, **kwargs):
-        if kwargs['password'] is None:
-            user_password = data_utils.rand_password()
-            kwargs['password'] = user_password
-        user = self.users_client.create_user(**kwargs)['user']
-        # Delete the user at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.users_client.delete_user, user['id'])
+        return trust
+
+    @classmethod
+    def setup_test_user(cls, password=None, **kwargs):
+        """Set up a test user."""
+        username = data_utils.rand_name('test_user')
+        email = username + '@testmail.tm'
+
+        user = cls.users_client.create_user(
+            name=username,
+            email=email,
+            password=password,
+            **kwargs)['user']
+        cls.users.append(user)
+
         return user
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py
index 7812ea8..42f2c01 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_credentials_rbac.py
@@ -14,101 +14,66 @@
 #    under the License.
 
 from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
 
 
-class IdentityCredentialsV3AdminRbacTest(
-        rbac_base.BaseIdentityV3RbacAdminTest):
+class IdentityCredentialsV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
 
-    def _create_credential(self):
-        """Creates a user, project, and credential for test."""
-        user = self.setup_test_user()
-        user_id = user['id']
-        project_id = user['project_id']
-        keys = [data_utils.rand_name('Access'),
-                data_utils.rand_name('Secret')]
-        blob = "{\"access\": \"%s\", \"secret\": \"%s\"}" % (
-            keys[0], keys[1])
-        credential = self.creds_client \
-                         .create_credential(user_id=user_id,
-                                            project_id=project_id,
-                                            blob=blob,
-                                            type='ec2')['credential']
-
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.creds_client.delete_credential, credential['id'])
-
-        return (project_id, credential)
+    def _create_user_project_and_credential(self):
+        project = self.setup_test_project()
+        user = self.setup_test_user(project_id=project['id'])
+        credential = self.setup_test_credential(user=user)
+        return credential
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_credential")
     @decorators.idempotent_id('c1ab6d34-c59f-4ae1-bae9-bb3c1089b48e')
     def test_create_credential(self):
-        """Create a Credential.
-
-        RBAC test for Keystone: identity:create_credential
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._create_credential()
+        project = self.setup_test_project()
+        user = self.setup_test_user(project_id=project['id'])
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_credential(user=user)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:update_credential")
     @decorators.idempotent_id('cfb05ce3-bffb-496e-a3c2-9515d730da63')
     def test_update_credential(self):
-        """Update a Credential.
+        credential = self._create_user_project_and_credential()
+        new_keys = [data_utils.rand_uuid_hex(),
+                    data_utils.rand_uuid_hex()]
 
-        RBAC test for Keystone: identity:update_credential
-        """
-        project_id, credential = self._create_credential()
-        # Update blob keys
-        new_keys = [data_utils.rand_name('NewAccess'),
-                    data_utils.rand_name('NewSecret')]
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.creds_client \
-            .update_credential(credential['id'],
-                               credential=credential,
-                               access_key=new_keys[0],
-                               secret_key=new_keys[1],
-                               project_id=project_id)['credential']
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.creds_client.update_credential(
+            credential['id'],
+            credential=credential,
+            access_key=new_keys[0],
+            secret_key=new_keys[1],
+            project_id=credential['project_id'])['credential']
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:delete_credential")
     @decorators.idempotent_id('87ab42af-8d41-401b-90df-21e72919fcde')
     def test_delete_credential(self):
-        """Delete a Credential.
+        credential = self._create_user_project_and_credential()
 
-        RBAC test for Keystone: identity:delete_credential
-        """
-        _, credential = self._create_credential()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.creds_client.delete_credential(credential['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:get_credential")
     @decorators.idempotent_id('1b6eeae6-f1e8-4cdf-8903-1c002b1fc271')
     def test_show_credential(self):
-        """Show/Get a Credential.
+        credential = self._create_user_project_and_credential()
 
-        RBAC test for Keystone: identity:get_credential
-        """
-        _, credential = self._create_credential()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.creds_client.show_credential(credential['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_credentials")
     @decorators.idempotent_id('3de303e2-12a7-4811-805a-f18906472038')
     def test_list_credentials(self):
-        """List all Credentials.
-
-        RBAC test for Keystone: identity:list_credentials
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.creds_client.list_credentials()
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_domains_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_domains_rbac.py
new file mode 100644
index 0000000..ba5d5e0
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_domains_rbac.py
@@ -0,0 +1,68 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+class IdentityDomainsV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_domain")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd110')
+    def test_create_domain(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_domain()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:update_domain")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd111')
+    def test_update_domain(self):
+        domain = self.setup_test_domain()
+        new_domain_name = data_utils.rand_name('test_update_domain')
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.domains_client.update_domain(domain['id'],
+                                          domain=domain,
+                                          name=new_domain_name)
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:delete_domain")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd112')
+    def test_delete_domain(self):
+        domain = self.setup_test_domain()
+        # A domain must be deactivated to be deleted
+        self.domains_client.update_domain(domain['id'],
+                                          domain=domain,
+                                          enabled=False)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.domains_client.delete_domain(domain['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:get_domain")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd113')
+    def test_show_domain(self):
+        domain = self.setup_test_domain()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.domains_client.show_domain(domain['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_domains")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd114')
+    def test_list_domains(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.domains_client.list_domains()
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_endpoint_filter_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_endpoint_filter_rbac.py
new file mode 100644
index 0000000..77ad647
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_endpoint_filter_rbac.py
@@ -0,0 +1,91 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+class IdentityEndpointsFilterV3RbacTest(
+        rbac_base.BaseIdentityV3RbacTest):
+
+    @classmethod
+    def setup_clients(cls):
+        super(IdentityEndpointsFilterV3RbacTest, cls).setup_clients()
+        cls.ep_api_client = cls.os_primary.endpoint_filter_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(IdentityEndpointsFilterV3RbacTest, cls).resource_setup()
+        cls.project = cls.setup_test_project()
+        cls.service = cls.setup_test_service()
+        cls.endpoint = cls.setup_test_endpoint(service=cls.service)
+
+    def _add_endpoint_to_project(self):
+        # Adding and cleaning up endpoints to projects
+        self.ep_api_client.add_endpoint_to_project(
+            self.project['id'], self.endpoint['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.ep_api_client.delete_endpoint_from_project,
+                        self.project['id'], self.endpoint['id'])
+
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:add_endpoint_to_project")
+    @decorators.idempotent_id('9199ec13-816d-4efe-b8b1-e1cd026b9747')
+    def test_add_endpoint_to_project(self):
+        # Adding endpoints to projects
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._add_endpoint_to_project()
+
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:list_projects_for_endpoint")
+    @decorators.idempotent_id('f53dca42-ec8a-48e9-924b-0bbe6c99727f')
+    def test_list_projects_for_endpoint(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.ep_api_client.list_projects_for_endpoint(
+            self.endpoint['id'])
+
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:check_endpoint_in_project")
+    @decorators.idempotent_id('0c1425eb-833c-4aa1-a21d-52ffa41fdc6a')
+    def test_check_endpoint_in_project(self):
+        self._add_endpoint_to_project()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.ep_api_client.check_endpoint_in_project(
+            self.project['id'], self.endpoint['id'])
+
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:list_endpoints_for_project")
+    @decorators.idempotent_id('5d86c659-c6ad-41e0-854e-3823e95c7cc2')
+    def test_list_endpoints_in_project(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.ep_api_client.list_endpoints_in_project(
+            self.project['id'])
+
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:remove_endpoint_from_project")
+    @decorators.idempotent_id('b4e21c10-4f47-427b-9b8a-f5b5601adfda')
+    def test_remove_endpoint_from_project(self):
+        self._add_endpoint_to_project()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.ep_api_client.delete_endpoint_from_project(
+            self.project['id'], self.endpoint['id'])
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py
index e416b15..eabebb6 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_endpoints_rbac.py
@@ -13,93 +13,56 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
 
-CONF = config.CONF
 
-
-class IdentityEndpointsV3AdminRbacTest(
-        rbac_base.BaseIdentityV3RbacAdminTest):
-
-    def _create_endpoint(self):
-        """Creates a service and an endpoint for test."""
-        interface = 'public'
-        url = data_utils.rand_url()
-        service = self._create_service()
-        endpoint = self.endpoints_client \
-                       .create_endpoint(service_id=service['id'],
-                                        interface=interface,
-                                        url=url)['endpoint']
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.endpoints_client.delete_endpoint, endpoint['id'])
-        return (service, endpoint)
+class IdentityEndpointsV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_endpoint")
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd127')
     def test_create_endpoint(self):
-        """Create an endpoint.
-
-        RBAC test for Keystone: identity:create_endpoint
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._create_endpoint()
+        service = self.setup_test_service()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_endpoint(service=service)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:update_endpoint")
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd128')
     def test_update_endpoint(self):
-        """Update an endpoint.
-
-        RBAC test for Keystone: identity:update_endpoint
-        """
-        service, endpoint = self._create_endpoint()
+        endpoint = self.setup_test_endpoint()
         new_url = data_utils.rand_url()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.endpoints_client.update_endpoint(endpoint["id"],
-                                              service_id=service['id'],
-                                              url=new_url)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.endpoints_client.update_endpoint(
+            endpoint["id"],
+            url=new_url)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:delete_endpoint")
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd129')
     def test_delete_endpoint(self):
-        """Delete an endpoint.
+        endpoint = self.setup_test_endpoint()
 
-        RBAC test for Keystone: identity:delete_endpoint
-        """
-        _, endpoint = self._create_endpoint()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.endpoints_client.delete_endpoint(endpoint['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:get_endpoint")
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd130')
     def test_show_endpoint(self):
-        """Show/Get an endpoint.
+        endpoint = self.setup_test_endpoint()
 
-        RBAC test for Keystone: identity:get_endpoint
-        """
-        _, endpoint = self._create_endpoint()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.endpoints_client.show_endpoint(endpoint['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_endpoints")
     @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd131')
     def test_list_endpoints(self):
-        """Create a Domain.
-
-        RBAC test for Keystone: identity:create_domain
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.endpoints_client.list_endpoints()
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py
index a61149e..3cc71a6 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_groups_rbac.py
@@ -13,115 +13,98 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
 
-CONF = config.CONF
 
+class IdentityGroupsV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
 
-class IdentityGroupsV3AdminRbacTest(rbac_base.BaseIdentityV3RbacAdminTest):
-
-    def _create_group(self):
-        """Creates a group for test."""
-        name = data_utils.rand_name('group')
-        group = self.groups_client.create_group(name=name)['group']
-
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.groups_client.delete_group, group['id'])
-        return group
-
-    def _add_user_to_group(self, group_id):
+    def _create_user_and_add_to_new_group(self):
         """Creates a user and adds to a group for test."""
-        user_name = data_utils.rand_name('User')
-        user = self._create_test_user(name=user_name, password=None)
-
-        self.groups_client.add_group_user(group_id, user['id'])
-
-        return user['id']
+        group = self.setup_test_group()
+        user = self.setup_test_user()
+        self.groups_client.add_group_user(group['id'], user['id'])
+        return (group['id'], user['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_group")
     @decorators.idempotent_id('88377f51-9074-4d64-a22f-f8931d048c9a')
     def test_create_group(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._create_group()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_group()
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:update_group")
     @decorators.idempotent_id('790fb7be-a657-4a64-9b83-c43425cf180b')
     def test_update_group(self):
-        group = self._create_group()
-        # Update Group
-        new_name = data_utils.rand_name('UpdateGroup')
+        group = self.setup_test_group()
+        new_group_name = data_utils.rand_name('group')
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.groups_client.update_group(group['id'],
-                                        name=new_name)
+                                        name=new_group_name)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:delete_group")
     @decorators.idempotent_id('646b52da-2a5f-486a-afb0-51fdc86a6c12')
     def test_delete_group(self):
-        group = self._create_group()
+        group = self.setup_test_group()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.groups_client.delete_group(group['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:get_group")
     @decorators.idempotent_id('d530f0ad-42b9-429b-ad05-e53ac95a040e')
     def test_show_group(self):
-        group = self._create_group()
+        group = self.setup_test_group()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.groups_client.show_group(group['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_groups")
     @decorators.idempotent_id('c4d0f76b-735f-4fd0-868b-0006bc420ff4')
     def test_list_groups(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.groups_client.list_groups()
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:add_user_to_group")
     @decorators.idempotent_id('fdd49b74-3ed3-4736-9f0e-9027a32017ac')
     def test_add_user_group(self):
-        group = self._create_group()
+        group = self.setup_test_group()
+        user = self.setup_test_user()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._add_user_to_group(group['id'])
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.groups_client.add_group_user(group['id'], user['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:remove_user_from_group")
     @decorators.idempotent_id('8a60d11c-7d2b-47e5-a0f3-9ea900ca66fe')
     def test_remove_user_group(self):
-        group = self._create_group()
-        user_id = self._add_user_to_group(group['id'])
+        group_id, user_id = self._create_user_and_add_to_new_group()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.groups_client.delete_group_user(group['id'], user_id)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.groups_client.delete_group_user(group_id, user_id)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_users_in_group")
     @decorators.idempotent_id('b3e394a7-079e-4a0d-a4ff-9b266293d1ee')
     def test_list_user_group(self):
-        group = self._create_group()
+        group = self.setup_test_group()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.groups_client.list_group_users(group['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:check_user_in_group")
     @decorators.idempotent_id('d3603241-fd87-4a2d-94f9-f32469d1aaba')
     def test_check_user_group(self):
-        group = self._create_group()
-        user_id = self._add_user_to_group(group['id'])
+        group_id, user_id = self._create_user_and_add_to_new_group()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.groups_client.check_group_user_existence(group['id'], user_id)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.groups_client.check_group_user_existence(group_id, user_id)
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_consumers_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_consumers_rbac.py
new file mode 100644
index 0000000..f331cff
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_oauth_consumers_rbac.py
@@ -0,0 +1,76 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+class IdentityConsumersV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
+
+    def _create_consumer(self):
+        description = data_utils.rand_name('test_create_consumer')
+        consumer = self.consumers_client.create_consumer(
+            description)['consumer']
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.consumers_client.delete_consumer,
+                        consumer['id'])
+        return consumer
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_consumer")
+    @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d970')
+    def test_create_consumer(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._create_consumer()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:delete_consumer")
+    @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d971')
+    def test_delete_consumer(self):
+        consumer = self._create_consumer()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.consumers_client.delete_consumer(consumer['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:update_consumer")
+    @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d972')
+    def test_update_consumer(self):
+        consumer = self._create_consumer()
+        new_description = data_utils.rand_name('test_update_consumer')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.consumers_client.update_consumer(consumer['id'],
+                                              new_description)
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:get_consumer")
+    @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d973')
+    def test_show_consumer(self):
+        consumer = self._create_consumer()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.consumers_client.show_consumer(consumer['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_consumers")
+    @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d975')
+    def test_list_consumers(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.consumers_client.list_consumers()
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py
index b115fb0..8f11e30 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_policies_rbac.py
@@ -13,71 +13,54 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
 
-CONF = config.CONF
 
-
-class IdentityPoliciesV3AdminRbacTest(rbac_base.BaseIdentityV3RbacAdminTest):
-
-    def _create_policy(self):
-        """Creates a policy for test."""
-        blob = data_utils.rand_name('BlobName')
-        policy_type = data_utils.rand_name('PolicyType')
-        policy = self.policies_client.create_policy(
-            blob=blob,
-            policy=policy_type,
-            type="application/json")['policy']
-
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.policies_client.delete_policy, policy['id'])
-        return policy
+class IdentityPoliciesV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_policy")
     @decorators.idempotent_id('de2f7ecb-fbf0-41f3-abf4-b97b5e082fd5')
     def test_create_policy(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._create_policy()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_policy()
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:update_policy")
     @decorators.idempotent_id('9cfed3c6-0b27-4d15-be67-e06e0cfb01b9')
     def test_update_policy(self):
-        policy = self._create_policy()
-        update_type = data_utils.rand_name('UpdatedPolicyType')
+        policy = self.setup_test_policy()
+        updated_policy_type = data_utils.rand_name('policy_type')
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.policies_client.update_policy(policy['id'],
-                                           type=update_type)
+                                           type=updated_policy_type)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:delete_policy")
     @decorators.idempotent_id('dcd93f75-1e1b-4fbe-bee0-9c4c7b201735')
     def test_delete_policy(self):
-        policy = self._create_policy()
+        policy = self.setup_test_policy()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.policies_client.delete_policy(policy['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:get_policy")
     @decorators.idempotent_id('d7e415c2-945a-4504-9571-0e2d0dd8594b')
     def test_show_policy(self):
-        policy = self._create_policy()
+        policy = self.setup_test_policy()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.policies_client.show_policy(policy['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_policies")
     @decorators.idempotent_id('35a56161-4054-4237-8a78-7ce805dce202')
     def test_list_policies(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.policies_client.list_policies()['policies']
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py
index d0b843d..325b987 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_projects_rbac.py
@@ -13,81 +13,54 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
 
-CONF = config.CONF
 
-
-class IdentityProjectV3AdminRbacTest(
-        rbac_base.BaseIdentityV3RbacAdminTest):
+class IdentityProjectV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_project")
     @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d904')
     def test_create_project(self):
-        """Create a Project.
-
-        RBAC test for Keystone: identity:create_project
-        """
-        name = data_utils.rand_name('project')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        project = self.non_admin_projects_client \
-                      .create_project(name)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_project()
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:update_project")
     @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d905')
     def test_update_project(self):
-        """Update a Project.
+        project = self.setup_test_project()
+        new_desc = data_utils.rand_name('description')
 
-        RBAC test for Keystone: identity:update_project
-        """
-        project = self._setup_test_project()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_projects_client \
-            .update_project(project['id'],
-                            description="Changed description")
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.projects_client.update_project(project['id'],
+                                            description=new_desc)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:delete_project")
     @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d906')
     def test_delete_project(self):
-        """Delete a Project.
+        project = self.setup_test_project()
 
-        RBAC test for Keystone: identity:delete_project
-        """
-        project = self._setup_test_project()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_projects_client.delete_project(project['id'])
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.projects_client.delete_project(project['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:get_project")
     @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d907')
     def test_show_project(self):
-        """Show a project.
+        project = self.setup_test_project()
 
-        RBAC test for Keystone: identity:get_project
-        """
-        project = self._setup_test_project()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_projects_client.show_project(project['id'])
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.projects_client.show_project(project['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_projects")
     @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d908')
     def test_list_projects(self):
-        """List all projects.
-
-        RBAC test for Keystone: identity:list_projects
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_projects_client.list_projects()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.projects_client.list_projects()
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_regions_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_regions_rbac.py
new file mode 100644
index 0000000..b35facd
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_regions_rbac.py
@@ -0,0 +1,66 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+class IdentityRegionsV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_region")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd119')
+    def test_create_region(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_region()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:update_region")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd120')
+    def test_update_region(self):
+        region = self.setup_test_region()
+        new_description = data_utils.rand_name('test_update_region')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.regions_client.update_region(region['id'],
+                                          description=new_description)
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:delete_region")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd121')
+    def test_delete_region(self):
+        region = self.setup_test_region()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.regions_client.delete_region(region['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:get_region")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd122')
+    def test_show_region(self):
+        region = self.setup_test_region()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.regions_client.show_region(region['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_regions")
+    @decorators.idempotent_id('6bdaecd4-0843-4ed6-ab64-3a57ab0cd123')
+    def test_list_regions(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.regions_client.list_regions()
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py
new file mode 100644
index 0000000..2dd0ff5
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py
@@ -0,0 +1,46 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+class IdentityRoleAssignmentsV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
+
+    @classmethod
+    def setup_clients(cls):
+        super(IdentityRoleAssignmentsV3RbacTest, cls).setup_clients()
+        cls.client = cls.role_assignments_client
+
+    @decorators.idempotent_id('afe57adb-1b9c-43d9-84a9-f0cf4c94e416')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_role_assignments")
+    def test_list_role_assignments(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_role_assignments()['role_assignments']
+
+    @decorators.idempotent_id('36c7a990-857e-415c-8717-38d7200a9894')
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:list_role_assignments_for_tree")
+    def test_list_role_assignments_for_tree(self):
+        project = self.setup_test_project()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_role_assignments(
+            include_subtree=True, **{'scope.project.id': project['id']})[
+            'role_assignments']
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py
new file mode 100644
index 0000000..2676bf9
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py
@@ -0,0 +1,395 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+class IdentityRolesV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
+
+    @classmethod
+    def resource_setup(cls):
+        super(IdentityRolesV3RbacTest, cls).resource_setup()
+        cls.domain = cls.setup_test_domain()
+        cls.project = cls.setup_test_project()
+        cls.group = cls.setup_test_group()
+        cls.role = cls.setup_test_role()
+        cls.implies_role = cls.setup_test_role()
+        cls.user = cls.setup_test_user()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_role")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d904')
+    def test_create_role(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_role()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:update_role")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d905')
+    def test_update_role(self):
+        new_role_name = data_utils.rand_name('test_update_role')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.update_role(self.role['id'],
+                                      name=new_role_name)
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:delete_role")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d906')
+    def test_delete_role(self):
+        role = self.setup_test_role()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.delete_role(role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:get_role")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d907')
+    def test_show_role(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.show_role(self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_roles")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d908')
+    def test_list_roles(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.list_roles()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d909')
+    def test_create_user_role_on_project(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.create_user_role_on_project(
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_user_on_project,
+                        self.project['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90c')
+    def test_create_group_role_on_project(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.create_group_role_on_project(
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_group_on_project,
+                        self.project['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90f')
+    def test_create_user_role_on_domain(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.create_user_role_on_domain(
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_user_on_domain,
+                        self.domain['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d912')
+    def test_create_group_role_on_domain(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.create_group_role_on_domain(
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_group_on_domain,
+                        self.domain['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:check_grant")
+    @decorators.idempotent_id('22921b1e-1a33-4026-bff9-f236d6dd149c')
+    def test_check_user_role_existence_on_project(self):
+        self.roles_client.create_user_role_on_project(
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_user_on_project,
+                        self.project['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.check_user_role_existence_on_project(
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
+
+    @decorators.idempotent_id('92f8e67d-85bf-407d-9814-edd5664abc47')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:check_grant")
+    def test_check_user_role_existence_on_domain(self):
+        self.roles_client.create_user_role_on_domain(
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_user_on_domain,
+                        self.domain['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.check_user_role_existence_on_domain(
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
+
+    @decorators.idempotent_id('8738d3d2-8c84-4423-b36c-7c59eaa08b73')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:check_grant")
+    def test_check_role_from_group_on_project_existence(self):
+        self.roles_client.create_group_role_on_project(
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_group_on_project,
+                        self.project['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.check_role_from_group_on_project_existence(
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
+
+    @decorators.idempotent_id('e7d73bd0-cf5e-4c0c-9c93-cf53e23232d6')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:check_grant")
+    def test_check_role_from_group_on_domain_existence(self):
+        self.roles_client.create_group_role_on_domain(
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_group_on_domain,
+                        self.domain['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.check_role_from_group_on_domain_existence(
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:revoke_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90a')
+    def test_delete_role_from_user_on_project(self):
+        self.roles_client.create_user_role_on_project(
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_user_on_project,
+                        self.project['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.delete_role_from_user_on_project(
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:revoke_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90d')
+    def test_delete_role_from_group_on_project(self):
+        self.roles_client.create_group_role_on_project(
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_group_on_project,
+                        self.project['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.delete_role_from_group_on_project(
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:revoke_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d910')
+    def test_delete_role_from_user_on_domain(self):
+        self.roles_client.create_user_role_on_domain(
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_user_on_domain,
+                        self.domain['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.delete_role_from_user_on_domain(
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:revoke_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d913')
+    def test_delete_role_from_group_on_domain(self):
+        self.roles_client.create_group_role_on_domain(
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_from_group_on_domain,
+                        self.domain['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.delete_role_from_group_on_domain(
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_grants")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90b')
+    def test_list_user_roles_on_project(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.list_user_roles_on_project(
+            self.project['id'],
+            self.user['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_grants")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90e')
+    def test_list_group_roles_on_project(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.list_group_roles_on_project(
+            self.project['id'],
+            self.group['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_grants")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d911')
+    def test_list_user_roles_on_domain(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.list_user_roles_on_domain(
+            self.domain['id'],
+            self.user['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_grants")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d914')
+    def test_list_group_roles_on_domain(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.list_group_roles_on_domain(
+            self.domain['id'],
+            self.group['id'])
+
+    @decorators.idempotent_id('2aef3eaa-8156-4962-a01d-c9bb0e499e15')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_implied_role")
+    def test_create_role_inference_rule(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.create_role_inference_rule(
+            self.role['id'], self.implies_role['id'])['role_inference']
+        self.addCleanup(self.roles_client.delete_role_inference_rule,
+                        self.role['id'], self.implies_role['id'])
+
+    @decorators.idempotent_id('83f997b2-55c4-4894-b1f2-e175b19d1fa5')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:get_implied_role")
+    def test_show_role_inference_rule(self):
+        self.roles_client.create_role_inference_rule(
+            self.role['id'], self.implies_role['id'])
+        self.addCleanup(self.roles_client.delete_role_inference_rule,
+                        self.role['id'], self.implies_role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.show_role_inference_rule(
+            self.role['id'], self.implies_role['id'])['role_inference']
+
+    @decorators.idempotent_id('f7bb39bf-0b06-468e-a8b0-60a4fb1f258d')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_implied_roles")
+    def test_list_role_inferences_rules(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.list_role_inferences_rules(self.role['id'])[
+            'role_inference']
+
+    @decorators.idempotent_id('eca2d502-09bb-45cd-9773-bce2e7bcddd1')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:check_implied_role")
+    def test_check_role_inference_rule(self):
+        self.roles_client.create_role_inference_rule(
+            self.role['id'], self.implies_role['id'])
+        self.addCleanup(self.roles_client.delete_role_inference_rule,
+                        self.role['id'], self.implies_role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.check_role_inference_rule(
+            self.role['id'], self.implies_role['id'])
+
+    @decorators.idempotent_id('13a5db1e-dd4a-4ca1-81ec-d5452aaaf54b')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:delete_implied_role")
+    def test_delete_role_inference_rule(self):
+        self.roles_client.create_role_inference_rule(
+            self.role['id'], self.implies_role['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role_inference_rule,
+                        self.role['id'], self.implies_role['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.delete_role_inference_rule(
+            self.role['id'], self.implies_role['id'])
+
+    @decorators.idempotent_id('05869f2b-4dd4-425a-905e-eec9a6f06374')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_role_inference_rules")
+    def test_list_all_role_inference_rules(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.roles_client.list_all_role_inference_rules()['role_inferences']
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py
index 1439f4f..c02b471 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_services_rbac.py
@@ -13,41 +13,30 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
 
-CONF = config.CONF
 
-
-class IdentitySericesV3AdminRbacTest(rbac_base.BaseIdentityV3RbacAdminTest):
+class IdentitySericesV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_service")
     @decorators.idempotent_id('9a4bb317-f0bb-4005-8df0-4b672885b7c8')
     def test_create_service(self):
-        """Create a service.
-
-        RBAC test for Keystone: identity:create_service
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._create_service()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_service()
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:update_service")
     @decorators.idempotent_id('b39447d1-2cf6-40e5-a899-46f287f2ecf0')
     def test_update_service(self):
-        """Update a service.
+        service = self.setup_test_service()
+        new_name = data_utils.rand_name('service')
 
-        RBAC test for Keystone: identity:update_service
-        """
-        service = self._create_service()
-        new_name = data_utils.rand_name('new_test_name')
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.services_client.update_service(service['id'],
                                             service=service,
                                             name=new_name,
@@ -57,35 +46,23 @@
                                  rule="identity:delete_service")
     @decorators.idempotent_id('177b991a-438d-4bef-8e9f-9c6cc5a1c9e8')
     def test_delete_service(self):
-        """Delete a service.
+        service = self.setup_test_service()
 
-        RBAC test for Keystone: identity:delete_service
-        """
-        service = self._create_service()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.services_client.delete_service(service['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:get_service")
     @decorators.idempotent_id('d89a9ac6-cd53-428d-84c0-5bc71f4a432d')
     def test_show_service(self):
-        """Show/Get a service.
+        service = self.setup_test_service()
 
-        RBAC test for Keystone: identity:get_service
-        """
-        service = self._create_service()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.services_client.show_service(service['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_services")
     @decorators.idempotent_id('706e6bea-3385-4718-919c-0b5121395806')
     def test_list_services(self):
-        """list all services.
-
-        RBAC test for Keystone: identity:list_services
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.services_client.list_services()
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_trusts_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_trusts_rbac.py
new file mode 100644
index 0000000..622b330
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_trusts_rbac.py
@@ -0,0 +1,130 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+CONF = config.CONF
+
+
+class IdentityTrustV3RbacTest(rbac_base.BaseIdentityV3RbacTest):
+
+    credentials = ['primary', 'admin', 'alt']
+
+    @classmethod
+    def skip_checks(cls):
+        super(IdentityTrustV3RbacTest, cls).skip_checks()
+        if not CONF.identity_feature_enabled.trust:
+            raise cls.skipException(
+                "%s skipped as trust feature isn't enabled" % cls.__name__)
+
+    @classmethod
+    def resource_setup(cls):
+        super(IdentityTrustV3RbacTest, cls).resource_setup()
+        # Use the primary user's credentials for the "trustor_user_id", since
+        # user_id:%(trust.trustor_user_id)s will thereby evaluate to
+        # "primary user's user_id:primary user's user_id" which evaluates to
+        # true.
+        cls.trustor_user_id = cls.auth_provider.credentials.user_id
+        cls.trustor_project_id = cls.auth_provider.credentials.project_id
+        cls.trustee_user_id = cls.setup_test_user()['id']
+
+        # The "unauthorized_user_id" does not have permissions to create a
+        # trust because the user_id in "user_id:%(trust.trustor_user_id)s" (the
+        # policy rule for creating a trust) corresponds to the primary user_id
+        # not the alt user_id.
+        cls.unauthorized_user_id = cls.os_alt.auth_provider.credentials.user_id
+
+        # A role is guaranteed to exist (namely the admin role), because
+        # "trustor_user_id" and "trustor_project_id" are the primary tempest
+        # user and project, respectively.
+        cls.delegated_role_id = cls.roles_client.list_user_roles_on_project(
+            cls.trustor_project_id, cls.trustor_user_id)['roles'][0]['id']
+
+        cls.trust = cls.setup_test_trust(trustor_user_id=cls.trustor_user_id,
+                                         trustee_user_id=cls.trustee_user_id,
+                                         project_id=cls.trustor_project_id,
+                                         roles=[{'id': cls.delegated_role_id}])
+
+    @decorators.idempotent_id('7ab595a7-9b71-45fe-91d8-2793b0292f72')
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:create_trust",
+        extra_target_data={
+            "trust.trustor_user_id": "os.auth_provider.credentials.user_id"
+        })
+    def test_create_trust(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_trust(trustor_user_id=self.trustor_user_id,
+                              trustee_user_id=self.trustee_user_id)
+
+    @decorators.idempotent_id('bd72d22a-6e11-4840-bd93-17b382e7f0e0')
+    @test.attr(type=['negative'])
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:create_trust",
+        extra_target_data={
+            "trust.trustor_user_id": "os_alt.auth_provider.credentials.user_id"
+        })
+    def test_create_trust_negative(self):
+        # Explicit negative test for identity:create_trust policy action.
+        # Assert expected exception is Forbidden and then reraise it.
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        e = self.assertRaises(lib_exc.Forbidden, self.setup_test_trust,
+                              trustor_user_id=self.unauthorized_user_id,
+                              trustee_user_id=self.trustee_user_id)
+        raise e
+
+    @decorators.idempotent_id('d9a6fd06-08f6-462c-a86c-ce009adf1230')
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:delete_trust")
+    def test_delete_trust(self):
+        trust = self.setup_test_trust(trustor_user_id=self.trustor_user_id,
+                                      trustee_user_id=self.trustee_user_id)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.trusts_client.delete_trust(trust['id'])
+
+    @decorators.idempotent_id('f2e32896-bf66-4f4e-89cf-e7fba0ef1f38')
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:list_trusts")
+    def test_list_trusts(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.trusts_client.list_trusts(
+            trustor_user_id=self.trustor_user_id)['trusts']
+
+    @decorators.idempotent_id('3c9ff92f-a73e-4f9b-8865-e017f38c70f5')
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:list_roles_for_trust")
+    def test_list_roles_for_trust(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.trusts_client.list_trust_roles(self.trust['id'])['roles']
+
+    @decorators.idempotent_id('3bb4f97b-cecd-4c7d-ad10-b88ee6c5d573')
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:get_role_for_trust")
+    def test_show_trust_role(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.trusts_client.show_trust_role(
+            self.trust['id'], self.delegated_role_id)['role']
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py
index 66798cd..7380531 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_users_rbac.py
@@ -13,126 +13,85 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
 
-CONF = config.CONF
 
+class IdentityUserV3AdminRbacTest(rbac_base.BaseIdentityV3RbacTest):
 
-class IdentityUserV3AdminRbacTest(
-        rbac_base.BaseIdentityV3RbacAdminTest):
+    @classmethod
+    def resource_setup(cls):
+        super(IdentityUserV3AdminRbacTest, cls).resource_setup()
+        cls.default_user_id = cls.auth_provider.credentials.user_id
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_user")
     @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d904')
     def test_create_user(self):
-        """Creates a user.
-
-        RBAC test for Keystone: identity:create_user
-        """
-        user_name = data_utils.rand_name('test_create_user')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client.create_user(name=user_name)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.setup_test_user()
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:update_user")
     @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d905')
     def test_update_user(self):
-        """Updates a user.
+        user = self.setup_test_user()
+        new_email = data_utils.rand_name('user_email')
 
-        RBAC test for Keystone: identity:update_user
-        """
-        user_name = data_utils.rand_name('test_update_user')
-        user = self._create_test_user(name=user_name, password=None)
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client.update_user(user['id'],
-                                                name=user_name,
-                                                email="changedUser@xyz.com")
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.users_client.update_user(user['id'],
+                                      name=user['name'],
+                                      email=new_email)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:delete_user")
     @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d906')
     def test_delete_user(self):
-        """Get the list of users.
+        user = self.setup_test_user()
 
-        RBAC test for Keystone: identity:delete_user
-        """
-        user_name = data_utils.rand_name('test_delete_user')
-        user = self._create_test_user(name=user_name, password=None)
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client.delete_user(user['id'])
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.users_client.delete_user(user['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_users")
     @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d907')
     def test_list_users(self):
-        """Get the list of users.
-
-        RBAC test for Keystone: identity:list_users
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client.list_users()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.users_client.list_users()
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:get_user")
     @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d908')
-    def test_show_user(self):
-        """Get one user.
-
-        RBAC test for Keystone: identity:get_user
-        """
-        user_name = data_utils.rand_name('test_get_user')
-        user = self._create_test_user(name=user_name, password=None)
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client.show_user(user['id'])
+    def test_show_own_user(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.users_client.show_user(self.default_user_id)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:change_password")
     @decorators.idempotent_id('0f148510-63bf-11e6-4522-080044d0d90a')
     def test_change_password(self):
-        """Update a user password
+        original_password = data_utils.rand_password()
+        user = self.setup_test_user(password=original_password)
 
-        RBAC test for Keystone: identity:change_password
-        """
-        user_name = data_utils.rand_name('test_change_password')
-        user = self._create_test_user(name=user_name, password='nova')
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client \
-            .update_user_password(user['id'],
-                                  original_password='nova',
-                                  password='neutron')
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.users_client.update_user_password(
+            user['id'],
+            original_password=original_password,
+            password=data_utils.rand_password())
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_groups_for_user")
     @decorators.idempotent_id('bd5946d4-46d2-423d-a800-a3e7aabc18b3')
-    def test_list_group_user(self):
-        """Lists groups which a user belongs to.
-
-        RBAC test for Keystone: identity:list_groups_for_user
-        """
-        user_name = data_utils.rand_name('User')
-        user = self._create_test_user(name=user_name, password=None)
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client.list_user_groups(user['id'])
+    def test_list_own_user_group(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.users_client.list_user_groups(self.default_user_id)
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_user_projects")
     @decorators.idempotent_id('0f148510-63bf-11e6-1564-080044d0d909')
-    def test_list_user_projects(self):
-        """List User's Projects.
-
-        RBAC test for Keystone: identity:list_user_projects
-        """
-        user = self.setup_test_user()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.non_admin_users_client.list_user_projects(user['id'])
+    def test_list_own_user_projects(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.users_client.list_user_projects(self.default_user_id)
diff --git a/patrole_tempest_plugin/tests/api/image/rbac_base.py b/patrole_tempest_plugin/tests/api/image/rbac_base.py
index b4fed7d..2a45ccb 100644
--- a/patrole_tempest_plugin/tests/api/image/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/image/rbac_base.py
@@ -26,16 +26,16 @@
     @classmethod
     def skip_checks(cls):
         super(BaseV1ImageRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
+        if not CONF.rbac.enable_rbac:
             raise cls.skipException(
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
     def setup_clients(cls):
         super(BaseV1ImageRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
+        cls.auth_provider = cls.os_primary.auth_provider
         cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
 
 
 class BaseV2ImageRbacTest(image_base.BaseV2ImageTest):
@@ -45,13 +45,13 @@
     @classmethod
     def skip_checks(cls):
         super(BaseV2ImageRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
+        if not CONF.rbac.enable_rbac:
             raise cls.skipException(
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
     def setup_clients(cls):
         super(BaseV2ImageRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
+        cls.auth_provider = cls.os_primary.auth_provider
         cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
diff --git a/patrole_tempest_plugin/tests/api/image/v1/test_images_member_rbac.py b/patrole_tempest_plugin/tests/api/image/v1/test_images_member_rbac.py
index d431eee..8015277 100644
--- a/patrole_tempest_plugin/tests/api/image/v1/test_images_member_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/v1/test_images_member_rbac.py
@@ -29,7 +29,7 @@
     @classmethod
     def setup_clients(cls):
         super(ImagesMemberRbacTest, cls).setup_clients()
-        cls.image_member_client = cls.os.image_member_client
+        cls.image_member_client = cls.os_primary.image_member_client
 
     @classmethod
     def resource_setup(cls):
@@ -45,7 +45,7 @@
         """
         image = self.create_image()
         # Toggle role and add image member
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.image_member_client.create_image_member(image['id'],
                                                      self.alt_tenant_id)
 
@@ -60,7 +60,7 @@
         self.image_member_client.create_image_member(image['id'],
                                                      self.alt_tenant_id)
         # Toggle role and delete image member
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.image_member_client.delete_image_member(image['id'],
                                                      self.alt_tenant_id)
 
@@ -75,5 +75,5 @@
         self.image_member_client.create_image_member(image['id'],
                                                      self.alt_tenant_id)
         # Toggle role and delete image member
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.image_member_client.list_image_members(image['id'])
diff --git a/patrole_tempest_plugin/tests/api/image/v1/test_images_rbac.py b/patrole_tempest_plugin/tests/api/image/v1/test_images_rbac.py
index 251c372..ae4e4d2 100644
--- a/patrole_tempest_plugin/tests/api/image/v1/test_images_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/v1/test_images_rbac.py
@@ -36,7 +36,7 @@
         """
         properties = {'prop1': 'val1'}
         image_name = data_utils.rand_name('image')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.create_image(name=image_name,
                           container_format='bare',
                           disk_format='raw',
@@ -58,7 +58,7 @@
                                  is_public=False,
                                  properties=properties)
         image_id = body['id']
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_image(image_id)
 
     @rbac_rule_validation.action(service="glance", rule="download_image")
@@ -80,7 +80,7 @@
         image_file = moves.cStringIO(data_utils.random_bytes())
         self.client.update_image(image_id, data=image_file)
         # Toggle role and get created image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_image(image_id)
 
     @rbac_rule_validation.action(service="glance", rule="get_image")
@@ -102,7 +102,7 @@
         image_file = moves.cStringIO(data_utils.random_bytes())
         self.client.update_image(image_id, data=image_file)
         # Toggle role and get created image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.check_image(image_id)
 
     @rbac_rule_validation.action(service="glance", rule="get_images")
@@ -112,7 +112,7 @@
 
         RBAC test for the glance get_images policy.
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_images()
 
     @rbac_rule_validation.action(service="glance", rule="modify_image")
@@ -131,7 +131,7 @@
                                  properties=properties)
         image_id = body.get('id')
         properties = {'prop1': 'val2'}
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.update_image(image_id, headers=properties)
 
     @rbac_rule_validation.action(service="glance", rule="publicize_image")
@@ -143,7 +143,7 @@
         """
         image_name = data_utils.rand_name('image')
         properties = {'prop1': 'val1'}
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.create_image(name=image_name,
                           container_format='bare',
                           disk_format='raw',
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_objects_rbac.py b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_objects_rbac.py
index 4370b6d..1c937b0 100644
--- a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_objects_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_objects_rbac.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
@@ -21,8 +20,6 @@
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.image import rbac_base
 
-CONF = config.CONF
-
 
 class ImageNamespacesObjectsRbacTest(rbac_base.BaseV2ImageRbacTest):
 
@@ -35,7 +32,7 @@
         RBAC test for the glance add_metadef_object policy
         """
         namespace = self.create_namespace()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # create a md object, it will be cleaned automatically after
         # cleanup of namespace
         object_name = data_utils.rand_name('test-object')
@@ -55,7 +52,7 @@
         RBAC test for the glance get_metadef_objects policy
         """
         namespace = self.create_namespace()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # list md objects
         self.namespace_objects_client.list_namespace_objects(
             namespace['namespace'])
@@ -78,7 +75,7 @@
                         namespace['namespace'], object_name)
 
         # Toggle role and modify object
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         new_name = "Object New Name"
         self.namespace_objects_client.update_namespace_object(
             namespace['namespace'], object_name, name=new_name)
@@ -100,7 +97,7 @@
                         self.namespace_objects_client.delete_namespace_object,
                         namespace['namespace'], object_name)
         # Toggle role and get object
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.namespace_objects_client.show_namespace_object(
             namespace['namespace'],
             object_name)
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_property_rbac.py b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_property_rbac.py
index e1858f4..0d194b7 100644
--- a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_property_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_property_rbac.py
@@ -13,15 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.image import rbac_base
 
-CONF = config.CONF
-
 
 class NamespacesPropertyRbacTest(rbac_base.BaseV2ImageRbacTest):
 
@@ -40,7 +37,7 @@
         RBAC test for the glance add_metadef_property policy
         """
         namespace = self.create_namespace()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         property_name = data_utils.rand_name('test-ns-property')
         self.namespace_properties_client.create_namespace_property(
             namespace=namespace['namespace'], type="string",
@@ -55,7 +52,7 @@
         RBAC test for the glance get_metadef_properties policy
         """
         namespace = self.create_namespace()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.namespace_properties_client.list_namespace_properties(
             namespace=namespace['namespace'])
 
@@ -73,7 +70,7 @@
             namespace=namespace['namespace'], type="string",
             title=property_name, name=self.resource_name)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.namespace_properties_client.show_namespace_properties(
             namespace['namespace'], self.resource_name)
 
@@ -91,7 +88,7 @@
             namespace=namespace['namespace'], type="string",
             title=property_name, name=self.resource_name)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.namespace_properties_client.update_namespace_properties(
             namespace['namespace'], self.resource_name, type="string",
             title=property_name, name=self.resource_name)
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_rbac.py b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_rbac.py
index 779ba8f..fb4a599 100644
--- a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_rbac.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
@@ -21,8 +20,6 @@
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.image import rbac_base
 
-CONF = config.CONF
-
 
 class ImageNamespacesRbacTest(rbac_base.BaseV2ImageRbacTest):
 
@@ -35,7 +32,7 @@
         RBAC test for the glance add_metadef_namespace policy
         """
         namespace_name = data_utils.rand_name('test-ns')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.namespaces_client.create_namespace(
             namespace=namespace_name,
             protected=False)
@@ -52,7 +49,7 @@
 
         RBAC test for the glance get_metadef_namespaces policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.namespaces_client.list_namespaces()
 
     @rbac_rule_validation.action(service="glance",
@@ -67,7 +64,7 @@
         body = self.namespaces_client.create_namespace(
             namespace=namespace_name,
             protected=False)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.namespaces_client.update_namespace(body['namespace'],
                                                 description="My new "
                                                             "description")
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_resource_type.py b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_resource_type.py
deleted file mode 100644
index e537414..0000000
--- a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_resource_type.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#    Copyright 2017 AT&T Corporation.
-#    All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest import config
-from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
-from tempest.lib import decorators
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.image import rbac_base
-
-CONF = config.CONF
-
-
-class ImageNamespacesResourceTypeRbacTest(rbac_base.BaseV2ImageRbacTest):
-
-    @rbac_rule_validation.action(service="glance",
-                                 rule="list_metadef_resource_types")
-    @decorators.idempotent_id('0416fc4d-cfdc-447b-88b6-d9f1dd0382f7')
-    def test_list_metadef_resource_types(self):
-        """List Metadef Resource Type Image Test
-
-        RBAC test for the glance list_metadef_resource_type policy.
-        """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.resource_types_client.list_resource_types()
-
-    @rbac_rule_validation.action(service="glance",
-                                 rule="get_metadef_resource_type")
-    @decorators.idempotent_id('3698d53c-71ae-4803-a2c3-c272c054f25c')
-    def test_get_metadef_resource_type(self):
-        """Get Metadef Resource Type Image Test
-
-        RBAC test for the glance get_metadef_resource_type policy.
-        """
-        namespace_name = data_utils.rand_name('test-ns')
-        self.namespaces_client.create_namespace(
-            namespace=namespace_name,
-            protected=False)
-        self.addCleanup(
-            test_utils.call_and_ignore_notfound_exc,
-            self.namespaces_client.delete_namespace,
-            namespace_name)
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.resource_types_client.list_resource_type_association(
-            namespace_name)
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_tags_rbac.py b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_tags_rbac.py
new file mode 100644
index 0000000..cfd544c
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/image/v2/test_image_namespace_tags_rbac.py
@@ -0,0 +1,112 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.image import rbac_base as base
+
+
+class NamespaceTagsRbacTest(base.BaseV2ImageRbacTest):
+    """RBAC tests for namespace_tags_client.
+
+    Performs RBAC testing for the endpoints in namespace_tags_client, except
+    for
+
+        1) delete_namespace_tag
+        2) delete_namespace_tags
+
+    because Glance does not currently do policy enforcement for them.
+    """
+
+    @classmethod
+    def setup_clients(cls):
+        super(NamespaceTagsRbacTest, cls).setup_clients()
+        cls.client = cls.namespace_tags_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(NamespaceTagsRbacTest, cls).resource_setup()
+        cls.namespace = cls.namespaces_client.create_namespace(
+            namespace=data_utils.rand_name('namespace'))['namespace']
+
+    @classmethod
+    def resource_cleanup(cls):
+        cls.namespaces_client.delete_namespace(cls.namespace)
+        super(NamespaceTagsRbacTest, cls).resource_cleanup()
+
+    def _create_namespace_tag(self, multiple=False):
+        tag_count = 2 if multiple else 1
+        namespace_tag_names = []
+
+        for i in range(tag_count):
+            tag_name = data_utils.rand_name('tag')
+            namespace_tag_names.append({'name': tag_name})
+
+        if multiple:
+            namespace_tags = self.client.create_namespace_tags(
+                self.namespace, tags=namespace_tag_names)['tags']
+        else:
+            namespace_tags = self.client.create_namespace_tag(
+                self.namespace, namespace_tag_names[0]['name'])
+
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_namespace_tags,
+                        self.namespace)
+
+        return [nt['name'] for nt in namespace_tags] if multiple \
+            else namespace_tags['name']
+
+    @decorators.idempotent_id('50bedccb-9d0b-4138-8d95-31a89250edf6')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="add_metadef_tag")
+    def test_create_namespace_tag(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._create_namespace_tag()
+
+    @decorators.idempotent_id('4acf70cc-05da-4b1e-87b2-d5e4475164e7')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="get_metadef_tag")
+    def test_show_namespace_tag(self):
+        tag_name = self._create_namespace_tag()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_namespace_tag(self.namespace, tag_name)
+
+    @decorators.idempotent_id('01593828-3edb-461e-8abc-8fdeb3927e37')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="modify_metadef_tag")
+    def test_update_namespace_tag(self):
+        tag_name = self._create_namespace_tag()
+        updated_tag_name = data_utils.rand_name('tag')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.update_namespace_tag(self.namespace, tag_name,
+                                         name=updated_tag_name)
+
+    @decorators.idempotent_id('20ffaf76-ebdc-4267-a1ad-194346f5cc91')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="add_metadef_tags")
+    def test_create_namespace_tags(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._create_namespace_tag(multiple=True)
+
+    @decorators.idempotent_id('d37c1501-e787-449d-89b3-754a942a459a')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="get_metadef_tags")
+    def test_list_namespace_tags(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_namespace_tags(self.namespace)
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_image_resource_types_rbac.py b/patrole_tempest_plugin/tests/api/image/v2/test_image_resource_types_rbac.py
new file mode 100644
index 0000000..552a137
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/image/v2/test_image_resource_types_rbac.py
@@ -0,0 +1,71 @@
+#    Copyright 2017 AT&T Corporation.
+#    All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.image import rbac_base
+
+
+class ImageResourceTypesRbacTest(rbac_base.BaseV2ImageRbacTest):
+
+    @classmethod
+    def resource_setup(cls):
+        super(ImageResourceTypesRbacTest, cls).resource_setup()
+        cls.namespace_name = data_utils.rand_name('test-ns')
+        cls.namespaces_client.create_namespace(
+            namespace=cls.namespace_name,
+            protected=False)
+
+    @classmethod
+    def resource_cleanup(cls):
+        test_utils.call_and_ignore_notfound_exc(
+            cls.namespaces_client.delete_namespace,
+            cls.namespace_name)
+        super(ImageResourceTypesRbacTest, cls).resource_setup()
+
+    @rbac_rule_validation.action(service="glance",
+                                 rule="list_metadef_resource_types")
+    @decorators.idempotent_id('0416fc4d-cfdc-447b-88b6-d9f1dd0382f7')
+    def test_list_metadef_resource_types(self):
+        """List Metadef Resource Type Image Test
+
+        RBAC test for the glance list_metadef_resource_type policy.
+        """
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.resource_types_client.list_resource_types()
+
+    @rbac_rule_validation.action(service="glance",
+                                 rule="get_metadef_resource_type")
+    @decorators.idempotent_id('3698d53c-71ae-4803-a2c3-c272c054f25c')
+    def test_get_metadef_resource_type(self):
+        """Get Metadef Resource Type Image Test
+
+        RBAC test for the glance get_metadef_resource_type policy.
+        """
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.resource_types_client.list_resource_type_association(
+            self.namespace_name)
+
+    @rbac_rule_validation.action(service="glance",
+                                 rule="add_metadef_resource_type_association")
+    @decorators.idempotent_id('ef9fbc60-3e28-4164-a25c-d30d892f7939')
+    def test_add_metadef_resource_type(self):
+        type_name = data_utils.rand_name()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.resource_types_client.create_resource_type_association(
+            self.namespace_name, name=type_name)
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_images_member_rbac.py b/patrole_tempest_plugin/tests/api/image/v2/test_images_member_rbac.py
index bbd5a79..a7c59f5 100644
--- a/patrole_tempest_plugin/tests/api/image/v2/test_images_member_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/v2/test_images_member_rbac.py
@@ -13,18 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-from tempest import config
 from tempest.lib import decorators
-from tempest.lib import exceptions
 
-from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.image import rbac_base as base
 
-CONF = config.CONF
-LOG = logging.getLogger(__name__)
-
 
 class ImagesMemberRbacTest(base.BaseV2ImageRbacTest):
 
@@ -39,12 +32,8 @@
     @classmethod
     def setup_clients(cls):
         super(ImagesMemberRbacTest, cls).setup_clients()
-        cls.image_client = cls.os.image_client_v2
-        cls.image_member_client = cls.os.image_member_client_v2
-
-    def setUp(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=False)
-        super(ImagesMemberRbacTest, self).setUp()
+        cls.image_client = cls.os_primary.image_client_v2
+        cls.image_member_client = cls.os_primary.image_member_client_v2
 
     @rbac_rule_validation.action(service="glance",
                                  rule="add_member")
@@ -57,7 +46,7 @@
         """
         image_id = self.create_image()['id']
         # Toggle role and add image member
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.image_member_client.create_image_member(image_id,
                                                      member=self.alt_tenant_id)
 
@@ -74,12 +63,13 @@
         self.image_member_client.create_image_member(image_id,
                                                      member=self.alt_tenant_id)
         # Toggle role and delete image member
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.image_member_client.delete_image_member(image_id,
                                                      self.alt_tenant_id)
 
     @rbac_rule_validation.action(service="glance",
-                                 rule="get_member")
+                                 rule="get_member",
+                                 expected_error_code=404)
     @decorators.idempotent_id('c01fd308-6484-11e6-881e-080027d0d606')
     def test_show_image_member(self):
 
@@ -87,24 +77,16 @@
 
         RBAC test for the glance get_member policy
         """
-        try:
-            image_id = self.create_image()['id']
-            self.image_member_client.create_image_member(
-                image_id,
-                member=self.alt_tenant_id)
+        image_id = self.create_image()['id']
+        self.image_member_client.create_image_member(
+            image_id,
+            member=self.alt_tenant_id)
 
-            # Toggle role and get image member
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            self.image_member_client.show_image_member(
-                image_id,
-                self.alt_tenant_id)
-        except exceptions.NotFound as e:
-            '''If the role doesn't have access to an image, a 404 exception is
-            thrown when the roles tries to show an image member'''
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the image and tries to show "
-                     "image members")
-            raise rbac_exceptions.RbacActionFailed(e)
+        # Toggle role and get image member
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.image_member_client.show_image_member(
+            image_id,
+            self.alt_tenant_id)
 
     @rbac_rule_validation.action(service="glance",
                                  rule="modify_member")
@@ -123,7 +105,7 @@
             image_id, self.tenant_id,
             status='accepted')
         # Toggle role and update member
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.image_member_client.update_image_member(
             image_id, self.tenant_id,
             status='pending')
@@ -141,5 +123,5 @@
         self.image_member_client.create_image_member(image_id,
                                                      member=self.alt_tenant_id)
         # Toggle role and list image members
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.image_member_client.list_image_members(image_id)
diff --git a/patrole_tempest_plugin/tests/api/image/v2/test_images_rbac.py b/patrole_tempest_plugin/tests/api/image/v2/test_images_rbac.py
index 8812262..880f892 100644
--- a/patrole_tempest_plugin/tests/api/image/v2/test_images_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/v2/test_images_rbac.py
@@ -15,24 +15,31 @@
 
 from six import moves
 
-from oslo_log import log as logging
-from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.image import rbac_base
 
-CONF = config.CONF
-LOG = logging.getLogger(__name__)
-
 
 class BasicOperationsImagesRbacTest(rbac_base.BaseV2ImageRbacTest):
 
     @classmethod
     def setup_clients(cls):
         super(BasicOperationsImagesRbacTest, cls).setup_clients()
-        cls.client = cls.os.image_client_v2
+        cls.client = cls.os_primary.image_client_v2
+
+    def _create_image(self, **kwargs):
+        image_name = data_utils.rand_name('image')
+        image = self.create_image(name=image_name,
+                                  container_format='bare',
+                                  disk_format='raw',
+                                  **kwargs)
+        return image
+
+    def _upload_image(self, image_id):
+        image_file = moves.cStringIO(data_utils.random_bytes())
+        return self.client.store_image_file(image_id, image_file)
 
     @rbac_rule_validation.action(service="glance",
                                  rule="add_image")
@@ -43,14 +50,8 @@
 
         RBAC test for the glance create_image endpoint
         """
-        uuid = '00000000-1111-2222-3333-444455556666'
-        image_name = data_utils.rand_name('image')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.create_image(name=image_name,
-                          container_format='bare',
-                          disk_format='raw',
-                          visibility='private',
-                          ramdisk_id=uuid)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._create_image()
 
     @rbac_rule_validation.action(service="glance",
                                  rule="upload_image")
@@ -61,18 +62,25 @@
 
         RBAC test for the glance upload_image endpoint
         """
-        uuid = '00000000-1111-2222-3333-444455556666'
-        image_name = data_utils.rand_name('image')
-        body = self.create_image(name=image_name,
-                                 container_format='bare',
-                                 disk_format='raw',
-                                 visibility='private',
-                                 ramdisk_id=uuid)
+        image = self._create_image()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Try uploading an image file
-        image_file = moves.cStringIO(data_utils.random_bytes())
-        self.client.store_image_file(body['id'], image_file)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._upload_image(image['id'])
+
+    @decorators.idempotent_id('f0c268f3-cb51-49aa-9bd5-d30cf647322f')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="download_image")
+    def test_download_image(self):
+
+        """Download Image Test
+
+        RBAC test for the glance download_image endpoint
+        """
+        image = self._create_image()
+        self._upload_image(image['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_image_file(image['id'])
 
     @rbac_rule_validation.action(service="glance",
                                  rule="delete_image")
@@ -83,16 +91,11 @@
 
         RBAC test for the glance delete_image endpoint
         """
-        image_name = data_utils.rand_name('image')
-        body = self.create_image(name=image_name,
-                                 container_format='bare',
-                                 disk_format='raw',
-                                 visibility='public')
-        image_id = body.get('id')
-        # Toggle role and delete created image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.delete_image(image_id)
-        self.client.wait_for_resource_deletion(image_id)
+        image = self._create_image()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_image(image['id'])
+        self.client.wait_for_resource_deletion(image['id'])
 
     @rbac_rule_validation.action(service="glance",
                                  rule="get_image")
@@ -103,16 +106,10 @@
 
         RBAC test for the glance create_image endpoint
         """
+        image = self._create_image()
 
-        image_name = data_utils.rand_name('image')
-        body = self.create_image(name=image_name,
-                                 container_format='bare',
-                                 disk_format='raw',
-                                 visibility='private')
-        image_id = body.get('id')
-        # Toggle role and get created image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.show_image(image_id)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_image(image['id'])
 
     @rbac_rule_validation.action(service="glance",
                                  rule="get_images")
@@ -123,10 +120,8 @@
 
         RBAC test for the glance list_images endpoint
         """
-
-        # Toggle role and get created image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.list_images()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_images()['images']
 
     @rbac_rule_validation.action(service="glance",
                                  rule="modify_image")
@@ -137,22 +132,42 @@
 
         RBAC test for the glance update_image endpoint
         """
-        image_name = data_utils.rand_name('image')
-        body = self.create_image(name=image_name,
-                                 container_format='bare',
-                                 disk_format='raw',
-                                 visibility='private')
-        image_id = body.get('id')
+        image = self._create_image()
 
-        # Now try uploading an image file
-        image_file = moves.cStringIO(data_utils.random_bytes())
-        self.client.store_image_file(image_id, image_file)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        updated_image_name = data_utils.rand_name('image')
+        self.client.update_image(image['id'], [
+            dict(replace='/name', value=updated_image_name)])
 
-        # Toggle role and update created image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        new_image_name = data_utils.rand_name('new-image')
-        body = self.client.update_image(image_id, [
-            dict(replace='/name', value=new_image_name)])
+    @decorators.idempotent_id('244050d9-1b9a-446a-b3c5-f26f3ba8eb75')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="modify_image")
+    def test_create_image_tag(self):
+
+        """Create image tag
+
+        RBAC test for the glance add_image_tag endpoint
+        """
+        image = self._create_image()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.add_image_tag(image['id'], data_utils.rand_name('tag'))
+
+    @decorators.idempotent_id('c4a0bf9c-b78b-48c6-a31f-72c95f943c6e')
+    @rbac_rule_validation.action(service="glance",
+                                 rule="modify_image")
+    def test_delete_image_tag(self):
+
+        """Delete image tag
+
+        RBAC test for the glance delete_image_tag endpoint
+        """
+        image = self._create_image()
+        tag_name = data_utils.rand_name('tag')
+        self.client.add_image_tag(image['id'], tag_name)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_image_tag(image['id'], tag_name)
 
     @rbac_rule_validation.action(service="glance",
                                  rule="publicize_image")
@@ -163,12 +178,8 @@
 
         RBAC test for the glance publicize_image endpoint
         """
-        image_name = data_utils.rand_name('image')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.create_image(name=image_name,
-                          container_format='bare',
-                          disk_format='raw',
-                          visibility='public')
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._create_image(visibility='public')
 
     @rbac_rule_validation.action(service="glance",
                                  rule="deactivate")
@@ -179,20 +190,11 @@
 
         RBAC test for the glance deactivate_image endpoint
         """
-        uuid = '00000000-1111-2222-3333-444455556666'
-        image_name = data_utils.rand_name('image')
-        body = self.create_image(name=image_name,
-                                 container_format='bare',
-                                 disk_format='raw',
-                                 visibility='private',
-                                 ramdisk_id=uuid)
-        image_id = body.get('id')
-        # Now try uploading an image file
-        image_file = moves.cStringIO(data_utils.random_bytes())
-        self.client.store_image_file(image_id=image_id, data=image_file)
-        # Toggling role and deacivate image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.deactivate_image(image_id)
+        image = self._create_image()
+        self._upload_image(image['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.deactivate_image(image['id'])
 
     @rbac_rule_validation.action(service="glance",
                                  rule="reactivate")
@@ -203,18 +205,8 @@
 
         RBAC test for the glance reactivate_image endpoint
         """
-        uuid = '00000000-1111-2222-3333-444455556666'
-        image_name = data_utils.rand_name('image')
-        body = self.create_image(name=image_name,
-                                 container_format='bare',
-                                 disk_format='raw',
-                                 visibility='private',
-                                 ramdisk_id=uuid)
+        image = self._create_image()
+        self._upload_image(image['id'])
 
-        # Now try uploading an image file
-        image_id = body.get('id')
-        image_file = moves.cStringIO(data_utils.random_bytes())
-        self.client.store_image_file(image_id=image_id, data=image_file)
-        # Toggling role and reactivate image
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.reactivate_image(image_id)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.reactivate_image(image['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/rbac_base.py b/patrole_tempest_plugin/tests/api/network/rbac_base.py
index de5ed88..629f0ca 100644
--- a/patrole_tempest_plugin/tests/api/network/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/network/rbac_base.py
@@ -28,13 +28,13 @@
     @classmethod
     def skip_checks(cls):
         super(BaseNetworkRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
+        if not CONF.rbac.enable_rbac:
             raise cls.skipException(
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
     def setup_clients(cls):
         super(BaseNetworkRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
+        cls.auth_provider = cls.os_primary.auth_provider
         cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
diff --git a/patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py b/patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py
index d186f38..a875321 100644
--- a/patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_floating_ips_rbac.py
@@ -19,9 +19,7 @@
 from tempest import config
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 
-from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.network import rbac_base as base
 
@@ -77,7 +75,7 @@
 
         RBAC test for the neutron create_floatingip policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_floatingip()
 
     @rbac_rule_validation.action(service="neutron",
@@ -90,7 +88,7 @@
         """
         fip = str(netaddr.IPAddress(self.cidr) + 10)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_floatingip(floating_ip_address=fip)
 
     @rbac_rule_validation.action(service="neutron",
@@ -102,13 +100,15 @@
         RBAC test for the neutron update_floatingip policy
         """
         floating_ip = self._create_floatingip()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
 
         # Associate floating IP to the other port
         self.floating_ips_client.update_floatingip(
             floating_ip['id'], port_id=None)
 
-    @rbac_rule_validation.action(service="neutron", rule="get_floatingip")
+    @rbac_rule_validation.action(service="neutron",
+                                 rule="get_floatingip",
+                                 expected_error_code=404)
     @decorators.idempotent_id('f8846fd0-c976-48fe-a148-105303931b32')
     def test_show_floating_ip(self):
         """Show floating IP.
@@ -116,19 +116,13 @@
         RBAC test for the neutron get_floatingip policy
         """
         floating_ip = self._create_floatingip()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-
-        try:
-            # Show floating IP
-            self.floating_ips_client.show_floatingip(floating_ip['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        # Show floating IP
+        self.floating_ips_client.show_floatingip(floating_ip['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_floatingip")
+                                 rule="delete_floatingip",
+                                 expected_error_code=404)
     @decorators.idempotent_id('2611b068-30d4-4241-a78f-1b801a14db7e')
     def test_delete_floating_ip(self):
         """Delete floating IP.
@@ -136,14 +130,6 @@
         RBAC test for the neutron delete_floatingip policy
         """
         floating_ip = self._create_floatingip()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-
-        try:
-            # Delete the floating IP
-            self.floating_ips_client.delete_floatingip(floating_ip['id'])
-
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        # Delete the floating IP
+        self.floating_ips_client.delete_floatingip(floating_ip['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py b/patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py
index 21c2f96..2efb3fe 100644
--- a/patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_metering_label_rules_rbac.py
@@ -18,10 +18,8 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 from tempest import test
 
-from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.network import rbac_base as base
 
@@ -41,8 +39,9 @@
     @classmethod
     def setup_clients(cls):
         super(MeteringLabelRulesRbacTest, cls).setup_clients()
-        cls.metering_labels_client = cls.os.metering_labels_client
-        cls.metering_label_rules_client = cls.os.metering_label_rules_client
+        cls.metering_labels_client = cls.os_primary.metering_labels_client
+        cls.metering_label_rules_client = \
+            cls.os_primary.metering_label_rules_client
 
     @classmethod
     def resource_setup(cls):
@@ -77,11 +76,12 @@
 
         RBAC test for the neutron create_metering_label_rule policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_metering_label_rule(self.label)
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_metering_label_rule")
+                                 rule="get_metering_label_rule",
+                                 expected_error_code=404)
     @decorators.idempotent_id('e21b40c3-d44d-412f-84ea-836ca8603bcb')
     def test_show_metering_label_rule(self):
         """Show metering label rule.
@@ -89,18 +89,13 @@
         RBAC test for the neutron get_metering_label_rule policy
         """
         label_rule = self._create_metering_label_rule(self.label)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.metering_label_rules_client.show_metering_label_rule(
-                label_rule['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.metering_label_rules_client.show_metering_label_rule(
+            label_rule['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_metering_label_rule")
+                                 rule="delete_metering_label_rule",
+                                 expected_error_code=404)
     @decorators.idempotent_id('e3adc88c-05c0-43a7-8e32-63947ae4890e')
     def test_delete_metering_label_rule(self):
         """Delete metering label rule.
@@ -108,12 +103,6 @@
         RBAC test for the neutron delete_metering_label_rule policy
         """
         label_rule = self._create_metering_label_rule(self.label)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.metering_label_rules_client.delete_metering_label_rule(
-                label_rule['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.metering_label_rules_client.delete_metering_label_rule(
+            label_rule['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py b/patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py
index 09e298c..9aabfa0 100644
--- a/patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_metering_labels_rbac.py
@@ -17,10 +17,8 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 from tempest import test
 
-from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.network import rbac_base as base
 
@@ -39,7 +37,7 @@
     @classmethod
     def setup_clients(cls):
         super(MeteringLabelsRbacTest, cls).setup_clients()
-        cls.metering_labels_client = cls.os.metering_labels_client
+        cls.metering_labels_client = cls.os_primary.metering_labels_client
 
     def _create_metering_label(self):
         body = self.metering_labels_client.create_metering_label(
@@ -59,11 +57,12 @@
 
         RBAC test for the neutron "create_metering_label" policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_metering_label()
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_metering_label")
+                                 rule="get_metering_label",
+                                 expected_error_code=404)
     @decorators.idempotent_id('c57f6636-c702-4755-8eac-5e73bc1f7d14')
     def test_show_metering_label(self):
         """Show metering label.
@@ -71,17 +70,12 @@
         RBAC test for the neutron "get_metering_label" policy
         """
         label = self._create_metering_label()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.metering_labels_client.show_metering_label(label['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.metering_labels_client.show_metering_label(label['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_metering_label")
+                                 rule="delete_metering_label",
+                                 expected_error_code=404)
     @decorators.idempotent_id('1621ccfe-2e3f-4d16-98aa-b620f9d00404')
     def test_delete_metering_label(self):
         """Delete metering label.
@@ -89,11 +83,5 @@
         RBAC test for the neutron "delete_metering_label" policy
         """
         label = self._create_metering_label()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.metering_labels_client.delete_metering_label(label['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.metering_labels_client.delete_metering_label(label['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/test_networks_multiprovider_rbac.py b/patrole_tempest_plugin/tests/api/network/test_networks_multiprovider_rbac.py
index 233f705..01cf0fd 100644
--- a/patrole_tempest_plugin/tests/api/network/test_networks_multiprovider_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_networks_multiprovider_rbac.py
@@ -56,7 +56,7 @@
 
         RBAC test for the neutron create_network:segments policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_network_segments()
 
     @rbac_rule_validation.action(service="neutron",
@@ -70,7 +70,7 @@
         network = self._create_network_segments()
         new_segments = [{"provider:network_type": "gre"}]
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.networks_client.update_network(network['id'],
                                             segments=new_segments)
 
@@ -84,7 +84,7 @@
         """
         network = self._create_network_segments()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         body = self.networks_client.show_network(network['id'],
                                                  fields='segments')
         response_network = body['network']
diff --git a/patrole_tempest_plugin/tests/api/network/test_networks_rbac.py b/patrole_tempest_plugin/tests/api/network/test_networks_rbac.py
index 5d4e11a..133ea74 100644
--- a/patrole_tempest_plugin/tests/api/network/test_networks_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_networks_rbac.py
@@ -30,12 +30,6 @@
 class RbacNetworksTest(base.BaseNetworkRbacTest):
 
     @classmethod
-    def setup_clients(cls):
-        super(RbacNetworksTest, cls).setup_clients()
-        cls.networks_client = cls.os.networks_client
-        cls.subnet_client = cls.os.subnets_client
-
-    @classmethod
     def resource_setup(cls):
         super(RbacNetworksTest, cls).resource_setup()
 
@@ -136,7 +130,7 @@
 
         RBAC test for the neutron create_network policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_network()
 
     @rbac_rule_validation.action(service="neutron",
@@ -148,7 +142,7 @@
 
         RBAC test for the neutron create_network:shared policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_network(shared=True)
 
     @rbac_rule_validation.action(service="neutron",
@@ -160,7 +154,7 @@
 
         RBAC test for the neutron create_network:router:external policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_network(router_external=True)
 
     @rbac_rule_validation.action(service="neutron",
@@ -172,7 +166,7 @@
 
         RBAC test for the neutron create_network:provider:network_type policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_network(provider_network_type='vxlan')
 
     @rbac_rule_validation.action(
@@ -185,7 +179,7 @@
 
         RBAC test for the neutron create_network:provider:segmentation_id
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_network(provider_network_type='vxlan',
                              provider_segmentation_id=200)
 
@@ -198,7 +192,7 @@
 
         RBAC test for the neutron update_network policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         updated_network = self._update_network(admin=False)
         self.assertEqual(updated_network['admin_state_up'], False)
 
@@ -215,7 +209,7 @@
 
         RBAC test for the neutron update_network:shared policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         updated_network = self._update_network(shared_network=True)
         self.assertEqual(updated_network['shared'], True)
 
@@ -233,7 +227,7 @@
         RBAC test for the neutron update_network:router:external policy
         """
         network = self._create_network()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._update_network(net_id=network['id'], router_external=True)
 
     @rbac_rule_validation.action(service="neutron",
@@ -245,7 +239,7 @@
 
         RBAC test for the neutron get_network policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # show a network that has been created during class setup
         self.networks_client.show_network(self.admin_network['id'])
 
@@ -260,7 +254,7 @@
         """
         post_body = {'fields': 'router:external'}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.networks_client.show_network(self.admin_network['id'],
                                           **post_body)
 
@@ -275,7 +269,7 @@
         """
         post_body = {'fields': 'provider:network_type'}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         body = self.networks_client.show_network(self.admin_network['id'],
                                                  **post_body)
         showed_net = body['network']
@@ -294,7 +288,7 @@
         """
         post_body = {'fields': 'provider:physical_network'}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         body = self.networks_client.show_network(self.admin_network['id'],
                                                  **post_body)
         showed_net = body['network']
@@ -313,7 +307,7 @@
         """
         post_body = {'fields': 'provider:segmentation_id'}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         body = self.networks_client.show_network(self.admin_network['id'],
                                                  **post_body)
         showed_net = body['network']
@@ -334,7 +328,7 @@
         RBAC test for the neutron delete_network policy
         """
         network = self._create_network()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.networks_client.delete_network(network['id'])
 
     @rbac_rule_validation.action(service="neutron",
@@ -349,7 +343,7 @@
         network = self._create_network()
         self.assertEqual('ACTIVE', network['status'])
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Create a subnet
         self.create_subnet(network, enable_dhcp=False)
 
@@ -362,7 +356,7 @@
 
         RBAC test for the neutron get_subnet policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.subnets_client.show_subnet(self.admin_subnet['id'])
 
     @rbac_rule_validation.action(service="neutron",
@@ -374,7 +368,7 @@
 
         RBAC test for the neutron update_subnet policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.subnets_client.update_subnet(self.admin_subnet['id'],
                                           name="New_subnet")
 
@@ -394,6 +388,6 @@
         # Create a subnet using admin privilege
         subnet = self.create_subnet(network, enable_dhcp=False)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Delete the subnet
         self.subnets_client.delete_subnet(subnet['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py b/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py
index 518c71b..33e0d2e 100644
--- a/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py
@@ -13,15 +13,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 #
+
 import netaddr
-import random
 
 from oslo_log import log
+
+from tempest.common.utils import net_utils
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 
 from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
@@ -36,25 +37,24 @@
     @classmethod
     def resource_setup(cls):
         super(PortsRbacTest, cls).resource_setup()
-        cls.admin_network = cls.create_network()
+        cls.network = cls.create_network()
 
         # Create a subnet by admin user
         cls.cidr = netaddr.IPNetwork(CONF.network.project_network_cidr)
 
-        cls.admin_subnet = cls.create_subnet(cls.admin_network,
-                                             cidr=cls.cidr,
-                                             mask_bits=24)
-        cls.admin_ip_range = netaddr.IPRange(
-            cls.admin_subnet['allocation_pools'][0]['start'],
-            cls.admin_subnet['allocation_pools'][0]['end'])
+        cls.subnet = cls.create_subnet(cls.network, cidr=cls.cidr,
+                                       mask_bits=24)
+        cls.ip_range = netaddr.IPRange(
+            cls.subnet['allocation_pools'][0]['start'],
+            cls.subnet['allocation_pools'][0]['end'])
 
         # Create a port by admin user
-        body = cls.ports_client.create_port(network_id=cls.admin_network['id'])
-        cls.admin_port = body['port']
-        cls.ports.append(cls.admin_port)
-        ipaddr = cls.admin_port['fixed_ips'][0]['ip_address']
-        cls.admin_port_ip_address = ipaddr
-        cls.admin_port_mac_address = cls.admin_port['mac_address']
+        body = cls.ports_client.create_port(network_id=cls.network['id'])
+        cls.port = body['port']
+        cls.ports.append(cls.port)
+        ipaddr = cls.port['fixed_ips'][0]['ip_address']
+        cls.port_ip_address = ipaddr
+        cls.port_mac_address = cls.port['mac_address']
 
     def _create_port(self, **post_body):
 
@@ -73,8 +73,8 @@
     @decorators.idempotent_id('0ec8c551-625c-4864-8a52-85baa7c40f22')
     def test_create_port(self):
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        post_body = {'network_id': self.admin_network['id']}
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        post_body = {'network_id': self.network['id']}
         self._create_port(**post_body)
 
     @rbac_rule_validation.action(service="neutron",
@@ -82,26 +82,30 @@
     @decorators.idempotent_id('a54bd6b8-a7eb-4101-bfe8-093930b0d660')
     def test_create_port_binding_host_id(self):
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:host_id': "rbac_test_host"}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_port(**post_body)
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="create_port:fixed_ips")
     @decorators.idempotent_id('2551e10d-006a-413c-925a-8c6f834c09ac')
     def test_create_port_fixed_ips(self):
-        # Pick an ip address within the allocation_pools range
-        ip_address = random.choice(list(self.admin_ip_range))
 
-        fixed_ips = [{'ip_address': ip_address},
-                     {'subnet_id': self.admin_subnet['id']}]
+        # Pick an unused ip address.
+        ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
+                                                    self.subnets_client,
+                                                    self.network['id'],
+                                                    self.subnet['id'],
+                                                    1)
+        fixed_ips = [{'ip_address': ip_list[0]},
+                     {'subnet_id': self.subnet['id']}]
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'fixed_ips': fixed_ips}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_port(**post_body)
 
     @rbac_rule_validation.action(service="neutron",
@@ -109,10 +113,10 @@
     @decorators.idempotent_id('aee6d0be-a7f3-452f-aefc-796b4eb9c9a8')
     def test_create_port_mac_address(self):
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'mac_address': data_utils.rand_mac_address()}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_port(**post_body)
 
     @rbac_rule_validation.action(service="neutron",
@@ -122,10 +126,10 @@
 
         binding_profile = {"foo": "1"}
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:profile': binding_profile}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_port(**post_body)
 
     @rbac_rule_validation.action(service="neutron",
@@ -134,29 +138,22 @@
     def test_create_port_allowed_address_pairs(self):
 
         # Create port with allowed address pair attribute
-        allowed_address_pairs = [{'ip_address': self.admin_port_ip_address,
-                                  'mac_address': self.admin_port_mac_address}]
+        allowed_address_pairs = [{'ip_address': self.port_ip_address,
+                                  'mac_address': self.port_mac_address}]
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'allowed_address_pairs': allowed_address_pairs}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_port(**post_body)
 
-    @rbac_rule_validation.action(service="neutron", rule="get_port")
+    @rbac_rule_validation.action(service="neutron",
+                                 rule="get_port",
+                                 expected_error_code=404)
     @decorators.idempotent_id('a9d41cb8-78a2-4b97-985c-44e4064416f4')
     def test_show_port(self):
-
-        try:
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-
-            self.ports_client.show_port(self.admin_port['id'])
-
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.ports_client.show_port(self.port['id'])
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="get_port:binding:vif_type")
@@ -166,16 +163,14 @@
         # Verify specific fields of a port
         fields = ['binding:vif_type']
 
-        try:
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            self.ports_client.show_port(self.admin_port['id'],
-                                        fields=fields)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
 
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        retrieved_port = self.ports_client.show_port(
+            self.port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="get_port:binding:vif_details")
@@ -185,16 +180,14 @@
         # Verify specific fields of a port
         fields = ['binding:vif_details']
 
-        try:
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            self.ports_client.show_port(self.admin_port['id'],
-                                        fields=fields)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
 
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        retrieved_port = self.ports_client.show_port(
+            self.port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="get_port:binding:host_id")
@@ -203,20 +196,18 @@
 
         # Verify specific fields of a port
         fields = ['binding:host_id']
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:host_id': data_utils.rand_name('host-id')}
         port = self._create_port(**post_body)
 
-        try:
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            self.ports_client.show_port(port['id'],
-                                        fields=fields)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
 
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        retrieved_port = self.ports_client.show_port(
+            port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="get_port:binding:profile")
@@ -226,38 +217,35 @@
         # Verify specific fields of a port
         fields = ['binding:profile']
         binding_profile = {"foo": "1"}
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:profile': binding_profile}
         port = self._create_port(**post_body)
 
-        try:
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            self.ports_client.show_port(port['id'],
-                                        fields=fields)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
 
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        retrieved_port = self.ports_client.show_port(
+            port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="update_port")
     @decorators.idempotent_id('afa80981-3c59-42fd-9531-3bcb2cd03711')
     def test_update_port(self):
 
-        port = self.create_port(self.admin_network)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.ports_client.update_port(port['id'],
-                                      admin_state_up=False)
+        port = self.create_port(self.network)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.ports_client.update_port(port['id'], admin_state_up=False)
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="update_port:mac_address")
     @decorators.idempotent_id('507140c8-7b14-4d63-b627-2103691d887e')
     def test_update_port_mac_address(self):
 
-        port = self.create_port(self.admin_network)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        port = self.create_port(self.network)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.ports_client.update_port(
             port['id'],
             mac_address=data_utils.rand_mac_address())
@@ -267,13 +255,19 @@
     @decorators.idempotent_id('c091c825-532b-4c6f-a14f-affd3259c1c3')
     def test_update_port_fixed_ips(self):
 
-        # Pick an ip address within the allocation_pools range
-        ip_address = random.choice(list(self.admin_ip_range))
-        fixed_ips = [{'ip_address': ip_address}]
-        post_body = {'network_id': self.admin_network['id']}
+        # Pick an ip address within the allocation_pools range.
+        post_body = {'network_id': self.network['id']}
         port = self._create_port(**post_body)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        # Pick an unused ip address.
+        ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
+                                                    self.subnets_client,
+                                                    self.network['id'],
+                                                    self.subnet['id'],
+                                                    1)
+        fixed_ips = [{'ip_address': ip_list[0]}]
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.ports_client.update_port(port['id'],
                                       fixed_ips=fixed_ips)
 
@@ -282,8 +276,8 @@
     @decorators.idempotent_id('795541af-6652-4e35-9581-fd58224f7545')
     def test_update_port_security_enabled(self):
 
-        port = self.create_port(self.admin_network)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        port = self.create_port(self.network)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.ports_client.update_port(port['id'],
                                       security_groups=[])
 
@@ -292,14 +286,14 @@
     @decorators.idempotent_id('24206a72-0d90-4712-918c-5c9a1ebef64d')
     def test_update_port_binding_host_id(self):
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:host_id': 'rbac_test_host'}
         port = self._create_port(**post_body)
 
         updated_body = {'port_id': port['id'],
                         'binding:host_id': 'rbac_test_host_updated'}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.ports_client.update_port(**updated_body)
 
     @rbac_rule_validation.action(service="neutron",
@@ -308,7 +302,7 @@
     def test_update_port_binding_profile(self):
 
         binding_profile = {"foo": "1"}
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:profile': binding_profile}
 
         port = self._create_port(**post_body)
@@ -317,7 +311,7 @@
         updated_body = {'port_id': port['id'],
                         'binding:profile': new_binding_profile}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.ports_client.update_port(**updated_body)
 
     @rbac_rule_validation.action(service="neutron",
@@ -325,29 +319,28 @@
     @decorators.idempotent_id('729c2151-bb49-4f4f-9d58-3ed8819b7582')
     def test_update_port_allowed_address_pairs(self):
 
-        ip_address = random.choice(list(self.admin_ip_range))
+        # Pick an unused ip address.
+        ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
+                                                    self.subnets_client,
+                                                    self.network['id'],
+                                                    self.subnet['id'],
+                                                    1)
         # Update allowed address pair attribute of port
-        address_pairs = [{'ip_address': ip_address,
+        address_pairs = [{'ip_address': ip_list[0],
                           'mac_address': data_utils.rand_mac_address()}]
-        post_body = {'network_id': self.admin_network['id']}
+        post_body = {'network_id': self.network['id']}
         port = self._create_port(**post_body)
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.ports_client.update_port(port['id'],
                                       allowed_address_pairs=address_pairs)
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_port")
+                                 rule="delete_port",
+                                 expected_error_code=404)
     @decorators.idempotent_id('1cf8e582-bc09-46cb-b32a-82bf991ad56f')
     def test_delete_port(self):
 
-        try:
-            port = self._create_port(network_id=self.admin_network['id'])
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            self.ports_client.delete_port(port['id'])
-
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        port = self._create_port(network_id=self.network['id'])
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.ports_client.delete_port(port['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py b/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py
index a227e5c..5ea1180 100644
--- a/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py
@@ -14,17 +14,16 @@
 #    under the License.
 
 import netaddr
-import random
 
 from oslo_log import log
+
+from tempest.common.utils import net_utils
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 from tempest import test
 
-from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.network import rbac_base as base
 
@@ -45,12 +44,12 @@
         super(RouterRbacTest, cls).resource_setup()
         post_body = {}
         post_body['router:external'] = True
-        cls.admin_network = cls.create_network(**post_body)
-        cls.admin_subnet = cls.create_subnet(cls.admin_network)
-        cls.admin_ip_range = netaddr.IPRange(
-            cls.admin_subnet['allocation_pools'][0]['start'],
-            cls.admin_subnet['allocation_pools'][0]['end'])
-        cls.admin_router = cls.create_router()
+        cls.network = cls.create_network(**post_body)
+        cls.subnet = cls.create_subnet(cls.network)
+        cls.ip_range = netaddr.IPRange(
+            cls.subnet['allocation_pools'][0]['start'],
+            cls.subnet['allocation_pools'][0]['end'])
+        cls.router = cls.create_router()
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="create_router")
@@ -60,7 +59,7 @@
 
         RBAC test for the neutron create_router policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         router = self.routers_client.create_router()
         self.addCleanup(self.routers_client.delete_router,
                         router['router']['id'])
@@ -76,10 +75,10 @@
         create_router:external_gateway_info:enable_snat policy
         """
         name = data_utils.rand_name('snat-router')
-        external_gateway_info = {'network_id': self.admin_network['id'],
+        external_gateway_info = {'network_id': self.network['id'],
                                  'enable_snat': True}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         router = self.routers_client.create_router(
             name=name, external_gateway_info=external_gateway_info)
         self.addCleanup(self.routers_client.delete_router,
@@ -96,36 +95,36 @@
         create_router:external_gateway_info:external_fixed_ips policy
         """
         name = data_utils.rand_name('snat-router')
-        # Pick an ip address within the allocation_pools range
-        ip_address = random.choice(list(self.admin_ip_range))
-        external_fixed_ips = {'subnet_id': self.admin_subnet['id'],
-                              'ip_address': ip_address}
 
-        external_gateway_info = {'network_id': self.admin_network['id'],
+        # Pick an unused IP address.
+        ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
+                                                    self.subnets_client,
+                                                    self.network['id'],
+                                                    self.subnet['id'],
+                                                    1)
+        external_fixed_ips = {'subnet_id': self.subnet['id'],
+                              'ip_address': ip_list[0]}
+        external_gateway_info = {'network_id': self.network['id'],
                                  'enable_snat': False,
                                  'external_fixed_ips': [external_fixed_ips]}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         router = self.routers_client.create_router(
             name=name, external_gateway_info=external_gateway_info)
         self.addCleanup(self.routers_client.delete_router,
                         router['router']['id'])
 
-    @rbac_rule_validation.action(service="neutron", rule="get_router")
+    @rbac_rule_validation.action(service="neutron",
+                                 rule="get_router",
+                                 expected_error_code=404)
     @decorators.idempotent_id('bfbdbcff-f115-4d3e-8cd5-6ada33fd0e21')
     def test_show_router(self):
         """Get Router
 
         RBAC test for the neutron get_router policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.routers_client.show_router(self.admin_router['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.routers_client.show_router(self.router['id'])
 
     @rbac_rule_validation.action(
         service="neutron", rule="update_router")
@@ -136,8 +135,8 @@
         RBAC test for the neutron update_router policy
         """
         new_name = data_utils.rand_name('new-router-name')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.routers_client.update_router(self.admin_router['id'],
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.routers_client.update_router(self.router['id'],
                                           name=new_name)
 
     @rbac_rule_validation.action(
@@ -149,8 +148,8 @@
         RBAC test for the neutron
         update_router:external_gateway_info policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.routers_client.update_router(self.admin_router['id'],
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.routers_client.update_router(self.router['id'],
                                           external_gateway_info={})
 
     @rbac_rule_validation.action(
@@ -163,10 +162,14 @@
         RBAC test for the neutron
         update_router:external_gateway_info:network_id policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.routers_client.update_router(
-            self.admin_router['id'],
-            external_gateway_info={'network_id': self.admin_network['id']})
+            self.router['id'],
+            external_gateway_info={'network_id': self.network['id']})
+        self.addCleanup(
+            self.routers_client.update_router,
+            self.router['id'],
+            external_gateway_info=None)
 
     @rbac_rule_validation.action(
         service="neutron",
@@ -178,11 +181,15 @@
         RBAC test for the neutron
         update_router:external_gateway_info:enable_snat policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.routers_client.update_router(
-            self.admin_router['id'],
-            external_gateway_info={'network_id': self.admin_network['id'],
+            self.router['id'],
+            external_gateway_info={'network_id': self.network['id'],
                                    'enable_snat': True})
+        self.addCleanup(
+            self.routers_client.update_router,
+            self.router['id'],
+            external_gateway_info=None)
 
     @rbac_rule_validation.action(
         service="neutron",
@@ -194,24 +201,29 @@
         RBAC test for the neutron
         update_router:external_gateway_info:external_fixed_ips policy
         """
-        # Pick an ip address within the allocation_pools range
-        ip_address = random.choice(list(self.admin_ip_range))
-        external_fixed_ips = {'subnet_id': self.admin_subnet['id'],
-                              'ip_address': ip_address}
-        external_gateway_info = {'network_id': self.admin_network['id'],
+        # Pick an unused IP address.
+        ip_list = net_utils.get_unused_ip_addresses(self.ports_client,
+                                                    self.subnets_client,
+                                                    self.network['id'],
+                                                    self.subnet['id'],
+                                                    1)
+        external_fixed_ips = {'subnet_id': self.subnet['id'],
+                              'ip_address': ip_list[0]}
+        external_gateway_info = {'network_id': self.network['id'],
                                  'external_fixed_ips': [external_fixed_ips]}
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.routers_client.update_router(
-            self.admin_router['id'],
+            self.router['id'],
             external_gateway_info=external_gateway_info)
         self.addCleanup(
             self.routers_client.update_router,
-            self.admin_router['id'],
+            self.router['id'],
             external_gateway_info=None)
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_router")
+                                 rule="delete_router",
+                                 expected_error_code=404)
     @decorators.idempotent_id('c0634dd5-0467-48f7-a4ae-1014d8edb2a7')
     def test_delete_router(self):
         """Delete Router
@@ -219,17 +231,12 @@
         RBAC test for the neutron delete_router policy
         """
         router = self.create_router()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.routers_client.delete_router(router['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.routers_client.delete_router(router['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="add_router_interface")
+                                 rule="add_router_interface",
+                                 expected_error_code=404)
     @decorators.idempotent_id('a0627778-d68d-4913-881b-e345360cca19')
     def test_add_router_interfaces(self):
         """Add Router Interface
@@ -240,23 +247,18 @@
         subnet = self.create_subnet(network)
         router = self.create_router()
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.routers_client.add_router_interface(
-                router['id'], subnet_id=subnet['id'])
-            self.addCleanup(
-                test_utils.call_and_ignore_notfound_exc,
-                self.routers_client.remove_router_interface,
-                router['id'],
-                subnet_id=subnet['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.routers_client.add_router_interface(
+            router['id'], subnet_id=subnet['id'])
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.routers_client.remove_router_interface,
+            router['id'],
+            subnet_id=subnet['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="remove_router_interface")
+                                 rule="remove_router_interface",
+                                 expected_error_code=404)
     @decorators.idempotent_id('ff2593a4-2bff-4c27-97d3-dd3702b27dfb')
     def test_remove_router_interfaces(self):
         """Remove Router Interface
@@ -275,13 +277,7 @@
                         router['id'],
                         subnet_id=subnet['id'])
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.routers_client.remove_router_interface(
-                router['id'],
-                subnet_id=subnet['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.routers_client.remove_router_interface(
+            router['id'],
+            subnet_id=subnet['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py b/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py
index cf76836..e04600e 100644
--- a/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py
@@ -18,9 +18,7 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 
-from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.network import rbac_base as base
 
@@ -76,64 +74,51 @@
     @decorators.idempotent_id('db7003ce-5717-4e5b-afc7-befa35e8c67f')
     def test_create_security_group(self):
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_security_group()
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_security_group")
+                                 rule="get_security_group",
+                                 expected_error_code=404)
     @decorators.idempotent_id('56335e77-aef2-4b54-86c7-7f772034b585')
     def test_show_security_groups(self):
 
-        try:
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            self.security_groups_client.show_security_group(
-                self.secgroup['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.security_groups_client.show_security_group(
+            self.secgroup['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_security_group")
+                                 rule="delete_security_group",
+                                 expected_error_code=404)
     @decorators.idempotent_id('0b1330fd-dd28-40f3-ad73-966052e4b3de')
     def test_delete_security_group(self):
 
         # Create a security group
         secgroup_id = self._create_security_group()['id']
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.security_groups_client.delete_security_group(secgroup_id)
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.security_groups_client.delete_security_group(secgroup_id)
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="update_security_group")
+                                 rule="update_security_group",
+                                 expected_error_code=404)
     @decorators.idempotent_id('56c5e4dc-f8aa-11e6-bc64-92361f002671')
     def test_update_security_group(self):
 
         # Create a security group
         secgroup_id = self._create_security_group()['id']
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.security_groups_client.update_security_group(
-                secgroup_id,
-                description="test description")
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.security_groups_client.update_security_group(
+            secgroup_id,
+            description="test description")
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="get_security_groups")
     @decorators.idempotent_id('fbaf8d96-ed3e-49af-b24c-5fb44f05bbb7')
     def test_list_security_groups(self):
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.security_groups_client.list_security_groups()
 
     @rbac_rule_validation.action(service="neutron",
@@ -141,47 +126,35 @@
     @decorators.idempotent_id('953d78df-00cd-416f-9cbd-b7cb4ea65772')
     def test_create_security_group_rule(self):
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_security_group_rule()
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_security_group_rule")
+                                 rule="delete_security_group_rule",
+                                 expected_error_code=404)
     @decorators.idempotent_id('2262539e-b7d9-438c-acf9-a5ce0613be28')
     def test_delete_security_group_rule(self):
 
         sec_group_rule = self._create_security_group_rule()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.security_group_rules_client.delete_security_group_rule(
-                sec_group_rule['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.security_group_rules_client.delete_security_group_rule(
+            sec_group_rule['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_security_group_rule")
+                                 rule="get_security_group_rule",
+                                 expected_error_code=404)
     @decorators.idempotent_id('84b4038c-261e-4a94-90d5-c885739ab0d5')
     def test_show_security_group_rule(self):
 
         sec_group_rule = self._create_security_group_rule()
-
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.security_group_rules_client.show_security_group_rule(
-                sec_group_rule['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.security_group_rules_client.show_security_group_rule(
+            sec_group_rule['id'])
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="get_security_group_rules")
     @decorators.idempotent_id('05739ab6-fa35-11e6-bc64-92361f002671')
     def test_list_security_group_rules(self):
 
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.security_group_rules_client.list_security_group_rules()
diff --git a/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py b/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py
index 35ad335..e7682df 100644
--- a/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py
@@ -18,10 +18,8 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest.lib import exceptions
 from tempest import test
 
-from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.network import rbac_base as base
 
@@ -64,7 +62,7 @@
 
         RBAC test for the neutron create_subnetpool policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_subnetpool()
 
     @rbac_rule_validation.action(service="neutron",
@@ -75,11 +73,12 @@
 
         RBAC test for the neutron create_subnetpool:shared policy
         """
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_subnetpool(shared=True)
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_subnetpool")
+                                 rule="get_subnetpool",
+                                 expected_error_code=404)
     @decorators.idempotent_id('4f5aee26-0507-4b6d-b44c-3128a25094d2')
     def test_show_subnetpool(self):
         """Show subnetpool.
@@ -87,14 +86,8 @@
         RBAC test for the neutron get_subnetpool policy
         """
         subnetpool = self._create_subnetpool()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.subnetpools_client.show_subnetpool(subnetpool['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.subnetpools_client.show_subnetpool(subnetpool['id'])
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="update_subnetpool")
@@ -105,12 +98,13 @@
         RBAC test for the neutron update_subnetpool policy
         """
         subnetpool = self._create_subnetpool()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.subnetpools_client.update_subnetpool(subnetpool['id'],
                                                   min_prefixlen=24)
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="delete_subnetpool")
+                                 rule="delete_subnetpool",
+                                 expected_error_code=404)
     @decorators.idempotent_id('50f5944e-43e5-457b-ab50-fb48a73f0d3e')
     def test_delete_subnetpool(self):
         """Delete subnetpool.
@@ -118,11 +112,5 @@
         RBAC test for the neutron delete_subnetpool policy
         """
         subnetpool = self._create_subnetpool()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        try:
-            self.subnetpools_client.delete_subnetpool(subnetpool['id'])
-        except exceptions.NotFound as e:
-            LOG.info("NotFound exception caught. Exception is thrown when "
-                     "role doesn't have access to the endpoint."
-                     "This is irregular and should be fixed.")
-            raise rbac_exceptions.RbacActionFailed(e)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.subnetpools_client.delete_subnetpool(subnetpool['id'])
diff --git a/patrole_tempest_plugin/tests/api/orchestration/__init__.py b/patrole_tempest_plugin/tests/api/orchestration/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/patrole_tempest_plugin/tests/api/orchestration/__init__.py
+++ /dev/null
diff --git a/patrole_tempest_plugin/tests/api/orchestration/rbac_base.py b/patrole_tempest_plugin/tests/api/orchestration/rbac_base.py
deleted file mode 100644
index 2cc7978..0000000
--- a/patrole_tempest_plugin/tests/api/orchestration/rbac_base.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.api.orchestration import base as heat_base
-from tempest import config
-
-from patrole_tempest_plugin.rbac_utils import rbac_utils
-
-CONF = config.CONF
-
-
-class BaseOrchestrationRbacTest(heat_base.BaseOrchestrationTest):
-
-    credentials = ['admin', 'primary']
-
-    @classmethod
-    def skip_checks(cls):
-        super(BaseOrchestrationRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
-            raise cls.skipException(
-                "%s skipped as RBAC Flag not enabled" % cls.__name__)
-
-    @classmethod
-    def setup_clients(cls):
-        super(BaseOrchestrationRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
-        cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
diff --git a/patrole_tempest_plugin/tests/api/orchestration/test_soft_config_rbac.py b/patrole_tempest_plugin/tests/api/orchestration/test_soft_config_rbac.py
deleted file mode 100644
index fa3840c..0000000
--- a/patrole_tempest_plugin/tests/api/orchestration/test_soft_config_rbac.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.lib.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
-from tempest.lib import decorators
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.orchestration import rbac_base
-
-
-class TestRbacSoftwareConfig(rbac_base.BaseOrchestrationRbacTest):
-
-    def setUp(self):
-        super(TestRbacSoftwareConfig, self).setUp()
-        self.config = self._config_create('a')
-        self._deployment_create(self.config['id'])
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_configs:show")
-    @decorators.idempotent_id('b2e7c98c-e17b-4f37-82f3-5d21eff86e79')
-    def test_get_software_config(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.show_software_config(self.config['id'])
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_deployments:metadata")
-    @decorators.idempotent_id('defa34ab-9d1f-4b14-8613-34e964c0c478')
-    def test_get_deployment_metadata(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.show_software_deployment_metadata(self.server_id)
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_deployments:index")
-    @decorators.idempotent_id('2a4dcb91-1803-4749-9cb7-5b69ba668b18')
-    def test_get_deployment_list(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.list_software_deployments()
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_deployments:show")
-    @decorators.idempotent_id('d4e627bc-88a3-4189-8092-151f22ed989d')
-    def test_software_show_deployment(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.show_software_deployment(self.deployment_id)
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_deployments:update")
-    @decorators.idempotent_id('90e8958c-6fa7-4515-b6d7-6d6952979f8c')
-    def test_software_deployment_update(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        new_action = data_utils.rand_name('ACTION')
-        new_status = data_utils.rand_name('STATUS')
-        new_reason = data_utils.rand_name('REASON')
-        self.client.update_software_deploy(self.deployment_id,
-                                           self.server_id,
-                                           self.config['id'],
-                                           new_action, new_status,
-                                           self.input_values,
-                                           self.output_values,
-                                           new_reason,
-                                           self.signal_transport)
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_deployments:create")
-    @decorators.idempotent_id('9175fe7b-4210-4c1d-acbb-954998a9fd77')
-    def test_software_deployment_create(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._deployment_create(self.config['id'])
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_deployments:delete")
-    @decorators.idempotent_id('20f4683d-7316-4d88-a6ea-1ee6013da908')
-    def test_software_deployment_delete(self):
-        deploy_id = self._deployment_create(self.config['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.delete_software_deploy(deploy_id)
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_configs:create")
-    @decorators.idempotent_id('c8fb1c73-fcb6-46c2-9510-8ef0083c9620')
-    def test_config_create(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._config_create('e')
-
-    @rbac_rule_validation.action(service="heat",
-                                 rule="software_configs:delete")
-    @decorators.idempotent_id('f4f784ea-9878-4306-bc5f-041ba5307ce5')
-    def test_config_delete(self):
-        configuration = self._config_create('d')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.delete_software_config(configuration['id'])
-
-    def _config_create(self, suffix):
-        configuration = {'group': 'script',
-                         'inputs': [],
-                         'outputs': [],
-                         'options': {}}
-        configuration['name'] = 'heat_soft_config_%s' % suffix
-        configuration['config'] = '#!/bin/bash echo init-%s' % suffix
-        api_config = self.client.create_software_config(**configuration)
-        self.addCleanup(
-            test_utils.call_and_ignore_notfound_exc,
-            self.client.delete_software_config,
-            api_config['software_config']['id'])
-        configuration['id'] = api_config['software_config']['id']
-        return configuration
-
-    def _deployment_create(self, config_id):
-        self.server_id = data_utils.rand_name('dummy-server')
-        self.action = 'ACTION_0'
-        self.status = 'STATUS_0'
-        self.input_values = {}
-        self.output_values = []
-        self.status_reason = 'REASON_0'
-        self.signal_transport = 'NO_SIGNAL'
-        self.deployment = self.client.create_software_deploy(
-            self.server_id, config_id, self.action, self.status,
-            self.input_values, self.output_values, self.status_reason,
-            self.signal_transport)
-        self.addCleanup(
-            test_utils.call_and_ignore_notfound_exc,
-            self.client.delete_software_deploy,
-            self.deployment['software_deployment']['id'])
-        self.deployment_id = self.deployment['software_deployment']['id']
-        return self.deployment_id
diff --git a/patrole_tempest_plugin/tests/api/volume/admin/__init__.py b/patrole_tempest_plugin/tests/api/volume/admin/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/patrole_tempest_plugin/tests/api/volume/admin/__init__.py
+++ /dev/null
diff --git a/patrole_tempest_plugin/tests/api/volume/admin/test_volumes_backup_admin_rbac.py b/patrole_tempest_plugin/tests/api/volume/admin/test_volumes_backup_admin_rbac.py
deleted file mode 100644
index a89aa87..0000000
--- a/patrole_tempest_plugin/tests/api/volume/admin/test_volumes_backup_admin_rbac.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from oslo_serialization import base64
-from oslo_serialization import jsonutils as json
-from tempest import config
-from tempest.lib.common.utils import data_utils
-from tempest.lib import decorators
-from tempest import test
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-
-
-class VolumesBackupsAdminRbacTest(rbac_base.BaseVolumeAdminRbacTest):
-
-    @classmethod
-    def skip_checks(cls):
-        super(VolumesBackupsAdminRbacTest, cls).skip_checks()
-        if not CONF.volume_feature_enabled.backup:
-            raise cls.skipException("Cinder backup feature disabled")
-
-    @classmethod
-    def resource_setup(cls):
-        super(VolumesBackupsAdminRbacTest, cls).resource_setup()
-        cls.volume = cls.create_volume()
-
-    def _decode_url(self, backup_url):
-        return json.loads(base64.decode_as_text(backup_url))
-
-    def _encode_backup(self, backup):
-        retval = json.dumps(backup)
-        return base64.encode_as_text(retval)
-
-    def _modify_backup_url(self, backup_url, changes):
-        backup = self._decode_url(backup_url)
-        backup.update(changes)
-        return self._encode_backup(backup)
-
-    @test.attr(type='slow')
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="backup:backup-export")
-    @decorators.idempotent_id('e984ec8d-e8eb-485c-98bc-f1856020303c')
-    def test_volume_backup_export(self):
-        # Create a temp backup
-        backup = self.create_backup(volume_id=self.volume['id'])
-        # Export Backup
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.backups_client.export_backup(
-            backup['id'])['backup-record']
-
-    @test.attr(type='slow')
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="backup:backup-import")
-    @decorators.idempotent_id('1e70f039-4556-44cc-9cc1-edf2b7ed648b')
-    def test_volume_backup_import(self):
-        # Create a temp backup
-        backup = self.create_backup(volume_id=self.volume['id'])
-        # Export a temp backup
-        export_backup = self.backups_client.export_backup(
-            backup['id'])['backup-record']
-        new_id = data_utils.rand_uuid()
-        new_url = self._modify_backup_url(
-            export_backup['backup_url'], {'id': new_id})
-        # Import the temp backup
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        import_backup = self.backups_client.import_backup(
-            backup_service=export_backup['backup_service'],
-            backup_url=new_url)['backup']
-        self.addCleanup(self.backups_client.delete_backup, import_backup['id'])
-
-
-class VolumesBackupsAdminV3RbacTest(VolumesBackupsAdminRbacTest):
-    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/rbac_base.py b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
index 2a14b19..ccadad1 100644
--- a/patrole_tempest_plugin/tests/api/volume/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
@@ -13,6 +13,8 @@
 
 from tempest.api.volume import base as vol_base
 from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 
 from patrole_tempest_plugin.rbac_utils import rbac_utils
 
@@ -26,39 +28,54 @@
     @classmethod
     def skip_checks(cls):
         super(BaseVolumeRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
+        if not CONF.rbac.enable_rbac:
             raise cls.skipException(
-                "%s skipped as RBAC Flag not enabled" % cls.__name__)
+                "%s skipped as RBAC testing not enabled" % cls.__name__)
 
     @classmethod
     def setup_clients(cls):
         super(BaseVolumeRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
+        cls.auth_provider = cls.os_primary.auth_provider
+
         cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
+        cls.rbac_utils.switch_role(cls, toggle_rbac_role=False)
 
-
-class BaseVolumeAdminRbacTest(vol_base.BaseVolumeAdminTest):
-
-    credentials = ['admin', 'primary']
-
-    @classmethod
-    def skip_checks(cls):
-        super(BaseVolumeAdminRbacTest, cls).skip_checks()
-        if not CONF.rbac.rbac_flag:
-            raise cls.skipException(
-                "%s skipped as RBAC Flag not enabled" % cls.__name__)
-
-    @classmethod
-    def setup_clients(cls):
-        super(BaseVolumeAdminRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
-        cls.rbac_utils = rbac_utils()
-        cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
         version_checker = {
-            1: [cls.os.volume_hosts_client, cls.os.volume_types_client],
-            2: [cls.os.volume_hosts_v2_client, cls.os.volume_types_v2_client],
-            3: [cls.os.volume_hosts_v2_client, cls.os.volume_types_v2_client]
+            1: [cls.os_primary.volume_hosts_client,
+                cls.os_primary.volume_types_client],
+            2: [cls.os_primary.volume_hosts_v2_client,
+                cls.os_primary.volume_types_v2_client],
+            3: [cls.os_primary.volume_hosts_v2_client,
+                cls.os_primary.volume_types_v2_client]
         }
         cls.volume_hosts_client, cls.volume_types_client = \
             version_checker[cls._api_version]
+
+    @classmethod
+    def resource_setup(cls):
+        super(BaseVolumeRbacTest, cls).resource_setup()
+        cls.volume_types = []
+
+    @classmethod
+    def resource_cleanup(cls):
+        super(BaseVolumeRbacTest, cls).resource_cleanup()
+        cls.clear_volume_types()
+
+    @classmethod
+    def create_volume_type(cls, name=None, **kwargs):
+        """Create a test volume-type"""
+        name = name or data_utils.rand_name(cls.__name__ + '-volume-type')
+        volume_type = cls.volume_types_client.create_volume_type(
+            name=name, **kwargs)['volume_type']
+        cls.volume_types.append(volume_type['id'])
+        return volume_type
+
+    @classmethod
+    def clear_volume_types(cls):
+        for vol_type in cls.volume_types:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.volume_types_client.delete_volume_type, vol_type)
+
+        for vol_type in cls.volume_types:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.volume_types_client.wait_for_resource_deletion, vol_type)
diff --git a/patrole_tempest_plugin/tests/api/volume/test_availability_zone_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_availability_zone_rbac.py
deleted file mode 100644
index 711c7d6..0000000
--- a/patrole_tempest_plugin/tests/api/volume/test_availability_zone_rbac.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest import config
-from tempest.lib import decorators
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-
-
-class AvailabilityZoneRbacTest(rbac_base.BaseVolumeRbacTest):
-
-    @classmethod
-    def setup_clients(cls):
-        super(AvailabilityZoneRbacTest, cls).setup_clients()
-        cls.client = cls.availability_zone_client
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:availability_zone_list")
-    @decorators.idempotent_id('8cfd920c-4b6c-402d-b6e2-ede86bedc702')
-    def test_get_availability_zone_list(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.list_availability_zones()
diff --git a/patrole_tempest_plugin/tests/api/volume/test_capabilities_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_capabilities_rbac.py
new file mode 100644
index 0000000..9d76ef3
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_capabilities_rbac.py
@@ -0,0 +1,48 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+
+class CapabilitiesRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(CapabilitiesRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('capabilities', 'volume'):
+            msg = "%s skipped as capabilities not enabled." % cls.__name__
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(CapabilitiesRbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.volume_capabilities_v2_client
+        cls.hosts_client = cls.os_primary.volume_hosts_v2_client
+
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume_extension:capabilities")
+    @decorators.idempotent_id('40928b74-2141-11e7-93ae-92361f002671')
+    def test_show_back_end_capabilities(self):
+        host = self.hosts_client.list_hosts()['hosts'][0]['host_name']
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_backend_capabilities(host)
+
+
+class CapabilitiesV3RbacTest(CapabilitiesRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_encryption_types_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_encryption_types_rbac.py
new file mode 100644
index 0000000..d829591
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_encryption_types_rbac.py
@@ -0,0 +1,86 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+
+class EncryptionTypesRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(EncryptionTypesRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('encryption', 'volume'):
+            msg = "%s skipped as encryption not enabled." % cls.__name__
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(EncryptionTypesRbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.encryption_types_v2_client
+
+    def _create_volume_type_encryption(self):
+        vol_type_id = self.create_volume_type()['id']
+        self.client.create_encryption_type(
+            vol_type_id,
+            provider="nova.volume.encryptors.luks.LuksEncryptor",
+            control_location="front-end")['encryption']
+        return vol_type_id
+
+    @decorators.idempotent_id('ffd94ce5-c24b-4b6c-84c9-c5aad8c3010c')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_type_encryption")
+    def test_create_volume_type_encryption(self):
+        vol_type_id = self.create_volume_type()['id']
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.create_encryption_type(
+            vol_type_id,
+            provider="nova.volume.encryptors.luks.LuksEncryptor",
+            control_location="front-end")['encryption']
+
+    @decorators.idempotent_id('6599e72e-acef-4c0d-a9b2-463fca30d1da')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_type_encryption")
+    def test_delete_volume_type_encryption(self):
+        vol_type_id = self._create_volume_type_encryption()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_encryption_type(vol_type_id)
+
+    @decorators.idempotent_id('42da9fec-32fd-4dca-9242-8a53b2fed25a')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_type_encryption")
+    def test_update_volume_type_encryption(self):
+        vol_type_id = self._create_volume_type_encryption()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.update_encryption_type(vol_type_id,
+                                           control_location="front-end")
+
+    @decorators.idempotent_id('1381a3dc-248f-4282-b231-c9399018c804')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_type_encryption")
+    def test_show_volume_type_encryption(self):
+        vol_type_id = self._create_volume_type_encryption()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_encryption_type(vol_type_id)
+
+
+class EncryptionTypesV3RbacTest(EncryptionTypesRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_extensions_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_extensions_rbac.py
deleted file mode 100644
index c9c2b63..0000000
--- a/patrole_tempest_plugin/tests/api/volume/test_extensions_rbac.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest import config
-from tempest.lib import decorators
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-
-
-class ExtensionsRbacTest(rbac_base.BaseVolumeRbacTest):
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:list_extensions")
-    @decorators.idempotent_id('7f2dcc41-e850-493f-a400-82db4e2b50c0')
-    def test_list_extensions(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.volumes_extension_client.list_extensions()
-
-
-class ExtensionsV3RbacTest(ExtensionsRbacTest):
-    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/admin/test_qos_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py
similarity index 76%
rename from patrole_tempest_plugin/tests/api/volume/admin/test_qos_rbac.py
rename to patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py
index 29c334f..4638e78 100644
--- a/patrole_tempest_plugin/tests/api/volume/admin/test_qos_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py
@@ -14,38 +14,46 @@
 #    under the License.
 
 from tempest.common import waiters
-from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.volume import rbac_base
 
-CONF = config.CONF
 
-
-class VolumeQOSRbacTest(rbac_base.BaseVolumeAdminRbacTest):
+class VolumeQOSRbacTest(rbac_base.BaseVolumeRbacTest):
     @classmethod
     def setup_clients(cls):
         super(VolumeQOSRbacTest, cls).setup_clients()
-        cls.auth_provider = cls.os.auth_provider
-        cls.client = cls.admin_volume_qos_client
+        cls.auth_provider = cls.os_primary.auth_provider
+        cls.client = cls.os_primary.volume_qos_v2_client
+
+    def _create_test_qos_specs(self, name=None, consumer=None, **kwargs):
+        """Create a test Qos-Specs."""
+        name = name or data_utils.rand_name(self.__class__.__name__ + '-QoS')
+        consumer = consumer or 'front-end'
+        qos_specs = self.client.create_qos(
+            name=name, consumer=consumer, **kwargs)['qos_specs']
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_qos, qos_specs['id'])
+        return qos_specs
 
     @rbac_rule_validation.action(
         service="cinder", rule="volume_extension:qos_specs_manage:create")
     @decorators.idempotent_id('4f9f45f0-b379-4577-a279-cec3e917cbec')
     def test_create_qos_with_consumer(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Create a qos
-        self.create_test_qos_specs()
+        self._create_test_qos_specs()
 
     @rbac_rule_validation.action(
         service="cinder", rule="volume_extension:qos_specs_manage:delete")
     @decorators.idempotent_id('fbc8a77e-6b6d-45ae-bebe-c496eb8f06f7')
     def test_delete_qos_with_consumer(self):
         # Create a qos
-        qos = self.create_test_qos_specs()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        qos = self._create_test_qos_specs()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Delete a qos
         self.client.delete_qos(qos['id'])
 
@@ -54,8 +62,8 @@
     @decorators.idempotent_id('22aff0dd-0343-408d-ae80-e77551956e14')
     def test_get_qos(self):
         # Create a qos
-        qos = self.create_test_qos_specs()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        qos = self._create_test_qos_specs()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Get a qos
         self.client.show_qos(qos['id'])['qos_specs']
 
@@ -63,7 +71,7 @@
                                  rule="volume_extension:qos_specs_manage:read")
     @decorators.idempotent_id('546b8bb1-04a4-4387-9506-a538a7f3cd6a')
     def test_list_qos(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # list all qos
         self.client.list_qos()['qos_specs']
 
@@ -72,8 +80,8 @@
     @decorators.idempotent_id('89b630b7-c170-47c3-ac80-50ed425c2d98')
     def test_set_qos_key(self):
         # Create a qos
-        qos = self.create_test_qos_specs()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        qos = self._create_test_qos_specs()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # set key
         self.client.set_qos_key(qos['id'], iops_bytes='500')['qos_specs']
 
@@ -82,10 +90,10 @@
     @decorators.idempotent_id('6c50c837-de77-4dae-a2ec-30e05c62969c')
     def test_unset_qos_key(self):
         # Create a qos
-        qos = self.create_test_qos_specs()
+        qos = self._create_test_qos_specs()
         # Set key
         self.client.set_qos_key(qos['id'], iops_bytes='500')['qos_specs']
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Unset key
         keys = ['iops_bytes']
         self.client.unset_qos_key(qos['id'], keys)
@@ -98,10 +106,10 @@
     @decorators.idempotent_id('2047b347-8bbe-405e-bf5a-c75a0d7e3930')
     def test_associate_qos(self):
         # Create a qos
-        qos = self.create_test_qos_specs()
+        qos = self._create_test_qos_specs()
         # create a test volume-type
         vol_type = self.create_volume_type()['id']
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # associate the qos-specs with volume-types
         self.client.associate_qos(qos['id'], vol_type)
         self.addCleanup(self.client.disassociate_qos, qos['id'], vol_type)
@@ -111,12 +119,12 @@
     @decorators.idempotent_id('ff1e98f3-d456-40a9-96d4-c7e4a55dcffa')
     def test_get_association_qos(self):
         # create a test volume-type
-        qos = self.create_test_qos_specs()
+        qos = self._create_test_qos_specs()
         vol_type = self.create_volume_type()['id']
         # associate the qos-specs with volume-types
         self.client.associate_qos(qos['id'], vol_type)
         self.addCleanup(self.client.disassociate_qos, qos['id'], vol_type)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # get the association of the qos-specs
         self.client.show_association_qos(qos['id'])
 
@@ -125,13 +133,13 @@
     @decorators.idempotent_id('f12aeca1-0c02-4f33-b805-014171e5b2d4')
     def test_disassociate_qos(self):
         # create a test volume-type
-        qos = self.create_test_qos_specs()
+        qos = self._create_test_qos_specs()
         vol_type = self.create_volume_type()['id']
         # associate the qos-specs with volume-types
         self.client.associate_qos(qos['id'], vol_type)
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.client.disassociate_qos, qos['id'], vol_type)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # disassociate a volume-type with qos-specs
         self.client.disassociate_qos(qos['id'], vol_type)
         operation = 'disassociate'
@@ -142,14 +150,14 @@
         service="cinder", rule="volume_extension:qos_specs_manage:update")
     @decorators.idempotent_id('9f6e664d-a5d9-4e71-b122-73a3086be1b9')
     def test_disassociate_all_qos(self):
-        qos = self.create_test_qos_specs()
+        qos = self._create_test_qos_specs()
         # create a test volume-type
         vol_type = self.create_volume_type()['id']
         # associate the qos-specs with volume-types
         self.client.associate_qos(qos['id'], vol_type)
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.client.disassociate_qos, qos['id'], vol_type)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # disassociate all volume-types from qos-specs
         self.client.disassociate_all_qos(qos['id'])
         operation = 'disassociate-all'
diff --git a/patrole_tempest_plugin/tests/api/volume/test_quota_classes_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_quota_classes_rbac.py
new file mode 100644
index 0000000..44c0d3e
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_quota_classes_rbac.py
@@ -0,0 +1,60 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+
+class QuotaClassesRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(QuotaClassesRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('os-quota-class-sets', 'volume'):
+            msg = ("%s skipped as os-quota-class-sets not enabled."
+                   % cls.__name__)
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(QuotaClassesRbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.quota_classes_client
+        cls.quota_name = data_utils.rand_name(cls.__name__ + '-QuotaClass')
+
+    @decorators.idempotent_id('1a060def-2b43-4534-97f5-5eadbbe8c726')
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume_extension:quota_classes")
+    def test_show_quota_class_set(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_quota_class_set(self.quota_name)['quota_class_set']
+
+    @decorators.idempotent_id('72159478-23a7-4c75-989f-6bac609eca62')
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume_extension:quota_classes")
+    def test_update_quota_class_set(self):
+        quota_class_set = self.client.show_quota_class_set(self.quota_name)[
+            'quota_class_set']
+        quota_class_set.pop('id')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.update_quota_class_set(self.quota_name, **quota_class_set)
+
+
+class QuotaClassesV3RbacTest(QuotaClassesRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_scheduler_stats_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_scheduler_stats_rbac.py
new file mode 100644
index 0000000..5a36709
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_scheduler_stats_rbac.py
@@ -0,0 +1,47 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+
+class SchedulerStatsRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(SchedulerStatsRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('scheduler-stats', 'volume'):
+            msg = "%s skipped as scheduler-stats not enabled." % cls.__name__
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(SchedulerStatsRbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.volume_scheduler_stats_v2_client
+
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="scheduler_extension:scheduler_stats:get_pools")
+    @decorators.idempotent_id('5f800441-4d30-48ec-9e5b-0d55bc86acbb')
+    def test_list_back_end_storage_pools(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_pools()
+
+
+class SchedulerStatsV3RbacTest(SchedulerStatsRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py
index 7b5064a..5a4e246 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_snapshots_actions_rbac.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest import config
 from tempest.lib import decorators
 
@@ -22,7 +20,6 @@
 from patrole_tempest_plugin.tests.api.volume import rbac_base
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class SnapshotsActionsRbacTest(rbac_base.BaseVolumeRbacTest):
@@ -36,14 +33,12 @@
     @classmethod
     def setup_clients(cls):
         super(SnapshotsActionsRbacTest, cls).setup_clients()
-        cls.client = cls.os.snapshots_client
+        cls.client = cls.snapshots_client
 
     @classmethod
     def resource_setup(cls):
         super(SnapshotsActionsRbacTest, cls).resource_setup()
-        # Create a volume
         cls.volume = cls.create_volume()
-        # Create a snapshot
         cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id'])
         cls.snapshot_id = cls.snapshot['id']
 
@@ -52,23 +47,18 @@
         rule="volume_extension:snapshot_admin_actions:reset_status")
     @decorators.idempotent_id('ea430145-34ef-408d-b678-95d5ae5f46eb')
     def test_reset_snapshot_status(self):
-        # Reset snapshot status to error
         status = 'error'
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.\
-            reset_snapshot_status(self.snapshot['id'], status)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.reset_snapshot_status(self.snapshot['id'], status)
 
     @rbac_rule_validation.action(
         service="cinder",
-        rule="volume_extension:volume_admin_actions:force_delete")
+        rule="volume_extension:snapshot_admin_actions:force_delete")
     @decorators.idempotent_id('a8b0f7d8-4c00-4645-b8d5-33ab4eecc6cb')
     def test_snapshot_force_delete(self):
-        # Test force delete of snapshot
-        # Create snapshot,
-        # and force delete temp snapshot
         temp_snapshot = self.create_snapshot(self.volume['id'])
-        # Force delete the snapshot
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.force_delete_snapshot(temp_snapshot['id'])
         self.client.wait_for_resource_deletion(temp_snapshot['id'])
 
diff --git a/patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py
index e78c492..81cd854 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_snapshots_metadata_rbac.py
@@ -53,17 +53,17 @@
     @decorators.idempotent_id('c9cbec1c-edfe-46b8-825b-7b6ac0a58c25')
     def test_create_snapshot_metadata(self):
         # Create metadata for the snapshot
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_test_snapshot_metadata()
 
     @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:get_volume_image_metadata")
+                                 rule="volume:get_snapshot_metadata")
     @decorators.idempotent_id('f6912bb1-62e6-483d-bcd0-e98c1641f4c3')
     def test_get_snapshot_metadata(self):
         # Create volume and snapshot metadata
         self._create_test_snapshot_metadata()
         # Get metadata for the snapshot
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.snapshots_client.show_snapshot_metadata(
             self.snapshot_id)
 
@@ -75,7 +75,7 @@
         # Create volume and snapshot metadata
         self._create_test_snapshot_metadata()
         # Get metadata for the snapshot
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Get the metadata of the snapshot
         self.snapshots_client.show_snapshot_metadata(
             self.snapshot_id)['metadata']
diff --git a/patrole_tempest_plugin/tests/api/volume/test_user_messages_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_user_messages_rbac.py
new file mode 100644
index 0000000..60484f1
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_user_messages_rbac.py
@@ -0,0 +1,91 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+CONF = config.CONF
+
+
+class MessagesV3RbacTest(rbac_base.BaseVolumeRbacTest):
+    _api_version = 3
+    min_microversion = '3.3'
+    max_microversion = 'latest'
+
+    @classmethod
+    def setup_clients(cls):
+        super(MessagesV3RbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.volume_v3_messages_client
+
+    def _create_user_message(self):
+        """Trigger a 'no valid host' situation to generate a message."""
+        bad_protocol = data_utils.rand_name('storage_protocol')
+        bad_vendor = data_utils.rand_name('vendor_name')
+        extra_specs = {'storage_protocol': bad_protocol,
+                       'vendor_name': bad_vendor}
+        vol_type_name = data_utils.rand_name(
+            self.__class__.__name__ + '-volume-type')
+        bogus_type = self.create_volume_type(
+            name=vol_type_name, extra_specs=extra_specs)
+        params = {'volume_type': bogus_type['id'],
+                  'size': CONF.volume.volume_size}
+        volume = self.create_volume(wait_until="error", **params)
+        messages = self.messages_client.list_messages()['messages']
+        message_id = None
+        for message in messages:
+            if message['resource_uuid'] == volume['id']:
+                message_id = message['id']
+                break
+        self.assertIsNotNone(message_id, 'No user message generated for '
+                                         'volume %s' % volume['id'])
+
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_message, message_id)
+
+        return message_id
+
+    @decorators.idempotent_id('bf7f31a1-509b-4a7d-a8a8-ad6ce68229c7')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="message:get_all")
+    def test_list_messages(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_messages()['messages']
+
+    @decorators.idempotent_id('9cc1ad1e-68a2-4407-8b60-ea77909bce08')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="message:get")
+    def test_show_message(self):
+        message_id = self._create_user_message()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_message(message_id)['message']
+
+    @decorators.idempotent_id('65ca7fb7-7f2c-443e-b144-ac86973a97be')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="message:delete")
+    def test_delete_message(self):
+        message_id = self._create_user_message()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_message(message_id)
+        self.client.wait_for_resource_deletion(message_id)
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
index 996e2b7..16e77ed 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
@@ -13,14 +13,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
-
 from tempest.common import compute
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.volume import rbac_base
@@ -30,10 +29,17 @@
 
 class VolumesActionsRbacTest(rbac_base.BaseVolumeRbacTest):
 
+    # TODO(felipemonteiro): "volume_extension:volume_actions:upload_public"
+    # test can be created once volumes v3 client is created in Tempest.
+
     @classmethod
     def setup_clients(cls):
         super(VolumesActionsRbacTest, cls).setup_clients()
-        cls.client = cls.os.volumes_client
+        cls.client = cls.volumes_client
+        if CONF.image_feature_enabled.api_v1:
+            cls.image_client = cls.os_primary.image_client
+        elif CONF.image_feature_enabled.api_v2:
+            cls.image_client = cls.os_primary.image_client_v2
 
     @classmethod
     def resource_setup(cls):
@@ -41,10 +47,11 @@
         cls.volume = cls.create_volume()
 
     def _create_server(self):
-        body, _ = compute.create_test_server(self.os, wait_until='ACTIVE')
+        server, _ = compute.create_test_server(
+            self.os_primary, wait_until='ACTIVE')
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.servers_client.delete_server, body['id'])
-        return body
+                        self.servers_client.delete_server, server['id'])
+        return server
 
     def _attach_volume(self, server):
         self.servers_client.attach_volume(
@@ -59,60 +66,139 @@
         waiters.wait_for_volume_resource_status(
             self.client, self.volume['id'], 'available')
 
-    @testtools.skipUnless(CONF.service_available.nova,
-                          "Nova is required to create a server")
+    @test.services('compute')
     @rbac_rule_validation.action(service="cinder", rule="volume:attach")
     @decorators.idempotent_id('f97b10e4-2eed-4f8b-8632-71c02cb9fe42')
     def test_attach_volume_to_instance(self):
         server = self._create_server()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Attach the volume
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._attach_volume(server)
 
+    @test.attr(type=["slow"])
+    @test.services('compute')
     @rbac_rule_validation.action(service="cinder", rule="volume:detach")
     @decorators.idempotent_id('5a042f6a-688b-42e6-a02e-fe5c47b89b07')
-    def test_detach_volume_to_instance(self):
-        # Attach the volume
+    def test_detach_volume_from_instance(self):
         server = self._create_server()
         self._attach_volume(server)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Detach the volume
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._detach_volume()
 
-    @testtools.skipUnless(CONF.service_available.nova,
-                          "Nova is needed to create a server")
-    @rbac_rule_validation.action(service="cinder", rule="volume:get")
-    @decorators.idempotent_id('c4c3fdd5-b1b1-49c3-b977-a9f40ee9257a')
-    def test_get_volume_attachment(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Get attachment
-        self.client.show_volume(self.volume['id'])
-
-    @testtools.skipIf(True, "Patrole bug #1672799")
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:copy_volume_to_image")
+    @test.services('image')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_actions:upload_image")
     @decorators.idempotent_id('b0d0da46-903c-4445-893e-20e680d68b50')
     def test_volume_upload(self):
-        self.image_client = self.os.image_client
-        image_name = data_utils.rand_name('image')
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        # TODO(felipemonteiro): The ``upload_volume`` endpoint also enforces
+        # "volume:copy_volume_to_image" but is not currently contained in
+        # Cinder's policy.json.
+        image_name = data_utils.rand_name(self.__class__.__name__ + '-Image')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         body = self.client.upload_volume(
-            self.volume['id'], image_name=image_name,
+            self.volume['id'], image_name=image_name, visibility="private",
             disk_format=CONF.volume.disk_format)['os-volume_upload_image']
+        image_id = body["image_id"]
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.image_client.delete_image,
-                        body['image_id'])
-        waiters.wait_for_volume_resource_status(
-            self.client, self.volume['id'], 'available')
+                        image_id)
+        waiters.wait_for_image_status(self.image_client, image_id, 'active')
+        waiters.wait_for_volume_resource_status(self.os_admin.volumes_client,
+                                                self.volume['id'], 'available')
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:update_readonly_flag")
     @decorators.idempotent_id('2750717a-f250-4e41-9e09-02624aad6ff8')
     def test_volume_readonly_update(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+
+        self.client.update_volume_readonly(self.volume['id'], readonly=True)
+        self.addCleanup(self.client.update_volume_readonly,
+                        self.volume['id'], readonly=False)
+
+    @decorators.idempotent_id('72bab13c-dfaf-4b6d-a132-c83a85fb1776')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_unmanage")
+    def test_unmanage_volume(self):
         volume = self.create_volume()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Update volume readonly
-        self.client.update_volume_readonly(volume['id'], readonly=True)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.unmanage_volume(volume['id'])
+
+    @decorators.idempotent_id('59b783c0-f4ef-430c-8a90-1bad97d4ec5c')
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:update")
+    def test_volume_set_bootable(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.set_bootable_volume(self.volume['id'], bootable=True)
+
+    @decorators.idempotent_id('41566922-75a1-4484-99c7-9c8782ee99ac')
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:reserve_volume")
+    def test_volume_reserve(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.reserve_volume(self.volume['id'])
+
+    @decorators.idempotent_id('e5fa9564-77d9-4e57-b0c0-3e0ae4d08535')
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:unreserve_volume")
+    def test_volume_unreserve(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.unreserve_volume(self.volume['id'])
+
+    @decorators.idempotent_id('c015c82f-7010-48cc-bd71-4ef542046f20')
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:retype")
+    def test_volume_retype(self):
+        volume = self.create_volume()
+        vol_type = self.create_volume_type()['name']
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.retype_volume(volume['id'], new_type=vol_type)
+
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_admin_actions:reset_status")
+    @decorators.idempotent_id('4b3dad7d-0e73-4839-8781-796dd3d7af1d')
+    def test_volume_reset_status(self):
+        volume = self.create_volume()
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.reset_volume_status(volume['id'], status='error')
+
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_admin_actions:force_delete")
+    @decorators.idempotent_id('a312a937-6abf-4b91-a950-747086cbce48')
+    def test_volume_force_delete(self):
+        volume = self.create_volume()
+        self.client.reset_volume_status(volume['id'], status='error')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.force_delete_volume(volume['id'])
+        self.client.wait_for_resource_deletion(volume['id'])
+
+    @decorators.idempotent_id('48bd302b-950a-4830-840c-3158246ecdcc')
+    @test.services('compute')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_admin_actions:force_detach")
+    def test_force_detach_volume_from_instance(self):
+        server = self._create_server()
+        self._attach_volume(server)
+        attachment = self.volumes_client.show_volume(
+            self.volume['id'])['volume']['attachments'][0]
+
+        # Reset volume's status to error.
+        self.volumes_client.reset_volume_status(self.volume['id'],
+                                                status='error')
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.volumes_client.force_detach_volume(
+            self.volume['id'], connector=None,
+            attachment_id=attachment['attachment_id'])
 
 
 class VolumesActionsV3RbacTest(VolumesActionsRbacTest):
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py
new file mode 100644
index 0000000..b98c39a
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py
@@ -0,0 +1,78 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+CONF = config.CONF
+
+
+class VolumesV2BasicCrudRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:create")
+    @decorators.idempotent_id('426b08ef-6394-4d06-9128-965d5a6c38ef')
+    def test_create_volume(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.create_volume()
+
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:delete")
+    @decorators.idempotent_id('6de9f9c2-509f-4558-867b-af21c7163be4')
+    def test_delete_volume(self):
+        volume = self.create_volume()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.volumes_client.delete_volume(volume['id'])
+
+    @rbac_rule_validation.action(service="cinder", rule="volume:get")
+    @decorators.idempotent_id('c4c3fdd5-b1b1-49c3-b977-a9f40ee9257a')
+    def test_get_volume(self):
+        volume = self.create_volume()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.volumes_client.show_volume(volume['id'])
+
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:get_all")
+    @decorators.idempotent_id('e3ab7906-b04b-4c45-aa11-1104d302f940')
+    def test_volume_list(self):
+        # Get a list of Volumes
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.volumes_client.list_volumes()
+
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_image_metadata")
+    @decorators.idempotent_id('3d48ca91-f02b-4616-a69d-4a8b296c8529')
+    def test_volume_list_image_metadata(self):
+        # Get a list of Volumes
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.volumes_client.list_volumes(detail=True)
+
+    @rbac_rule_validation.action(service="cinder", rule="volume:update")
+    @decorators.idempotent_id('b751b889-9a9b-40d8-ae7d-4b0f65e71ac7')
+    def test_update_volume(self):
+        volume = self.create_volume()
+        new_name = data_utils.rand_name('volume')
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.volumes_client.update_volume(volume['id'],
+                                          name=new_name)
+
+
+class VolumesV3BasicCrudRbacTest(VolumesV2BasicCrudRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_create_delete_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_create_delete_rbac.py
deleted file mode 100644
index d028180..0000000
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_create_delete_rbac.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from oslo_log import log as logging
-
-from tempest import config
-from tempest.lib import decorators
-from tempest.lib import exceptions
-
-from patrole_tempest_plugin import rbac_exceptions
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-LOG = logging.getLogger(__name__)
-
-
-class CreateDeleteVolumeRbacTest(rbac_base.BaseVolumeRbacTest):
-
-    def _create_volume(self):
-        # create_volume waits for volume status to be
-        # "available" before returning and automatically
-        # cleans up at the end of testing
-        volume = self.create_volume()
-        return volume
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:create")
-    @decorators.idempotent_id('426b08ef-6394-4d06-9128-965d5a6c38ef')
-    def test_create_volume(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Create a volume
-        self._create_volume()
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:delete")
-    @decorators.idempotent_id('6de9f9c2-509f-4558-867b-af21c7163be4')
-    def test_delete_volume(self):
-        try:
-            # Create a volume
-            volume = self._create_volume()
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            # Delete a volume
-            self.volumes_client.delete_volume(volume['id'])
-        except exceptions.NotFound as e:
-            raise rbac_exceptions.RbacActionFailed(e)
-
-
-class CreateDeleteVolumeV3RbacTest(CreateDeleteVolumeRbacTest):
-    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py
index 60130ee..18a2768 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py
@@ -19,11 +19,11 @@
 from patrole_tempest_plugin.tests.api.volume import rbac_base
 
 
-class VolumeHostsAdminRbacTest(rbac_base.BaseVolumeAdminRbacTest):
+class VolumeHostsRbacTest(rbac_base.BaseVolumeRbacTest):
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume_extension:hosts")
     @decorators.idempotent_id('64e837f5-5452-4e26-b934-c721ea7a8644')
     def test_list_hosts(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.volume_hosts_client.list_hosts()
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py
index 08de7b5..d07e5c6 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest import config
 from tempest.lib import decorators
 
@@ -22,62 +20,95 @@
 from patrole_tempest_plugin.tests.api.volume import rbac_base
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class VolumeMetadataRbacTest(rbac_base.BaseVolumeRbacTest):
     @classmethod
     def setup_clients(cls):
         super(VolumeMetadataRbacTest, cls).setup_clients()
-        cls.client = cls.os.volumes_client
+        cls.client = cls.volumes_client
+        if CONF.image_feature_enabled.api_v1:
+            cls.image_client = cls.os_primary.image_client
+        elif CONF.image_feature_enabled.api_v2:
+            cls.image_client = cls.os_primary.image_client_v2
+        cls.image_id = CONF.compute.image_ref
 
-    def _add_metadata(self, volume):
+    @classmethod
+    def resource_setup(cls):
+        super(VolumeMetadataRbacTest, cls).resource_setup()
+        cls.volume = cls.create_volume()
+        cls._add_metadata(cls.volume)
+        cls.image_id = CONF.compute.image_ref
+
+    @classmethod
+    def _add_metadata(cls, volume):
         # Create metadata for the volume
         metadata = {"key1": "value1",
                     "key2": "value2",
                     "key3": "value3",
                     "key4": "<value&special_chars>"}
-        self.volumes_client.create_volume_metadata(volume['id'],
-                                                   metadata)['metadata']
+        cls.client.create_volume_metadata(cls.volume['id'],
+                                          metadata)['metadata']
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:update_volume_metadata")
     @decorators.idempotent_id('232bbb8b-4c29-44dc-9077-b1398c20b738')
     def test_create_volume_metadata(self):
-        volume = self.create_volume()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self._add_metadata(volume)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._add_metadata(self.volume)
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:get")
     @decorators.idempotent_id('87ea37d9-23ab-47b2-a59c-16fc4d2c6dfa')
     def test_get_volume_metadata(self):
-        volume = self.create_volume()
-        self._add_metadata(volume)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.volumes_client.show_volume_metadata(volume['id'])['metadata']
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.show_volume_metadata(self.volume['id'])['metadata']
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:delete_volume_metadata")
     @decorators.idempotent_id('7498dfc1-9db2-4423-ad20-e6dcb25d1beb')
-    def test_delete_volume_metadata(self):
-        volume = self.create_volume()
-        self._add_metadata(volume)
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.volumes_client.delete_volume_metadata_item(volume['id'],
-                                                        "key1")
+    def test_delete_volume_metadata_item(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_volume_metadata_item(self.volume['id'], "key1")
+
+    @decorators.idempotent_id('a41c8eed-2051-4a25-b401-df036faacbdc')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume:delete_volume_metadata")
+    def test_delete_volume_image_metadata(self):
+        self.client.update_volume_image_metadata(self.volume['id'],
+                                                 image_id=self.image_id)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.delete_volume_image_metadata(self.volume['id'], 'image_id')
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:update_volume_metadata")
     @decorators.idempotent_id('8ce2ff80-99ba-49ae-9bb1-7e96729ee5af')
-    def test_update_volume_metadata(self):
-        volume = self.create_volume()
-        self._add_metadata(volume)
+    def test_update_volume_metadata_item(self):
         # Metadata to update
         update_item = {"key3": "value3_update"}
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.volumes_client.update_volume_metadata_item(
-            volume['id'], "key3", update_item)['meta']
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.update_volume_metadata_item(self.volume['id'], "key3",
+                                                update_item)['meta']
+
+    @decorators.idempotent_id('a231b445-97a5-4657-b05f-245895e88da9')
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:update_volume_metadata")
+    def test_update_volume_metadata(self):
+        # Metadata to update
+        update = {"key1": "value1",
+                  "key3": "value3"}
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.update_volume_metadata(self.volume['id'], update)
+
+    @decorators.idempotent_id('a9d9e825-5ea3-42e6-96f3-7ac4e97b2ed0')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume:update_volume_metadata")
+    def test_update_volume_image_metadata(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.update_volume_image_metadata(self.volume['id'],
+                                                 image_id=self.image_id)
 
 
 class VolumeMetadataV3RbacTest(VolumeMetadataRbacTest):
diff --git a/patrole_tempest_plugin/tests/api/volume/admin/test_volume_quotas_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_quotas_rbac.py
similarity index 79%
rename from patrole_tempest_plugin/tests/api/volume/admin/test_volume_quotas_rbac.py
rename to patrole_tempest_plugin/tests/api/volume/test_volume_quotas_rbac.py
index 8e054ac..0321e13 100644
--- a/patrole_tempest_plugin/tests/api/volume/admin/test_volume_quotas_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_quotas_rbac.py
@@ -27,23 +27,23 @@
 LOG = logging.getLogger(__name__)
 
 
-class VolumeQuotasAdminRbacTest(rbac_base.BaseVolumeAdminRbacTest):
+class VolumeQuotasRbacTest(rbac_base.BaseVolumeRbacTest):
 
     @classmethod
     def setup_credentials(cls):
-        super(VolumeQuotasAdminRbacTest, cls).setup_credentials()
-        cls.demo_tenant_id = cls.os.credentials.tenant_id
+        super(VolumeQuotasRbacTest, cls).setup_credentials()
+        cls.demo_tenant_id = cls.os_primary.credentials.tenant_id
 
     @classmethod
     def setup_clients(cls):
-        super(VolumeQuotasAdminRbacTest, cls).setup_clients()
-        cls.client = cls.os.volume_quotas_client
+        super(VolumeQuotasRbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.volume_quotas_client
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume_extension:quotas:show")
     @decorators.idempotent_id('b3c7177e-b6b1-4d0f-810a-fc95606964dd')
     def test_list_default_quotas(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_default_quota_set(
             self.demo_tenant_id)['quota_set']
 
@@ -55,11 +55,11 @@
                          'volumes': 11,
                          'snapshots': 11}
         # Update limits for all quota resources
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.update_quota_set(
             self.demo_tenant_id,
             **new_quota_set)['quota_set']
 
 
-class VolumeQuotasAdminV3RbacTest(VolumeQuotasAdminRbacTest):
+class VolumeQuotasV3RbacTest(VolumeQuotasRbacTest):
     _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_services_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_services_rbac.py
new file mode 100644
index 0000000..c1d8a65
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_services_rbac.py
@@ -0,0 +1,51 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+
+class VolumeServicesRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    # TODO(felipemonteiro): Implement a test to cover the policy action,
+    # "volume_extension:services:update", once the Tempest client endpoint
+    # is implemented.
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumeServicesRbacTest, cls).skip_checks()
+        if not test.is_extension_enabled('os-services', 'volume'):
+            msg = "%s skipped as os-services not enabled." % cls.__name__
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(VolumeServicesRbacTest, cls).setup_clients()
+        cls.client = cls.os_primary.volume_services_v2_client
+
+    @decorators.idempotent_id('b9134f01-97c0-4abd-9455-fe2f03e3f966')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:services:index")
+    def test_list_services(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.client.list_services()['services']
+
+
+class VolumeServicesV3RbacTest(VolumeServicesRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py
index 358733f..057379b 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py
@@ -14,26 +14,22 @@
 #    under the License.
 
 from tempest.common import waiters
-from tempest import config
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.volume import rbac_base
 
-CONF = config.CONF
-
 
 class VolumesTransfersRbacTest(rbac_base.BaseVolumeRbacTest):
 
-    credentials = ['primary', 'admin', 'alt']
+    credentials = ['primary', 'admin']
 
     @classmethod
     def setup_clients(cls):
         super(VolumesTransfersRbacTest, cls).setup_clients()
-        cls.client = cls.volumes_client
-        cls.alt_client = cls.os_alt.volumes_client
-        cls.alt_tenant_id = cls.alt_client.tenant_id
+        cls.client = cls.os_primary.volume_transfers_v2_client
+        cls.adm_volumes_client = cls.os_admin.volumes_v2_client
 
     @classmethod
     def resource_setup(cls):
@@ -43,11 +39,11 @@
     def _delete_transfer(self, transfer):
         # Volume from create_volume_transfer test may get stuck in
         # 'awaiting-transfer' state, preventing cleanup and causing
-        # the test to fail
+        # the test to fail.
         test_utils.call_and_ignore_notfound_exc(
             self.client.delete_volume_transfer, transfer['id'])
         waiters.wait_for_volume_resource_status(
-            self.client, self.volume['id'], 'available')
+            self.adm_volumes_client, self.volume['id'], 'available')
 
     def _create_transfer(self):
         transfer = self.client.create_volume_transfer(
@@ -59,7 +55,7 @@
                                  rule="volume:create_transfer")
     @decorators.idempotent_id('25413af4-468d-48ff-94ca-4436f8526b3e')
     def test_create_volume_transfer(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_transfer()
 
     @rbac_rule_validation.action(service="cinder",
@@ -67,14 +63,14 @@
     @decorators.idempotent_id('7a0925d3-ed97-4c25-8299-e5cdabe2eb55')
     def test_get_volume_transfer(self):
         transfer = self._create_transfer()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_volume_transfer(transfer['id'])
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:get_all_transfers")
     @decorators.idempotent_id('02a06f2b-5040-49e2-b2b7-619a7db59603')
     def test_list_volume_transfers(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.list_volume_transfers()
 
     @rbac_rule_validation.action(service="cinder",
@@ -82,7 +78,7 @@
     @decorators.idempotent_id('987f2a11-d657-4984-a6c9-28f06c1cd014')
     def test_accept_volume_transfer(self):
         transfer = self._create_transfer()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.accept_volume_transfer(transfer['id'],
                                            auth_key=transfer['auth_key'])
 
@@ -91,7 +87,7 @@
     @decorators.idempotent_id('4672187e-7fff-454b-832a-5c8865dda868')
     def test_delete_volume_transfer(self):
         transfer = self._create_transfer()
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.delete_volume_transfer(transfer['id'])
 
 
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py
index e045794..94199b5 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_types_extra_specs_rbac.py
@@ -13,24 +13,21 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.volume import rbac_base
 
-CONF = config.CONF
 
-
-class VolumeTypesExtraSpecsAdminRbacTest(rbac_base.BaseVolumeAdminRbacTest):
+class VolumeTypesExtraSpecsRbacTest(rbac_base.BaseVolumeRbacTest):
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume_extension:types_extra_specs")
     @decorators.idempotent_id('eea40251-990b-49b0-99ae-10e4585b479b')
-    def test_volume_type_extra_specs_list(self):
+    def test_create_volume_type_extra_specs(self):
         vol_type = self.create_volume_type()
         # List Volume types extra specs.
         extra_specs = {"spec1": "val1"}
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.volume_types_client.create_volume_type_extra_specs(
             vol_type['id'], extra_specs)
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
index 36ee02e..8c04a8d 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
@@ -13,11 +13,15 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from oslo_serialization import base64
+from oslo_serialization import jsonutils as json
+
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
+from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.volume import rbac_base
@@ -49,13 +53,27 @@
             self.backups_client, backup['id'], 'available')
         return backup
 
+    def _decode_url(self, backup_url):
+        return json.loads(base64.decode_as_text(backup_url))
+
+    def _encode_backup(self, backup):
+        retval = json.dumps(backup)
+        return base64.encode_as_text(retval)
+
+    def _modify_backup_url(self, backup_url, changes):
+        backup = self._decode_url(backup_url)
+        backup.update(changes)
+        return self._encode_backup(backup)
+
+    @test.attr(type=["slow"])
     @rbac_rule_validation.action(service="cinder",
                                  rule="backup:create")
     @decorators.idempotent_id('6887ec94-0bcf-4ab7-b30f-3808a4b5a2a5')
     def test_volume_backup_create(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._create_backup(volume_id=self.volume['id'])
 
+    @test.attr(type=["slow"])
     @rbac_rule_validation.action(service="cinder",
                                  rule="backup:get")
     @decorators.idempotent_id('abd92bdd-b0fb-4dc4-9cfc-de9e968f8c8a')
@@ -63,16 +81,17 @@
         # Create a temp backup
         backup = self._create_backup(volume_id=self.volume['id'])
         # Get a given backup
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.backups_client.show_backup(backup['id'])
 
     @rbac_rule_validation.action(service="cinder",
                                  rule="backup:get_all")
     @decorators.idempotent_id('4d18f0f0-7e01-4007-b622-dedc859b22f6')
     def test_volume_backup_list(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.backups_client.list_backups()
 
+    @test.attr(type=["slow"])
     @rbac_rule_validation.action(service="cinder",
                                  rule="backup:restore")
     @decorators.idempotent_id('9c794bf9-2446-4f41-8fe0-80b71e757f9d')
@@ -80,22 +99,56 @@
         # Create a temp backup
         backup = self._create_backup(volume_id=self.volume['id'])
         # Restore backup
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         restore = self.backups_client.restore_backup(backup['id'])['restore']
         waiters.wait_for_volume_resource_status(
             self.backups_client, restore['backup_id'], 'available')
 
+    @test.attr(type=["slow"])
     @rbac_rule_validation.action(service="cinder",
                                  rule="backup:delete")
     @decorators.idempotent_id('d5d0c6a2-413d-437e-a73f-4bf2b41a20ed')
     def test_volume_backup_delete(self):
         # Create a temp backup
         backup = self._create_backup(volume_id=self.volume['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Delete backup
         self.backups_client.delete_backup(backup['id'])
         self.backups_client.wait_for_resource_deletion(backup['id'])
 
+    @test.attr(type=["slow"])
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="backup:backup-export")
+    @decorators.idempotent_id('e984ec8d-e8eb-485c-98bc-f1856020303c')
+    def test_volume_backup_export(self):
+        # Create a temp backup
+        backup = self._create_backup(volume_id=self.volume['id'])
+
+        # Export Backup
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.backups_client.export_backup(backup['id'])['backup-record']
+
+    @test.attr(type=["slow"])
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="backup:backup-import")
+    @decorators.idempotent_id('1e70f039-4556-44cc-9cc1-edf2b7ed648b')
+    def test_volume_backup_import(self):
+        # Create a temp backup
+        backup = self._create_backup(volume_id=self.volume['id'])
+        # Export a temp backup
+        export_backup = self.backups_client.export_backup(
+            backup['id'])['backup-record']
+        new_id = data_utils.rand_uuid()
+        new_url = self._modify_backup_url(
+            export_backup['backup_url'], {'id': new_id})
+
+        # Import the temp backup
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        import_backup = self.backups_client.import_backup(
+            backup_service=export_backup['backup_service'],
+            backup_url=new_url)['backup']
+        self.addCleanup(self.backups_client.delete_backup, import_backup['id'])
+
 
 class VolumesBackupsV3RbacTest(VolumesBackupsRbacTest):
     _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py
index 64493c5..72afd69 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py
@@ -36,7 +36,7 @@
     def test_volume_extend(self):
         # Extend volume test
         extend_size = int(self.volume['size']) + 1
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.volumes_client.extend_volume(self.volume['id'],
                                           new_size=extend_size)
         waiters.wait_for_volume_resource_status(
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_list_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_list_rbac.py
deleted file mode 100644
index 8c0a9e0..0000000
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_list_rbac.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2017 AT&T Corp
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest import config
-from tempest.lib import decorators
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-
-
-class VolumesListRbacTest(rbac_base.BaseVolumeRbacTest):
-
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesListRbacTest, cls).setup_clients()
-        cls.client = cls.os.volumes_client
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:get_all")
-    @decorators.idempotent_id('e3ab7906-b04b-4c45-aa11-1104d302f940')
-    def test_volume_list(self):
-        # Get a list of Volumes
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.list_volumes()
-
-    @rbac_rule_validation.action(
-        service="cinder",
-        rule="volume_extension:get_volumes_image_metadata")
-    @decorators.idempotent_id('3d48ca91-f02b-4616-a69d-4a8b296c8529')
-    def test_volume_list_image_metadata(self):
-        # Get a list of Volumes
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.list_volumes(detail=True)
-
-
-class VolumeListV3RbacTest(VolumesListRbacTest):
-    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_manage_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_manage_rbac.py
new file mode 100644
index 0000000..7a9d7ba
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_volumes_manage_rbac.py
@@ -0,0 +1,113 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.common import waiters
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+CONF = config.CONF
+
+
+class VolumesManageRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesManageRbacTest, cls).skip_checks()
+
+        if not CONF.volume_feature_enabled.manage_volume:
+            raise cls.skipException("Manage volume tests are disabled")
+
+        if len(CONF.volume.manage_volume_ref) != 2:
+            raise cls.skipException("Manage volume ref is not correctly "
+                                    "configured")
+
+    @classmethod
+    def setup_clients(cls):
+        super(VolumesManageRbacTest, cls).setup_clients()
+        cls.volume_manage_client = cls.os_primary.volume_manage_v2_client
+
+    def _manage_volume(self, org_volume):
+        # Manage volume
+        new_volume_name = data_utils.rand_name(
+            self.__class__.__name__ + '-volume')
+
+        new_volume_ref = {
+            'name': new_volume_name,
+            'host': org_volume['os-vol-host-attr:host'],
+            'ref': {CONF.volume.manage_volume_ref[0]:
+                    CONF.volume.manage_volume_ref[1] % org_volume['id']},
+            'volume_type': org_volume['volume_type'],
+            'availability_zone': org_volume['availability_zone']}
+
+        new_volume_id = self.volume_manage_client.manage_volume(
+            **new_volume_ref)['volume']['id']
+
+        waiters.wait_for_volume_resource_status(self.volumes_client,
+                                                new_volume_id, 'available')
+        self.addCleanup(self.delete_volume,
+                        self.volumes_client, new_volume_id)
+
+    def _unmanage_volume(self, volume):
+        self.volumes_client.unmanage_volume(volume['id'])
+        self.volumes_client.wait_for_resource_deletion(volume['id'])
+
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_manage")
+    @decorators.idempotent_id('114f9708-939b-407e-aeac-d21ebfabaad3')
+    def test_volume_manage(self):
+        volume_id = self.create_volume()['id']
+        volume = self.volumes_client.show_volume(volume_id)['volume']
+
+        # By default, the volume is managed after creation.  We need to
+        # unmanage the volume first before testing manage volume.
+        self._unmanage_volume(volume)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        try:
+            self._manage_volume(volume)
+        except exceptions.Forbidden as e:
+            # Since the test role under test does not have permission to
+            # manage the volume, Forbidden exception is thrown and the
+            # manageable list will not be cleaned up. Therefore, we need to
+            # re-manage the volume at the end of the test case for proper
+            # resource clean up.
+            self.addCleanup(self._manage_volume, volume)
+            raise exceptions.Forbidden(e)
+
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:volume_unmanage")
+    @decorators.idempotent_id('d5d72abe-60bc-45ac-a8f2-c21b24f0b5d6')
+    def test_volume_unmanage(self):
+        volume_id = self.create_volume()['id']
+        volume = self.volumes_client.show_volume(volume_id)['volume']
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._unmanage_volume(volume)
+
+        # In order to clean up the manageable list, we need to re-manage the
+        # volume after the test.  The _manage_volume method will set up the
+        # proper resource cleanup
+        self.addCleanup(self._manage_volume, volume)
+
+
+class VolumesManageV3RbacTest(VolumesManageRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_rbac.py
deleted file mode 100644
index f6e79dc..0000000
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_rbac.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2017 AT&T Corporation.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from oslo_log import log as logging
-
-from tempest import config
-from tempest.lib import decorators
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-LOG = logging.getLogger(__name__)
-
-
-class VolumesRbacTest(rbac_base.BaseVolumeRbacTest):
-
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesRbacTest, cls).setup_clients()
-        cls.client = cls.volumes_client
-
-    @rbac_rule_validation.action(
-        service="cinder",
-        rule="volume_extension:volume_admin_actions:reset_status")
-    @decorators.idempotent_id('4b3dad7d-0e73-4839-8781-796dd3d7af1d')
-    def test_volume_reset_status(self):
-        volume = self.create_volume()
-        # Test volume reset status : available->error->available
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.reset_volume_status(volume['id'], status='error')
-        self.client.reset_volume_status(volume['id'], status='available')
-
-    @rbac_rule_validation.action(
-        service="cinder",
-        rule="volume_extension:volume_admin_actions:force_delete")
-    @decorators.idempotent_id('a312a937-6abf-4b91-a950-747086cbce48')
-    def test_volume_force_delete_when_volume_is_error(self):
-        volume = self.create_volume()
-        self.client.reset_volume_status(volume['id'], status='error')
-        # Test force delete when status of volume is error
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.force_delete_volume(volume['id'])
-        self.client.wait_for_resource_deletion(volume['id'])
-
-
-class VolumesV3RbacTest(VolumesRbacTest):
-    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py
index 83871cb..ce443e2 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volumes_snapshots_rbac.py
@@ -39,8 +39,6 @@
     def resource_setup(cls):
         super(VolumesSnapshotRbacTest, cls).resource_setup()
         # Create a test shared volume for tests
-        cls.name_field = cls.special_fields['name_field']
-        cls.descrip_field = cls.special_fields['descrip_field']
         cls.volume = cls.create_volume()
         # Create a test shared snapshot for tests
         cls.snapshot = cls.create_snapshot(cls.volume['id'])
@@ -48,7 +46,6 @@
     def _list_by_param_values(self, params, with_detail=False):
         # Perform list or list_details action with given params
         # and validates result.
-
         if with_detail:
             self.snapshots_client.list_snapshots(
                 detail=True, params=params)['snapshots']
@@ -61,7 +58,7 @@
     @decorators.idempotent_id('ac7b2ee5-fbc0-4360-afc2-de8fa4881ede')
     def test_snapshot_create(self):
         # Create a temp snapshot
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.create_snapshot(self.volume['id'])
 
     @rbac_rule_validation.action(service="cinder",
@@ -69,7 +66,7 @@
     @decorators.idempotent_id('93a11b40-1ba8-44d6-a196-f8d97220f796')
     def test_snapshot_get(self):
         # Get the snapshot
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.show_snapshot(self.snapshot
                                   ['id'])['snapshot']
 
@@ -78,9 +75,9 @@
     @decorators.idempotent_id('53fe8ee3-3bea-4ae8-a979-3c98ea72f620')
     def test_snapshot_update(self):
         new_desc = 'This is the new description of snapshot.'
-        params = {self.descrip_field: new_desc}
+        params = {'description': new_desc}
         # Updates snapshot with new values
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.client.update_snapshot(
             self.snapshot['id'], **params)['snapshot']
 
@@ -90,8 +87,8 @@
     def test_snapshots_get_all(self):
         """list snapshots with params."""
         # Verify list snapshots by display_name filter
-        params = {self.name_field: self.snapshot[self.name_field]}
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        params = {'name': self.snapshot['name']}
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self._list_by_param_values(params)
 
     @rbac_rule_validation.action(service="cinder",
@@ -100,7 +97,7 @@
     def test_snapshot_delete(self):
         # Create a temp snapshot
         temp_snapshot = self.create_snapshot(self.volume['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Delete the snapshot
         self.client.delete_snapshot(temp_snapshot['id'])
 
diff --git a/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json b/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json
index 0e7466a..d959168 100644
--- a/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json
+++ b/patrole_tempest_plugin/tests/unit/resources/custom_rbac_policy.json
@@ -10,5 +10,5 @@
     "policy_action_3": "rule:zero_rule",
     "policy_action_4": "rule:prime_rule",
     "policy_action_5": "rule:all_rule",
-    "policy_action_6": "role:eight",
+    "policy_action_6": "role:eight"
 }
diff --git a/patrole_tempest_plugin/tests/unit/test_rbac_policy_parser.py b/patrole_tempest_plugin/tests/unit/test_rbac_policy_parser.py
index 8583eb5..6889b44 100644
--- a/patrole_tempest_plugin/tests/unit/test_rbac_policy_parser.py
+++ b/patrole_tempest_plugin/tests/unit/test_rbac_policy_parser.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import json
 import mock
 import os
 
@@ -31,6 +32,8 @@
         super(RbacPolicyTest, self).setUp()
         self.mock_admin_mgr = mock.patch.object(
             rbac_policy_parser, 'credentials').start()
+        self.mock_path = mock.patch.object(
+            rbac_policy_parser, 'os').start()
 
         current_directory = os.path.dirname(os.path.realpath(__file__))
         self.custom_policy_file = os.path.join(current_directory,
@@ -75,6 +78,11 @@
             identity_services_v3_client.list_services.return_value = \
             services
 
+    def _get_fake_policy_rule(self, name, rule):
+        fake_rule = mock.Mock(check=rule)
+        fake_rule.name = name
+        return fake_rule
+
     @mock.patch.object(rbac_policy_parser, 'LOG', autospec=True)
     def test_custom_policy(self, m_log):
         default_roles = ['zero', 'one', 'two', 'three', 'four',
@@ -82,8 +90,9 @@
 
         test_tenant_id = mock.sentinel.tenant_id
         test_user_id = mock.sentinel.user_id
+        self.mock_path.path.join.return_value = self.custom_policy_file
         parser = rbac_policy_parser.RbacPolicyParser(
-            test_tenant_id, test_user_id, "test", self.custom_policy_file)
+            test_tenant_id, test_user_id, "test")
 
         expected = {
             'policy_action_1': ['two', 'four', 'six', 'eight'],
@@ -104,8 +113,9 @@
     def test_admin_policy_file_with_admin_role(self):
         test_tenant_id = mock.sentinel.tenant_id
         test_user_id = mock.sentinel.user_id
+        self.mock_path.path.join.return_value = self.admin_policy_file
         parser = rbac_policy_parser.RbacPolicyParser(
-            test_tenant_id, test_user_id, "test", self.admin_policy_file)
+            test_tenant_id, test_user_id, "test")
 
         role = 'admin'
         allowed_rules = [
@@ -124,8 +134,9 @@
     def test_admin_policy_file_with_member_role(self):
         test_tenant_id = mock.sentinel.tenant_id
         test_user_id = mock.sentinel.user_id
+        self.mock_path.path.join.return_value = self.admin_policy_file
         parser = rbac_policy_parser.RbacPolicyParser(
-            test_tenant_id, test_user_id, "test", self.admin_policy_file)
+            test_tenant_id, test_user_id, "test")
 
         role = 'Member'
         allowed_rules = [
@@ -145,8 +156,9 @@
     def test_admin_policy_file_with_context_is_admin(self):
         test_tenant_id = mock.sentinel.tenant_id
         test_user_id = mock.sentinel.user_id
+        self.mock_path.path.join.return_value = self.alt_admin_policy_file
         parser = rbac_policy_parser.RbacPolicyParser(
-            test_tenant_id, test_user_id, "test", self.alt_admin_policy_file)
+            test_tenant_id, test_user_id, "test")
 
         role = 'fake_admin'
         allowed_rules = ['non_admin_rule']
@@ -181,8 +193,9 @@
         """
         test_tenant_id = mock.sentinel.tenant_id
         test_user_id = mock.sentinel.user_id
+        self.mock_path.path.join.return_value = self.tenant_policy_file
         parser = rbac_policy_parser.RbacPolicyParser(
-            test_tenant_id, test_user_id, "test", self.tenant_policy_file)
+            test_tenant_id, test_user_id, "test")
 
         # Check whether Member role can perform expected actions.
         allowed_rules = ['rule1', 'rule2', 'rule3', 'rule4']
@@ -262,9 +275,9 @@
     def test_invalid_policy_rule_throws_rbac_parsing_exception(self, m_log):
         test_tenant_id = mock.sentinel.tenant_id
         test_user_id = mock.sentinel.user_id
-
+        self.mock_path.path.join.return_value = self.custom_policy_file
         parser = rbac_policy_parser.RbacPolicyParser(
-            test_tenant_id, test_user_id, "test", self.custom_policy_file)
+            test_tenant_id, test_user_id, "test")
 
         fake_rule = 'fake_rule'
         expected_message = "Policy action: {0} not found in policy file: {1}."\
@@ -279,19 +292,185 @@
     def test_unknown_exception_throws_rbac_parsing_exception(self, m_log):
         test_tenant_id = mock.sentinel.tenant_id
         test_user_id = mock.sentinel.user_id
-
+        self.mock_path.path.join.return_value = self.custom_policy_file
         parser = rbac_policy_parser.RbacPolicyParser(
-            test_tenant_id, test_user_id, "test", self.custom_policy_file)
+            test_tenant_id, test_user_id, "test")
         parser.rules = mock.MagicMock(
             **{'__getitem__.return_value.side_effect': Exception(
                mock.sentinel.error)})
 
-        expected_message = "Unknown exception: {0} for policy action: {1} in "\
-                           "policy file: {2}.".format(mock.sentinel.error,
-                                                      mock.sentinel.rule,
+        expected_message = "Policy action: {0} not found in "\
+                           "policy file: {1}.".format(mock.sentinel.rule,
                                                       self.custom_policy_file)
 
         e = self.assertRaises(rbac_exceptions.RbacParsingException,
                               parser.allowed, mock.sentinel.rule, None)
         self.assertIn(expected_message, str(e))
         m_log.debug.assert_called_once_with(expected_message)
+
+    @mock.patch.object(rbac_policy_parser, 'stevedore', autospec=True)
+    def test_get_policy_data_from_file_and_from_code(self, mock_stevedore):
+        fake_policy_rules = [
+            self._get_fake_policy_rule('code_policy_action_1',
+                                       'rule:code_rule_1'),
+            self._get_fake_policy_rule('code_policy_action_2',
+                                       'rule:code_rule_2'),
+            self._get_fake_policy_rule('code_policy_action_3',
+                                       'rule:code_rule_3'),
+        ]
+
+        mock_manager = mock.Mock(obj=fake_policy_rules)
+        mock_manager.configure_mock(name='fake_service')
+        mock_stevedore.named.NamedExtensionManager.return_value = [
+            mock_manager
+        ]
+
+        test_tenant_id = mock.sentinel.tenant_id
+        test_user_id = mock.sentinel.user_id
+        self.mock_path.path.join.return_value = self.tenant_policy_file
+        parser = rbac_policy_parser.RbacPolicyParser(
+            test_tenant_id, test_user_id, "test")
+
+        policy_data = parser._get_policy_data('fake_service')
+
+        self.assertIsInstance(policy_data, str)
+
+        actual_policy_data = json.loads(policy_data)
+        expected_policy_data = {
+            "code_policy_action_1": "rule:code_rule_1",
+            "code_policy_action_2": "rule:code_rule_2",
+            "code_policy_action_3": "rule:code_rule_3",
+            "rule1": "tenant_id:%(network:tenant_id)s",
+            "rule2": "tenant_id:%(tenant_id)s",
+            "rule3": "project_id:%(project_id)s",
+            "rule4": "user_id:%(user_id)s",
+            "admin_tenant_rule": "role:admin and tenant_id:%(tenant_id)s",
+            "admin_user_rule": "role:admin and user_id:%(user_id)s"
+
+        }
+
+        self.assertEqual(expected_policy_data, actual_policy_data)
+
+    @mock.patch.object(rbac_policy_parser, 'stevedore', autospec=True)
+    def test_get_policy_data_from_file_and_from_code_with_overwrite(
+            self, mock_stevedore):
+        # The custom policy file should overwrite default rules rule1 and rule2
+        # that are defined in code.
+        fake_policy_rules = [
+            self._get_fake_policy_rule('rule1', 'rule:code_rule_1'),
+            self._get_fake_policy_rule('rule2', 'rule:code_rule_2'),
+            self._get_fake_policy_rule('code_policy_action_3',
+                                       'rule:code_rule_3'),
+        ]
+
+        mock_manager = mock.Mock(obj=fake_policy_rules)
+        mock_manager.configure_mock(name='fake_service')
+        mock_stevedore.named.NamedExtensionManager.return_value = [
+            mock_manager
+        ]
+
+        test_tenant_id = mock.sentinel.tenant_id
+        test_user_id = mock.sentinel.user_id
+        self.mock_path.path.join.return_value = self.tenant_policy_file
+        parser = rbac_policy_parser.RbacPolicyParser(
+            test_tenant_id, test_user_id, "test")
+
+        policy_data = parser._get_policy_data('fake_service')
+
+        self.assertIsInstance(policy_data, str)
+
+        actual_policy_data = json.loads(policy_data)
+        expected_policy_data = {
+            "code_policy_action_3": "rule:code_rule_3",
+            "rule1": "tenant_id:%(network:tenant_id)s",
+            "rule2": "tenant_id:%(tenant_id)s",
+            "rule3": "project_id:%(project_id)s",
+            "rule4": "user_id:%(user_id)s",
+            "admin_tenant_rule": "role:admin and tenant_id:%(tenant_id)s",
+            "admin_user_rule": "role:admin and user_id:%(user_id)s"
+        }
+
+        self.assertEqual(expected_policy_data, actual_policy_data)
+
+    @mock.patch.object(rbac_policy_parser, 'credentials', autospec=True)
+    @mock.patch.object(rbac_policy_parser, 'stevedore', autospec=True)
+    def test_get_policy_data_cannot_find_policy(self, mock_stevedore,
+                                                mock_creds):
+        mock_stevedore.named.NamedExtensionManager.return_value = None
+        mock_creds.AdminManager.return_value.identity_services_v3_client.\
+            list_services.return_value = {
+                'services': [{'name': 'test_service'}]}
+        self.mock_path.path.join.return_value = '/etc/test_service/policy.json'
+        e = self.assertRaises(rbac_exceptions.RbacParsingException,
+                              rbac_policy_parser.RbacPolicyParser,
+                              None, None, 'test_service')
+
+        expected_error = \
+            'Policy file for {0} service neither found in code '\
+            'nor at {1}.'.format('test_service',
+                                 '/etc/test_service/policy.json')
+
+        self.assertIn(expected_error, str(e))
+
+    @mock.patch.object(rbac_policy_parser, 'json', autospec=True)
+    @mock.patch.object(rbac_policy_parser, 'credentials', autospec=True)
+    @mock.patch.object(rbac_policy_parser, 'stevedore', autospec=True)
+    def test_get_policy_data_without_valid_policy(self, mock_stevedore,
+                                                  mock_credentials, mock_json):
+        self.mock_path.path.isfile.return_value = False
+
+        test_policy_action = mock.Mock(check='rule:bar')
+        test_policy_action.configure_mock(name='foo')
+
+        test_policy = mock.Mock(obj=[test_policy_action])
+        test_policy.configure_mock(name='test_service')
+
+        mock_stevedore.named.NamedExtensionManager\
+            .return_value = [test_policy]
+
+        mock_credentials.AdminManager.return_value.identity_services_v3_client.\
+            list_services.return_value = {
+                'services': [{'name': 'test_service'}]
+            }
+
+        mock_json.dumps.side_effect = ValueError
+
+        e = self.assertRaises(rbac_exceptions.RbacParsingException,
+                              rbac_policy_parser.RbacPolicyParser,
+                              None, None, 'test_service')
+
+        expected_error = "Policy file for {0} service is invalid."\
+                         .format("test_service")
+
+        self.assertIn(expected_error, str(e))
+
+        mock_stevedore.named.NamedExtensionManager.assert_called_once_with(
+            'oslo.policy.policies',
+            names=['test_service'],
+            on_load_failure_callback=None,
+            invoke_on_load=True,
+            warn_on_missing_entrypoint=False)
+
+    @mock.patch.object(rbac_policy_parser, 'json', autospec=True)
+    @mock.patch.object(rbac_policy_parser, 'credentials', autospec=True)
+    @mock.patch.object(rbac_policy_parser, 'stevedore', autospec=True)
+    def test_get_policy_data_from_file_not_json(self, mock_stevedore,
+                                                mock_credentials,
+                                                mock_json):
+
+        mock_credentials.AdminManager.return_value.identity_services_v3_client.\
+            list_services.return_value = {
+                'services': [{'name': 'test_service'}]
+            }
+        mock_stevedore.named.NamedExtensionManager.return_value = None
+        mock_json.loads.side_effect = ValueError
+        self.mock_path.path.join.return_value = self.tenant_policy_file
+        e = self.assertRaises(rbac_exceptions.RbacParsingException,
+                              rbac_policy_parser.RbacPolicyParser,
+                              None, None, 'test_service')
+
+        expected_error = 'Policy file for {0} service neither found in code '\
+                         'nor at {1}.'.format('test_service',
+                                              self.tenant_policy_file)
+
+        self.assertIn(expected_error, str(e))
diff --git a/patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py b/patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py
index eeb06cc..41af3b2 100644
--- a/patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py
+++ b/patrole_tempest_plugin/tests/unit/test_rbac_rule_validation.py
@@ -13,16 +13,17 @@
 #    under the License.
 
 import mock
-import testtools
 
-from patrole_tempest_plugin import rbac_auth
-from patrole_tempest_plugin import rbac_exceptions
-from patrole_tempest_plugin import rbac_rule_validation as rbac_rv
-
+from tempest import config
 from tempest.lib import exceptions
 from tempest import test
 from tempest.tests import base
 
+from patrole_tempest_plugin import rbac_exceptions
+from patrole_tempest_plugin import rbac_rule_validation as rbac_rv
+
+CONF = config.CONF
+
 
 class RBACRuleValidationTest(base.TestCase):
 
@@ -31,82 +32,240 @@
         self.mock_args = mock.Mock(spec=test.BaseTestCase)
         self.mock_args.auth_provider = mock.Mock()
         self.mock_args.rbac_utils = mock.Mock()
-        self.mock_args.auth_provider.credentials.tenant_id = \
-            mock.sentinel.tenant_id
+        self.mock_args.auth_provider.credentials.project_id = \
+            mock.sentinel.project_id
         self.mock_args.auth_provider.credentials.user_id = \
             mock.sentinel.user_id
 
-    @mock.patch('patrole_tempest_plugin.rbac_auth.RbacAuthority')
-    def test_RBAC_rv_happy_path(self, mock_auth):
-        decorator = rbac_rv.action("", "")
-        mock_function = mock.Mock()
-        wrapper = decorator(mock_function)
-        wrapper((self.mock_args))
-        self.assertTrue(mock_function.called)
+        CONF.set_override('rbac_test_role', 'Member', group='rbac',
+                          enforce_type=True)
+        self.addCleanup(CONF.clear_override, 'rbac_test_role', group='rbac')
 
-    @mock.patch('patrole_tempest_plugin.rbac_auth.RbacAuthority')
-    def test_RBAC_rv_forbidden(self, mock_auth):
-        decorator = rbac_rv.action("", "")
-        mock_function = mock.Mock()
-        mock_function.side_effect = exceptions.Forbidden
-        wrapper = decorator(mock_function)
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_rule_validation_have_permission_no_exc(self, mock_policy,
+                                                    mock_log):
+        """Test that having permission and no exception thrown is success.
 
-        self.assertRaises(exceptions.Forbidden, wrapper, self.mock_args)
-
-    @mock.patch('patrole_tempest_plugin.rbac_auth.RbacAuthority')
-    def test_RBAC_rv_rbac_action_failed(self, mock_auth):
-        decorator = rbac_rv.action("", "")
-        mock_function = mock.Mock()
-        mock_function.side_effect = rbac_exceptions.RbacActionFailed
-
-        wrapper = decorator(mock_function)
-        self.assertRaises(exceptions.Forbidden, wrapper, self.mock_args)
-
-    @mock.patch('patrole_tempest_plugin.rbac_auth.RbacAuthority')
-    def test_RBAC_rv_not_allowed(self, mock_auth):
-        decorator = rbac_rv.action("", "")
+        Positive test case success scenario.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service, mock.sentinel.action)
 
         mock_function = mock.Mock()
         wrapper = decorator(mock_function)
 
-        mock_permission = mock.Mock()
-        mock_permission.get_permission.return_value = False
-        mock_auth.return_value = mock_permission
+        mock_policy.RbacPolicyParser.return_value.allowed.return_value = True
 
-        self.assertRaises(rbac_exceptions.RbacOverPermission, wrapper,
-                          self.mock_args)
+        result = wrapper(self.mock_args)
 
-    @mock.patch('patrole_tempest_plugin.rbac_auth.RbacAuthority')
-    def test_RBAC_rv_forbidden_not_allowed(self, mock_auth):
-        decorator = rbac_rv.action("", "")
+        self.assertIsNone(result)
+        mock_log.warning.assert_not_called()
+        mock_log.error.assert_not_called()
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_rule_validation_lack_permission_throw_exc(self, mock_policy,
+                                                       mock_log):
+        """Test that having no permission and exception thrown is success.
+
+        Negative test case success scenario.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service, mock.sentinel.action)
 
         mock_function = mock.Mock()
         mock_function.side_effect = exceptions.Forbidden
         wrapper = decorator(mock_function)
 
-        mock_permission = mock.Mock()
-        mock_permission.get_permission.return_value = False
-        mock_auth.return_value = mock_permission
+        mock_policy.RbacPolicyParser.return_value.allowed.return_value = False
 
-        self.assertIsNone(wrapper(self.mock_args))
+        result = wrapper(self.mock_args)
 
-    @mock.patch('patrole_tempest_plugin.rbac_auth.RbacAuthority')
-    def test_RBAC_rv_rbac_action_failed_not_allowed(self, mock_auth):
-        decorator = rbac_rv.action("", "")
+        self.assertIsNone(result)
+        mock_log.warning.assert_not_called()
+        mock_log.error.assert_not_called()
 
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_rule_validation_forbidden_negative(self, mock_policy, mock_log):
+        """Test Forbidden error is thrown and have permission fails.
+
+        Negative test case: if Forbidden is thrown and the user should be
+        allowed to perform the action, then the Forbidden exception should be
+        raised.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service, mock.sentinel.action)
+        mock_function = mock.Mock()
+        mock_function.side_effect = exceptions.Forbidden
+        wrapper = decorator(mock_function)
+
+        mock_policy.RbacPolicyParser.return_value.allowed.return_value = True
+
+        e = self.assertRaises(exceptions.Forbidden, wrapper, self.mock_args)
+        self.assertIn(
+            "Role Member was not allowed to perform sentinel.action.",
+            e.__str__())
+        mock_log.error.assert_called_once_with("Role Member was not allowed to"
+                                               " perform sentinel.action.")
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_rule_validation_rbac_action_failed_positive(self, mock_policy,
+                                                         mock_log):
+        """Test RbacActionFailed error is thrown without permission passes.
+
+        Positive test case: if RbacActionFailed is thrown and the user is not
+        allowed to perform the action, then this is a success.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service, mock.sentinel.action)
         mock_function = mock.Mock()
         mock_function.side_effect = rbac_exceptions.RbacActionFailed
         wrapper = decorator(mock_function)
 
-        mock_permission = mock.Mock()
-        mock_permission.get_permission.return_value = False
-        mock_auth.return_value = mock_permission
+        mock_policy.RbacPolicyParser.return_value.allowed.return_value = False
 
-        self.assertIsNone(wrapper(self.mock_args))
+        result = wrapper(self.mock_args)
 
-    @mock.patch.object(rbac_auth, 'rbac_policy_parser', autospec=True)
-    def test_invalid_policy_rule_throws_skip_exception(
+        self.assertIsNone(result)
+        mock_log.error.assert_not_called()
+        mock_log.warning.assert_not_called()
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_rule_validation_rbac_action_failed_negative(self, mock_policy,
+                                                         mock_log):
+        """Test RbacActionFailed error is thrown with permission fails.
+
+        Negative test case: if RbacActionFailed is thrown and the user is
+        allowed to perform the action, then this is an expected failure.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service, mock.sentinel.action)
+        mock_function = mock.Mock()
+        mock_function.side_effect = rbac_exceptions.RbacActionFailed
+        wrapper = decorator(mock_function)
+
+        mock_policy.RbacPolicyParser.return_value.allowed.return_value = True
+
+        e = self.assertRaises(exceptions.Forbidden, wrapper, self.mock_args)
+        self.assertIn(
+            "Role Member was not allowed to perform sentinel.action.",
+            e.__str__())
+
+        mock_log.error.assert_called_once_with("Role Member was not allowed to"
+                                               " perform sentinel.action.")
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_expect_not_found_but_raises_forbidden(self, mock_policy,
+                                                   mock_log):
+        """Test that expecting 404 but getting 403 works for all scenarios.
+
+        Tests the following scenarios:
+        1) Test no permission and 404 is expected but 403 is thrown throws
+           exception.
+        2) Test have permission and 404 is expected but 403 is thrown throws
+           exception.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service,
+                                   mock.sentinel.action,
+                                   expected_error_code=404)
+        mock_function = mock.Mock()
+        mock_function.side_effect = exceptions.Forbidden('Random message.')
+        wrapper = decorator(mock_function)
+
+        expected_error = "Forbidden\nDetails: Random message. An unexpected "\
+                         "exception has occurred: Expected exception was "\
+                         "NotFound, which was not thrown."
+
+        for permission in [True, False]:
+            mock_policy.RbacPolicyParser.return_value.allowed.return_value =\
+                permission
+
+            e = self.assertRaises(exceptions.Forbidden, wrapper,
+                                  self.mock_args)
+            self.assertIn(expected_error, e.__str__())
+            mock_log.error.assert_called_once_with(expected_error)
+            mock_log.error.reset_mock()
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_expect_not_found_and_raise_not_found(self, mock_policy, mock_log):
+        """Test that expecting 404 and getting 404 works for all scenarios.
+
+        Tests the following scenarios:
+        1) Test no permission and 404 is expected and 404 is thrown succeeds.
+        2) Test have permission and 404 is expected and 404 is thrown fails.
+
+        In both cases, a LOG.warning is called with the "irregular message"
+        that signals to user that a 404 was expected and caught.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service,
+                                   mock.sentinel.action,
+                                   expected_error_code=404)
+        mock_function = mock.Mock()
+        mock_function.side_effect = exceptions.NotFound
+        wrapper = decorator(mock_function)
+
+        expected_errors = [
+            "Role Member was not allowed to perform sentinel.action.", None
+        ]
+
+        for pos, permission in enumerate([True, False]):
+            mock_policy.RbacPolicyParser.return_value.allowed.return_value =\
+                permission
+
+            expected_error = expected_errors[pos]
+
+            if expected_error:
+                e = self.assertRaises(exceptions.Forbidden, wrapper,
+                                      self.mock_args)
+                self.assertIn(expected_error, e.__str__())
+                mock_log.error.assert_called_once_with(expected_error)
+            else:
+                wrapper(self.mock_args)
+                mock_log.error.assert_not_called()
+
+            mock_log.warning.assert_called_once_with(
+                "NotFound exception was caught for policy action {0}. The "
+                "service {1} throws a 404 instead of a 403, which is "
+                "irregular.".format(mock.sentinel.action,
+                                    mock.sentinel.service))
+
+            mock_log.warning.reset_mock()
+            mock_log.error.reset_mock()
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_rule_validation_overpermission_negative(self, mock_policy,
+                                                     mock_log):
+        """Test that OverPermission is correctly handled.
+
+        Tests that case where no exception is thrown but the Patrole framework
+        says that the role should not be allowed to perform the policy action.
+        """
+        decorator = rbac_rv.action(mock.sentinel.service, mock.sentinel.action)
+
+        mock_function = mock.Mock()
+        wrapper = decorator(mock_function)
+
+        mock_policy.RbacPolicyParser.return_value.allowed.return_value = False
+
+        e = self.assertRaises(rbac_exceptions.RbacOverPermission, wrapper,
+                              self.mock_args)
+        self.assertIn(("OverPermission: Role Member was allowed to perform "
+                      "sentinel.action"), e.__str__())
+
+        mock_log.error.assert_called_once_with(
+            "Role Member was allowed to perform sentinel.action")
+
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_invalid_policy_rule_throws_parsing_exception(
             self, mock_rbac_policy_parser):
+        """Test that invalid policy action causes test to be skipped."""
+        CONF.set_override('strict_policy_check', True, group='rbac',
+                          enforce_type=True)
+        self.addCleanup(CONF.clear_override, 'strict_policy_check',
+                        group='rbac')
+
         mock_rbac_policy_parser.RbacPolicyParser.return_value.allowed.\
             side_effect = rbac_exceptions.RbacParsingException
 
@@ -114,11 +273,64 @@
                                    mock.sentinel.policy_rule)
         wrapper = decorator(mock.Mock())
 
-        e = self.assertRaises(testtools.TestCase.skipException, wrapper,
+        e = self.assertRaises(rbac_exceptions.RbacParsingException, wrapper,
                               self.mock_args)
         self.assertEqual('Attempted to test an invalid policy file or action',
                          str(e))
 
         mock_rbac_policy_parser.RbacPolicyParser.assert_called_once_with(
-            mock.sentinel.tenant_id, mock.sentinel.user_id,
-            mock.sentinel.service)
+            mock.sentinel.project_id, mock.sentinel.user_id,
+            mock.sentinel.service, extra_target_data={})
+
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_get_exception_type_404(self, mock_policy):
+        """Test that getting a 404 exception type returns NotFound."""
+        expected_exception = exceptions.NotFound
+        expected_irregular_msg = ("NotFound exception was caught for policy "
+                                  "action {0}. The service {1} throws a 404 "
+                                  "instead of a 403, which is irregular.")
+
+        actual_exception, actual_irregular_msg = \
+            rbac_rv._get_exception_type(404)
+
+        self.assertEqual(expected_exception, actual_exception)
+        self.assertEqual(expected_irregular_msg, actual_irregular_msg)
+
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_get_exception_type_403(self, mock_policy):
+        """Test that getting a 404 exception type returns Forbidden."""
+        expected_exception = exceptions.Forbidden
+        expected_irregular_msg = None
+
+        actual_exception, actual_irregular_msg = \
+            rbac_rv._get_exception_type(403)
+
+        self.assertEqual(expected_exception, actual_exception)
+        self.assertEqual(expected_irregular_msg, actual_irregular_msg)
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_exception_thrown_when_type_is_not_int(self, mock_policy,
+                                                   mock_log):
+        """Test that non-integer exception type raises error."""
+        self.assertRaises(rbac_exceptions.RbacInvalidErrorCode,
+                          rbac_rv._get_exception_type, "403")
+
+        mock_log.error.assert_called_once_with("Please pass an expected error "
+                                               "code. Currently supported "
+                                               "codes: [403, 404]")
+
+    @mock.patch.object(rbac_rv, 'LOG', autospec=True)
+    @mock.patch.object(rbac_rv, 'rbac_policy_parser', autospec=True)
+    def test_exception_thrown_when_type_is_403_or_404(self, mock_policy,
+                                                      mock_log):
+        """Test that unsupported exceptions throw error."""
+        invalid_exceptions = [200, 400, 500]
+        for exc in invalid_exceptions:
+            self.assertRaises(rbac_exceptions.RbacInvalidErrorCode,
+                              rbac_rv._get_exception_type, exc)
+            mock_log.error.assert_called_once_with(
+                "Please pass an expected error code. Currently supported "
+                "codes: [403, 404]")
+
+            mock_log.error.reset_mock()
diff --git a/patrole_tempest_plugin/tests/unit/test_rbac_utils.py b/patrole_tempest_plugin/tests/unit/test_rbac_utils.py
index add1770..a2917cf 100644
--- a/patrole_tempest_plugin/tests/unit/test_rbac_utils.py
+++ b/patrole_tempest_plugin/tests/unit/test_rbac_utils.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 import mock
+import testtools
 
 from tempest import config
 from tempest.lib import exceptions as lib_exc
@@ -27,62 +28,90 @@
 
 class RBACUtilsTest(base.TestCase):
 
-    @mock.patch.object(rbac_utils, 'time', autospec=True)
-    def setUp(self, _):
+    def setUp(self):
         super(RBACUtilsTest, self).setUp()
-        self.mock_creds_provider = mock.patch.object(
-            rbac_utils, 'credentials_factory', autospec=True).start()
-
         available_roles = {
             'roles': [
                 {'name': 'admin', 'id': 'admin_id'},
                 {'name': 'Member', 'id': 'member_id'}
             ]
         }
-        self.mock_creds_provider.get_credentials_provider.return_value.\
-            creds_client.roles_client.list_roles.return_value = \
-            available_roles
-        self.addCleanup(mock.patch.stopall)
-
-        CONF.set_override('rbac_test_role', 'Member', group='rbac',
-                          enforce_type=True)
-        self.addCleanup(CONF.clear_override, 'rbac_test_role', group='rbac')
 
         # Because rbac_utils is a singleton, reset all of its role-related
         # parameters to the correct values for each test run.
         self.rbac_utils = rbac_utils.rbac_utils()
-        self.rbac_utils.available_roles = available_roles
+        self.rbac_utils.switch_role_history = {}
         self.rbac_utils.admin_role_id = 'admin_id'
         self.rbac_utils.rbac_role_id = 'member_id'
 
-    def test_initialization_with_missing_admin_role(self):
-        self.rbac_utils.admin_role_id = None
-        e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
-                              self.rbac_utils.switch_role, None)
-        self.assertIn("Defined 'rbac_role' or 'admin' role does not exist"
-                      " in the system.", e.__str__())
+        self.mock_test_obj = mock.Mock()
+        self.mock_test_obj.auth_provider = mock.Mock(
+            **{'credentials.user_id': mock.sentinel.user_id,
+               'credentials.tenant_id': mock.sentinel.project_id})
+        self.mock_test_obj.os_admin = mock.Mock(
+            **{'roles_v3_client.list_roles.return_value': available_roles})
 
-    def test_initialization_with_missing_rbac_role(self):
+        CONF.set_override('admin_role', 'admin', group='identity',
+                          enforce_type=True)
+        CONF.set_override('auth_version', 'v3', group='identity',
+                          enforce_type=True)
+        CONF.set_override('rbac_test_role', 'Member', group='rbac',
+                          enforce_type=True)
+
+        self.addCleanup(CONF.clear_override, 'rbac_test_role', group='rbac')
+        self.addCleanup(CONF.clear_override, 'admin_role', group='identity')
+        self.addCleanup(CONF.clear_override, 'auth_version', group='identity')
+        self.addCleanup(mock.patch.stopall)
+
+    def _mock_list_user_roles_on_project(self, return_value):
+        self.mock_test_obj.admin_manager = mock.Mock(
+            **{'roles_client.list_user_roles_on_project.'
+               'return_value': {'roles': [{'id': return_value}]}})
+
+    @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+                       autospec=True, return_value=False)
+    def test_initialization_with_missing_admin_role(self, _):
+        self.mock_test_obj.os_admin = mock.Mock(
+            **{'roles_v3_client.list_roles.return_value':
+               {'roles': [{'name': 'Member', 'id': 'member_id'}]}})
+        self.rbac_utils.admin_role_id = None
         self.rbac_utils.rbac_role_id = None
         e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
-                              self.rbac_utils.switch_role, None)
-        self.assertIn("Defined 'rbac_role' or 'admin' role does not exist"
-                      " in the system.", e.__str__())
+                              self.rbac_utils.switch_role, self.mock_test_obj,
+                              True)
+        self.assertIn("Role with name 'admin' does not exist in the system.",
+                      e.__str__())
+
+    @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+                       autospec=True, return_value=False)
+    def test_initialization_with_missing_rbac_role(self, _):
+        self.mock_test_obj.os_admin = mock.Mock(
+            **{'roles_v3_client.list_roles.return_value':
+               {'roles': [{'name': 'admin', 'id': 'admin_id'}]}})
+        self.rbac_utils.admin_role_id = None
+        self.rbac_utils.rbac_role_id = None
+        e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+                              self.rbac_utils.switch_role, self.mock_test_obj,
+                              True)
+        self.assertIn("Role defined by rbac_test_role does not exist in the "
+                      "system.", e.__str__())
 
     def test_clear_user_roles(self):
-        self.rbac_utils.creds_client = mock.Mock()
-        creds_client = self.rbac_utils.creds_client
-        creds_client.roles_client.list_user_roles_on_project.return_value = {
+        roles_client = self.mock_test_obj.os_admin.roles_v3_client
+        roles_client.list_user_roles_on_project.return_value = {
             'roles': [{'id': 'admin_id'}, {'id': 'member_id'}]
         }
 
-        self.rbac_utils._clear_user_roles(mock.sentinel.user_id,
-                                          mock.sentinel.project_id)
+        self.rbac_utils.roles_client = roles_client
+        self.rbac_utils.project_id = mock.sentinel.project_id
+        self.rbac_utils.user_id = mock.sentinel.user_id
 
-        creds_client.roles_client.list_user_roles_on_project.\
+        self.rbac_utils._clear_user_roles(None)
+
+        roles_client.list_user_roles_on_project.\
             assert_called_once_with(mock.sentinel.project_id,
                                     mock.sentinel.user_id)
-        creds_client.roles_client.delete_role_from_user_on_project.\
+        roles_client.delete_role_from_user_on_project.\
             assert_has_calls([
                 mock.call(mock.sentinel.project_id, mock.sentinel.user_id,
                           'admin_id'),
@@ -91,65 +120,124 @@
             ])
 
     @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
-                       autospec=True)
-    def test_rbac_utils_switch_role_to_admin(self, mock_clear_user_roles):
-        mock_test_object = mock.Mock()
-        mock_test_object.auth_provider.credentials.user_id = \
-            mock.sentinel.user_id
-        mock_test_object.auth_provider.credentials.tenant_id = \
-            mock.sentinel.project_id
+                       autospec=True, return_value=False)
+    @mock.patch.object(rbac_utils, 'time', autospec=True)
+    def test_rbac_utils_switch_role_to_admin_role(self, mock_time,
+                                                  mock_clear_user_roles):
+        self.rbac_utils.prev_switch_role = True
+        self._mock_list_user_roles_on_project('admin_id')
+        roles_client = self.mock_test_obj.os_admin.roles_v3_client
 
-        self.rbac_utils.creds_client = mock.Mock()
-        creds_client = self.rbac_utils.creds_client
+        self.rbac_utils.switch_role(self.mock_test_obj, False)
 
-        self.rbac_utils.switch_role(mock_test_object, False)
-
-        creds_client.roles_client.create_user_role_on_project.\
+        roles_client.create_user_role_on_project.\
             assert_called_once_with(mock.sentinel.project_id,
                                     mock.sentinel.user_id,
                                     'admin_id')
         mock_clear_user_roles.assert_called_once_with(
-            self.rbac_utils, mock.sentinel.user_id, mock.sentinel.project_id)
-        mock_test_object.auth_provider.clear_auth.assert_called_once_with()
-        mock_test_object.auth_provider.set_auth.assert_called_once_with()
+            self.rbac_utils, 'admin_id')
+        self.mock_test_obj.auth_provider.clear_auth.assert_called_once_with()
+        self.mock_test_obj.auth_provider.set_auth.assert_called_once_with()
+        mock_time.sleep.assert_called_once_with(1)
 
     @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
-                       autospec=True)
-    def test_rbac_utils_switch_role_to_rbac_role(self, mock_clear_user_roles):
-        mock_test_object = mock.Mock()
-        mock_test_object.auth_provider.credentials.user_id = \
-            mock.sentinel.user_id
-        mock_test_object.auth_provider.credentials.tenant_id = \
-            mock.sentinel.project_id
+                       autospec=True, return_value=False)
+    @mock.patch.object(rbac_utils, 'time', autospec=True)
+    def test_rbac_utils_switch_role_to_rbac_role(self, mock_time,
+                                                 mock_clear_user_roles):
+        self._mock_list_user_roles_on_project('member_id')
+        roles_client = self.mock_test_obj.os_admin.roles_v3_client
 
-        self.rbac_utils.creds_client = mock.Mock()
-        creds_client = self.rbac_utils.creds_client
+        self.rbac_utils.switch_role(self.mock_test_obj, True)
 
-        self.rbac_utils.switch_role(mock_test_object, True)
-
-        creds_client.roles_client.create_user_role_on_project.\
+        roles_client.create_user_role_on_project.\
             assert_called_once_with(mock.sentinel.project_id,
                                     mock.sentinel.user_id,
                                     'member_id')
         mock_clear_user_roles.assert_called_once_with(
-            self.rbac_utils, mock.sentinel.user_id, mock.sentinel.project_id)
-        mock_test_object.auth_provider.clear_auth.assert_called_once_with()
-        mock_test_object.auth_provider.set_auth.assert_called_once_with()
+            self.rbac_utils, 'member_id')
+        self.mock_test_obj.auth_provider.clear_auth.assert_called_once_with()
+        self.mock_test_obj.auth_provider.set_auth.assert_called_once_with()
+        mock_time.sleep.assert_called_once_with(1)
 
-    def test_rbac_utils_switch_roles_with_invalid_value(self):
-        e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
-                              self.rbac_utils.switch_role, None)
-        self.assertIn("Wrong value for parameter 'switchToRbacRole' is passed."
-                      " It should be either 'True' or 'False'.", e.__str__())
+    def test_RBAC_utils_switch_roles_without_boolean_value(self):
+        self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+                          self.rbac_utils.switch_role, self.mock_test_obj,
+                          "admin")
+        self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+                          self.rbac_utils.switch_role, self.mock_test_obj,
+                          None)
 
     @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
-                       autospec=True)
+                       autospec=True, return_value=False)
+    def test_rbac_utils_switch_roles_with_false_value_twice(self, _):
+        self._mock_list_user_roles_on_project('admin_id')
+        self.rbac_utils.switch_role(self.mock_test_obj, False)
+        e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+                              self.rbac_utils.switch_role, self.mock_test_obj,
+                              False)
+        self.assertIn(
+            '`toggle_rbac_role` must not be called with the same bool value '
+            'twice. Make sure that you included a rbac_utils.switch_role '
+            'method call inside the test.', str(e))
+
+    @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+                       autospec=True, return_value=False)
+    def test_rbac_utils_switch_roles_with_true_value_twice(self, _):
+        self._mock_list_user_roles_on_project('admin_id')
+        self.rbac_utils.switch_role(self.mock_test_obj, True)
+        e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+                              self.rbac_utils.switch_role, self.mock_test_obj,
+                              True)
+        self.assertIn(
+            '`toggle_rbac_role` must not be called with the same bool value '
+            'twice. Make sure that you included a rbac_utils.switch_role '
+            'method call inside the test.', str(e))
+
+    @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+                       autospec=True, return_value=False)
+    @mock.patch.object(rbac_utils, 'LOG', autospec=True)
+    @mock.patch.object(rbac_utils, 'sys', autospec=True)
+    def test_rbac_utils_switch_roles_with_unhandled_exception(self, mock_sys,
+                                                              mock_log, _):
+        """Test whether throwing an unhandled exception doesn't throw error.
+
+        If a skip exception, say, is thrown then this means that switch_role is
+        never called within the test function. But if an unhandled exception
+        or skip exception is thrown, then this should not result in an error
+        being raised.
+        """
+        self._mock_list_user_roles_on_project('member_id')
+
+        # Skip exception is an example of a legitimate case where `switch_role`
+        # is thrown. AttributeError, on the other hand, is an example of an
+        # unexpected exception being thrown that should be allowed to bubble
+        # up, rather than being obfuscated by `switch_role` error being thrown
+        # instead.
+        unhandled_exceptions = [testtools.TestCase.skipException,
+                                AttributeError]
+
+        for unhandled_exception in unhandled_exceptions:
+            mock_sys.exc_info.return_value = [unhandled_exception]
+
+            # Ordinarily switching to the same role would result in an error,
+            # but because the skipException is thrown before the test finishes,
+            # this is not treated as a failure.
+            self.rbac_utils.switch_role(self.mock_test_obj, False)
+            self.rbac_utils.switch_role(self.mock_test_obj, False)
+            mock_log.error.assert_not_called()
+
+            self.rbac_utils.switch_role(self.mock_test_obj, True)
+            self.rbac_utils.switch_role(self.mock_test_obj, True)
+            mock_log.error.assert_not_called()
+
+    @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+                       autospec=True, return_value=False)
     def test_rbac_utils_switch_role_except_exception(self,
                                                      mock_clear_user_roles):
-        self.rbac_utils.creds_client = mock.Mock()
-        creds_client = self.rbac_utils.creds_client
-        creds_client.roles_client.create_user_role_on_project.side_effect =\
+        roles_client = self.mock_test_obj.os_admin.roles_v3_client
+        roles_client.create_user_role_on_project.side_effect =\
             lib_exc.NotFound
 
         self.assertRaises(lib_exc.NotFound, self.rbac_utils.switch_role,
-                          mock.Mock(), True)
+                          self.mock_test_obj, True)
diff --git a/releasenotes/notes/add-force-delete-backup-test-7e896affd1471328.yaml b/releasenotes/notes/add-force-delete-backup-test-7e896affd1471328.yaml
new file mode 100644
index 0000000..3d81baa
--- /dev/null
+++ b/releasenotes/notes/add-force-delete-backup-test-7e896affd1471328.yaml
@@ -0,0 +1,11 @@
+---
+features:
+  - |
+    Added an RBAC test for force-deleting a backup which enforces the cinder
+    policy action: "volume_extension:backup_admin_actions:force_delete".
+fixes:
+  - |
+    Corrected the policy action in the ``rbac_rule_validation`` decorator
+    for the test ``test_snapshot_force_delete`` from
+    "volume_extension:volume_admin_actions:force_delete" to
+    "volume_extension:snapshot_admin_actions:force_delete".
diff --git a/releasenotes/notes/add-metadef-resource-type-7973621c5e8fff7f.yaml b/releasenotes/notes/add-metadef-resource-type-7973621c5e8fff7f.yaml
new file mode 100644
index 0000000..61bec83
--- /dev/null
+++ b/releasenotes/notes/add-metadef-resource-type-7973621c5e8fff7f.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Adds test for glance's
+    add_metadef_resource_type_association policy.
diff --git a/releasenotes/notes/add-quota-classes-tests-3e61e671f6e131df.yaml b/releasenotes/notes/add-quota-classes-tests-3e61e671f6e131df.yaml
new file mode 100644
index 0000000..656f6a1
--- /dev/null
+++ b/releasenotes/notes/add-quota-classes-tests-3e61e671f6e131df.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Add RBAC tests for cinder os-quota-class-sets API, which cover the
+    policy action "volume_extension:quota_classes".
diff --git a/releasenotes/notes/admin-only-identity-v2-admin-6f382e38d7a690a4.yaml b/releasenotes/notes/admin-only-identity-v2-admin-6f382e38d7a690a4.yaml
new file mode 100644
index 0000000..750a9f1
--- /dev/null
+++ b/releasenotes/notes/admin-only-identity-v2-admin-6f382e38d7a690a4.yaml
@@ -0,0 +1,12 @@
+---
+fixes:
+  - |
+    Removed ``rule`` kwarg from ``rbac_rule_validation`` decorator for identity
+    v2 admin tests, because the identity v2 admin API does not do policy
+    enforcement, and instead checks whether the request object has
+    ``context_is_admin``.
+other:
+  - |
+    Updated the class names for identity v2 tests to include the "Admin"
+    substring, to convey the fact that these tests are only intended
+    to test the v2 admin API, not the v2 API.
diff --git a/releasenotes/notes/config-opts-paths-01e2a5096a1579b8.yaml b/releasenotes/notes/config-opts-paths-01e2a5096a1579b8.yaml
new file mode 100644
index 0000000..3e63c9d
--- /dev/null
+++ b/releasenotes/notes/config-opts-paths-01e2a5096a1579b8.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - |
+    Refactored framework to remove unused "path"
+    argument. Added config options to allow the path
+    to the policy.json files for Nova, Keystone, Cinder,
+    Neutron, and Glance to be configured without needing
+    to manually change code.
diff --git a/releasenotes/notes/encryption-types-c9a2d9a3c1996da4.yaml b/releasenotes/notes/encryption-types-c9a2d9a3c1996da4.yaml
new file mode 100644
index 0000000..7b6ae0c
--- /dev/null
+++ b/releasenotes/notes/encryption-types-c9a2d9a3c1996da4.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - |
+    Adds RBAC tests for the encryption types client.
diff --git a/releasenotes/notes/endpoint-filter-projects-7f64c88659ef0c30.yaml b/releasenotes/notes/endpoint-filter-projects-7f64c88659ef0c30.yaml
new file mode 100644
index 0000000..1537618
--- /dev/null
+++ b/releasenotes/notes/endpoint-filter-projects-7f64c88659ef0c30.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Adds RBAC tests for the project-related endpoints belonging to the
+    OS-EP-FILTER Keystone v3 extension API.
diff --git a/releasenotes/notes/merge-rbac-auth-with-rbac-rule-validation-5d7c286788a95ee9.yaml b/releasenotes/notes/merge-rbac-auth-with-rbac-rule-validation-5d7c286788a95ee9.yaml
new file mode 100644
index 0000000..b96c73a
--- /dev/null
+++ b/releasenotes/notes/merge-rbac-auth-with-rbac-rule-validation-5d7c286788a95ee9.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    Merges `rbac_auth` with `rbac_rule_validation`, because `rbac_auth`
+    decentralized logic from `rbac_rule_validation` without providing any
+    authentication-related utility. This change facilitates code maintenance
+    and code readability.
diff --git a/releasenotes/notes/volume-services-rbac-test-57e69f9952c8746e.yaml b/releasenotes/notes/volume-services-rbac-test-57e69f9952c8746e.yaml
new file mode 100644
index 0000000..5b6f0cd
--- /dev/null
+++ b/releasenotes/notes/volume-services-rbac-test-57e69f9952c8746e.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Added RBAC test for the volume services API, which covers the following
+    policy action: "volume_extension:services:index".
diff --git a/releasenotes/notes/volumes-client-tests-d697a4a75d3e1405.yaml b/releasenotes/notes/volumes-client-tests-d697a4a75d3e1405.yaml
new file mode 100644
index 0000000..5dc9ff3
--- /dev/null
+++ b/releasenotes/notes/volumes-client-tests-d697a4a75d3e1405.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - Added tests for volumes client functions set
+    bootable, reserve, unreserve, and update metadata.
+other:
+  - Renamed update metadata item and delete metadata
+    item tests to accurately reflect what actions are
+    being performed.
diff --git a/requirements.txt b/requirements.txt
index b22bec8..ffc6abe 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,6 @@
 pbr>=1.8 # Apache-2.0
 urllib3>=1.15.1 # MIT
 oslo.log>=3.11.0 # Apache-2.0
+oslo.config>=3.22.0  # Apache-2.0
+tempest>=14.0.0  # Apache-2.0
+stevedore>=1.20.0  # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index a8732dc..09b71eb 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -18,6 +18,7 @@
     Programming Language :: Python :: 3
     Programming Language :: Python :: 3.3
     Programming Language :: Python :: 3.4
+    Programming Language :: Python :: 3.5
 
 [files]
 packages =
diff --git a/tox.ini b/tox.ini
index b4953e7..a004c6e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,21 +13,25 @@
 whitelist_externals = find
 deps = -r{toxinidir}/requirements.txt
        -r{toxinidir}/test-requirements.txt
-commands = 
+commands =
     find . -type f -name "*.pyc" -delete
     ostestr {posargs} --whitelist-file test-whitelist.txt
 
 [testenv:pep8]
 commands = flake8 {posargs}
-		   check-uuid
+           check-uuid --package patrole_tempest_plugin.tests.api
 
 [testenv:uuidgen]
-commands = check-uuid --fix
+commands = check-uuid --package patrole_tempest_plugin.tests.api --fix
 
 [testenv:venv]
 commands = {posargs}
 
 [testenv:cover]
+commands = rm -rf *.pyc
+           rm -rf cover
+           rm -f .coverage
+           nosetests {posargs}
 setenv = VIRTUAL_ENV={envdir}
          NOSE_WITH_COVERAGE=1
          NOSE_COVER_BRANCHES=1
@@ -36,7 +40,7 @@
          NOSE_COVER_HTML_DIR={toxinidir}/cover
          NOSE_WHERE=patrole_tempest_plugin/tests/unit
 whitelist_externals = nosetests
-commands = nosetests {posargs}
+                      rm
 
 [testenv:docs]
 commands = python setup.py build_sphinx
@@ -46,7 +50,7 @@
   sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
 
 [testenv:debug]
-commands = oslo_debug_helper {posargs}
+commands = oslo_debug_helper -t patrole_tempest_plugin/tests {posargs}
 
 [flake8]
 # E123, E125 skipped as they are invalid PEP-8.