Merge "trivial: Fix irrelevant-files regexes for unit tests"
diff --git a/HACKING.rst b/HACKING.rst
index 9992017..9868e39 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -121,3 +121,34 @@
 policies also applies to Patrole.
 
 .. _Tempest logic: https://docs.openstack.org/tempest/latest/HACKING.html#new-tests-for-existing-features
+
+
+Black Box vs. White Box Testing
+-------------------------------
+
+Tempest is a `black box testing framework`_, meaning that it is concerned with
+testing public API endpoints and doesn't concern itself with testing internal
+implementation details. Patrole, as a Tempest plugin, also falls underneath
+the category of black box testing. However, even with policy in code
+documentation, some degree of white box testing is required in order to
+correctly write RBAC tests.
+
+This is because :ref:`policy-in-code` documentation, while useful in many
+respects, is usually quite brief and its main purpose is to help operators
+understand how to customize policy configuration rather than to help
+developers understand complex policy authorization work flows. For example,
+policy in code documentation doesn't make deriving
+:ref:`multiple policies <multiple-policies>` easy. Such documentation also
+doesn't usually mention that a specific parameter needs to be set, or that a
+particular microversion must be enabled, or that a particular set of
+prerequisite API or policy actions must be executed, in order for the policy
+under test to be enforced by the server. This means that test writers must
+account for the internal RBAC implementation in API code in order to correctly
+understand the complete RBAC work flow within an API.
+
+Besides, as mentioned :ref:`elsewhere <design-principles>` in this
+documentation, not all services currently implement policy in code, making
+some degree of white box testing a "necessary evil" for writing robust RBAC
+tests.
+
+.. _black box testing framework: https://docs.openstack.org/tempest/latest/HACKING.html#negative-tests
diff --git a/README.rst b/README.rst
index 31cd3b7..5331445 100644
--- a/README.rst
+++ b/README.rst
@@ -202,8 +202,10 @@
   **admin** and **member** roles. However, other services may use entirely
   different roles or role combinations.
 
-For more information about the member role and its nomenclature,
-please see: `<https://ask.openstack.org/en/question/4759/member-vs-_member_/>`__.
+For more information about RBAC, reference the `rbac-overview`_
+documentation page.
+
+.. _rbac-overview: https://docs.openstack.org/patrole/latest/rbac-overview.html
 
 Unit Tests
 ----------
diff --git a/doc/source/rbac-overview.rst b/doc/source/rbac-overview.rst
index acfd66f..cc47f75 100644
--- a/doc/source/rbac-overview.rst
+++ b/doc/source/rbac-overview.rst
@@ -1,3 +1,5 @@
+.. _rbac-overview:
+
 ==================================
 Role-Based Access Control Overview
 ==================================
diff --git a/patrole_tempest_plugin/config.py b/patrole_tempest_plugin/config.py
index 90d5fba..62337f7 100644
--- a/patrole_tempest_plugin/config.py
+++ b/patrole_tempest_plugin/config.py
@@ -117,7 +117,7 @@
     cfg.StrOpt('report_log_path',
                default='.',
                help="Path (relative or absolute) where the output from "
-                    "'enable_reporting' is logged. This is combined with"
+                    "'enable_reporting' is logged. This is combined with "
                     "report_log_name to generate the full path."),
 ]
 
diff --git a/patrole_tempest_plugin/requirements_authority.py b/patrole_tempest_plugin/requirements_authority.py
index 4697c3b..4d6f25b 100644
--- a/patrole_tempest_plugin/requirements_authority.py
+++ b/patrole_tempest_plugin/requirements_authority.py
@@ -18,9 +18,10 @@
 from oslo_log import log as logging
 
 from tempest import config
-from tempest.lib import exceptions
+from tempest.lib import exceptions as lib_exc
 
 from patrole_tempest_plugin.rbac_authority import RbacAuthority
+from patrole_tempest_plugin import rbac_exceptions
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
@@ -81,7 +82,7 @@
         except yaml.parser.ParserError:
             LOG.error("Error while parsing the requirements YAML file. Did "
                       "you pass a valid component name from the test case?")
-        return None
+        return {}
 
 
 class RequirementsAuthority(RbacAuthority):
@@ -98,10 +99,10 @@
             Defaults to ``[patrole].custom_requirements_file``.
         :param str component: Name of the OpenStack service to be validated.
         """
-        filepath = filepath or CONF.patrole.custom_requirements_file
-
+        self.filepath = filepath or CONF.patrole.custom_requirements_file
         if component is not None:
-            self.roles_dict = RequirementsParser(filepath).parse(component)
+            self.roles_dict = RequirementsParser(self.filepath).parse(
+                component)
         else:
             self.roles_dict = None
 
@@ -116,33 +117,34 @@
         :returns: True if ``role`` is allowed to perform ``rule_name``, else
             False.
         :rtype: bool
-        :raises KeyError: If ``rule_name`` does not exist among the keyed
-            policy names in the custom requirements file.
+        :raises RbacParsingException: If ``rule_name`` does not exist among the
+            keyed policy names in the custom requirements file.
         """
-        if self.roles_dict is None:
-            raise exceptions.InvalidConfiguration(
+        if not self.roles_dict:
+            raise lib_exc.InvalidConfiguration(
                 "Roles dictionary parsed from requirements YAML file is "
                 "empty. Ensure the requirements YAML file is correctly "
                 "formatted.")
         try:
             requirement_roles = self.roles_dict[rule_name]
-
-            for role_reqs in requirement_roles:
-                required_roles = [
-                    role for role in role_reqs if not role.startswith("!")]
-                forbidden_roles = [
-                    role[1:] for role in role_reqs if role.startswith("!")]
-
-                # User must have all required roles
-                required_passed = all([r in roles for r in required_roles])
-                # User must not have any forbidden roles
-                forbidden_passed = all([r not in forbidden_roles
-                                        for r in roles])
-
-                if required_passed and forbidden_passed:
-                    return True
-
-            return False
         except KeyError:
-            raise KeyError("'%s' API is not defined in the requirements YAML "
-                           "file" % rule_name)
+            raise rbac_exceptions.RbacParsingException(
+                "'%s' rule name is not defined in the requirements YAML file: "
+                "%s" % (rule_name, self.filepath))
+
+        for role_reqs in requirement_roles:
+            required_roles = [
+                role for role in role_reqs if not role.startswith("!")]
+            forbidden_roles = [
+                role[1:] for role in role_reqs if role.startswith("!")]
+
+            # User must have all required roles
+            required_passed = all([r in roles for r in required_roles])
+            # User must not have any forbidden roles
+            forbidden_passed = all([r not in forbidden_roles
+                                    for r in roles])
+
+            if required_passed and forbidden_passed:
+                return True
+
+        return False
diff --git a/patrole_tempest_plugin/tests/api/network/rbac_base.py b/patrole_tempest_plugin/tests/api/network/rbac_base.py
index 347651d..dc0ce7f 100644
--- a/patrole_tempest_plugin/tests/api/network/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/network/rbac_base.py
@@ -13,7 +13,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from oslo_serialization import jsonutils as json
+
 from tempest.api.network import base as network_base
+from tempest.lib.common.utils import test_utils
 
 from patrole_tempest_plugin import rbac_utils
 
@@ -72,3 +75,13 @@
             cls.ntp_client = neutron_tempest_manager.network_client
 
         return manager
+
+    @classmethod
+    def create_service_profile(cls):
+        service_profile = cls.ntp_client.create_service_profile(
+            metainfo=json.dumps({'foo': 'bar'}))
+        service_profile_id = service_profile["service_profile"]["id"]
+        cls.addClassResourceCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            cls.ntp_client.delete_service_profile, service_profile_id)
+        return service_profile_id
diff --git a/patrole_tempest_plugin/tests/api/network/test_flavor_service_profile_rbac.py b/patrole_tempest_plugin/tests/api/network/test_flavor_service_profile_rbac.py
new file mode 100644
index 0000000..db0b8f1
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/network/test_flavor_service_profile_rbac.py
@@ -0,0 +1,77 @@
+# Copyright 2018 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.network import rbac_base as base
+
+
+class FlavorsServiceProfileExtRbacTest(base.BaseNetworkExtRbacTest):
+    @classmethod
+    def resource_setup(cls):
+        super(FlavorsServiceProfileExtRbacTest, cls).resource_setup()
+        providers = cls.ntp_client.list_service_providers()
+        if not providers["service_providers"]:
+            raise cls.skipException("No service_providers available.")
+        cls.service_type = providers["service_providers"][0]["service_type"]
+
+        cls.flavor_id = cls.create_flavor()
+        cls.service_profile_id = cls.create_service_profile()
+
+    @classmethod
+    def create_flavor(cls):
+        flavor = cls.ntp_client.create_flavor(service_type=cls.service_type)
+        flavor_id = flavor["flavor"]["id"]
+        cls.addClassResourceCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            cls.ntp_client.delete_flavor, flavor_id)
+        return flavor_id
+
+    def create_flavor_service_profile(self, flavor_id, service_profile_id):
+        self.ntp_client.create_flavor_service_profile(
+            flavor_id, service_profile_id)
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.ntp_client.delete_flavor_service_profile,
+            flavor_id, service_profile_id)
+
+    @decorators.idempotent_id('aa84b4c5-0dd6-4c34-aa81-3a76507f9b81')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["create_flavor_service_profile"])
+    def test_create_flavor_service_profile(self):
+        """Create flavor_service_profile.
+
+        RBAC test for the neutron "create_flavor_service_profile" policy
+        """
+        with self.rbac_utils.override_role(self):
+            self.create_flavor_service_profile(self.flavor_id,
+                                               self.service_profile_id)
+
+    @decorators.idempotent_id('3b680d9e-946a-4670-ab7f-0e4576675833')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["delete_flavor_service_profile"])
+    def test_delete_flavor_service_profile(self):
+        """Delete flavor_service_profile.
+
+        RBAC test for the neutron "delete_flavor_service_profile" policy
+        """
+        self.create_flavor_service_profile(self.flavor_id,
+                                           self.service_profile_id)
+
+        with self.rbac_utils.override_role(self):
+            self.ntp_client.delete_flavor_service_profile(
+                self.flavor_id, self.service_profile_id)
diff --git a/patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py b/patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py
index dea95ba..76c0db3 100644
--- a/patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_flavors_rbac.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_serialization import jsonutils as json
-
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
@@ -118,72 +116,3 @@
 
         with self.rbac_utils.override_role(self):
             self.ntp_client.list_flavors()
-
-
-class FlavorsServiceProfileExtRbacTest(base.BaseNetworkExtRbacTest):
-    @classmethod
-    def resource_setup(cls):
-        super(FlavorsServiceProfileExtRbacTest, cls).resource_setup()
-        providers = cls.ntp_client.list_service_providers()
-        if not providers["service_providers"]:
-            raise cls.skipException("No service_providers available.")
-        cls.service_type = providers["service_providers"][0]["service_type"]
-
-        cls.flavor_id = cls.create_flavor()
-        cls.service_profile_id = cls.create_service_profile()
-
-    @classmethod
-    def create_flavor(cls):
-        flavor = cls.ntp_client.create_flavor(service_type=cls.service_type)
-        flavor_id = flavor["flavor"]["id"]
-        cls.addClassResourceCleanup(
-            test_utils.call_and_ignore_notfound_exc,
-            cls.ntp_client.delete_flavor, flavor_id)
-        return flavor_id
-
-    @classmethod
-    def create_service_profile(cls):
-        service_profile = cls.ntp_client.create_service_profile(
-            metainfo=json.dumps({'foo': 'bar'}))
-        service_profile_id = service_profile["service_profile"]["id"]
-        cls.addClassResourceCleanup(
-            test_utils.call_and_ignore_notfound_exc,
-            cls.ntp_client.delete_service_profile, service_profile_id)
-        return service_profile_id
-
-    def create_flavor_service_profile(self, flavor_id, service_profile_id):
-        self.ntp_client.create_flavor_service_profile(
-            flavor_id, service_profile_id)
-        self.addCleanup(
-            test_utils.call_and_ignore_notfound_exc,
-            self.ntp_client.delete_flavor_service_profile,
-            flavor_id, service_profile_id)
-
-    @decorators.idempotent_id('aa84b4c5-0dd6-4c34-aa81-3a76507f9b81')
-    @rbac_rule_validation.action(service="neutron",
-                                 rules=["create_flavor_service_profile"])
-    def test_create_flavor_service_profile(self):
-        """Create flavor_service_profile.
-
-        RBAC test for the neutron "create_flavor_service_profile" policy
-        """
-        with self.rbac_utils.override_role(self):
-            self.create_flavor_service_profile(self.flavor_id,
-                                               self.service_profile_id)
-
-    @decorators.idempotent_id('3b680d9e-946a-4670-ab7f-0e4576675833')
-    @rbac_rule_validation.action(service="neutron",
-                                 rules=["get_flavor_service_profile",
-                                        "delete_flavor_service_profile"],
-                                 expected_error_codes=[404, 403])
-    def test_delete_flavor_service_profile(self):
-        """Delete flavor_service_profile.
-
-        RBAC test for the neutron "delete_flavor_service_profile" policy
-        """
-        self.create_flavor_service_profile(self.flavor_id,
-                                           self.service_profile_id)
-
-        with self.rbac_utils.override_role(self):
-            self.ntp_client.delete_flavor_service_profile(
-                self.flavor_id, self.service_profile_id)
diff --git a/patrole_tempest_plugin/tests/api/network/test_service_profile_rbac.py b/patrole_tempest_plugin/tests/api/network/test_service_profile_rbac.py
new file mode 100644
index 0000000..9e82835
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/network/test_service_profile_rbac.py
@@ -0,0 +1,73 @@
+# Copyright 2018 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.network import rbac_base as base
+
+
+class ServiceProfileExtRbacTest(base.BaseNetworkExtRbacTest):
+    @decorators.idempotent_id('6ce76efa-7400-44c1-80ec-58f79b1d89ca')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["create_service_profile"])
+    def test_create_service_profile(self):
+        """Create service profile
+
+        RBAC test for the neutron "create_service_profile" policy
+        """
+        with self.rbac_utils.override_role(self):
+            self.create_service_profile()
+
+    @decorators.idempotent_id('e4c473b7-3ae9-4a2e-8cac-848f7b01187d')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["get_service_profile"],
+                                 expected_error_codes=[404])
+    def test_show_service_profile(self):
+        """Show service profile
+
+        RBAC test for the neutron "get_service_profile" policy
+        """
+        profile_id = self.create_service_profile()
+        with self.rbac_utils.override_role(self):
+            self.ntp_client.show_service_profile(profile_id)
+
+    @decorators.idempotent_id('a3dd719d-4cd3-40cc-b4f1-5642e2717adf')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["get_service_profile",
+                                        "update_service_profile"],
+                                 expected_error_codes=[404, 403])
+    def test_update_service_profile(self):
+        """Update service profile
+
+        RBAC test for the neutron "update_service_profile" policy
+        """
+        profile_id = self.create_service_profile()
+        with self.rbac_utils.override_role(self):
+            self.ntp_client.update_service_profile(profile_id, enabled=False)
+
+    @decorators.idempotent_id('926b60c2-04fe-4339-aa44-bf27121392e8')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["get_service_profile",
+                                        "delete_service_profile"],
+                                 expected_error_codes=[404, 403])
+    def test_delete_service_profile(self):
+        """Delete service profile
+
+        RBAC test for the neutron "delete_service_profile" policy
+        """
+        profile_id = self.create_service_profile()
+        with self.rbac_utils.override_role(self):
+            self.ntp_client.delete_service_profile(profile_id)
diff --git a/patrole_tempest_plugin/tests/unit/test_requirements_authority.py b/patrole_tempest_plugin/tests/unit/test_requirements_authority.py
index 0f7310e..94af81f 100644
--- a/patrole_tempest_plugin/tests/unit/test_requirements_authority.py
+++ b/patrole_tempest_plugin/tests/unit/test_requirements_authority.py
@@ -17,6 +17,7 @@
 from tempest.lib import exceptions
 from tempest.tests import base
 
+from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import requirements_authority as req_auth
 
 
@@ -50,17 +51,17 @@
                           self.rbac_auth.allowed, "", [""])
 
     def test_auth_allowed_role_in_api(self):
-        self.rbac_auth.roles_dict = {'api': [['_member_']]}
-        self.assertTrue(self.rbac_auth.allowed("api", ["_member_"]))
+        self.rbac_auth.roles_dict = {'rule': [['_member_']]}
+        self.assertTrue(self.rbac_auth.allowed("rule", ["_member_"]))
 
     def test_auth_allowed_role_not_in_api(self):
-        self.rbac_auth.roles_dict = {'api': [['_member_']]}
-        self.assertFalse(self.rbac_auth.allowed("api", "support_member"))
+        self.rbac_auth.roles_dict = {'rule': [['_member_']]}
+        self.assertFalse(self.rbac_auth.allowed("rule", "support_member"))
 
-    def test_parser_get_allowed_except_keyerror(self):
-        self.rbac_auth.roles_dict = {}
-        self.assertRaises(KeyError, self.rbac_auth.allowed,
-                          "api", "support_member")
+    def test_parser_get_allowed_invalid_rule_raises_parsing_exception(self):
+        self.rbac_auth.roles_dict = {"foo": "bar"}
+        self.assertRaises(rbac_exceptions.RbacParsingException,
+                          self.rbac_auth.allowed, "baz", "support_member")
 
     def test_parser_init(self):
         req_auth.RequirementsParser(self.yaml_test_file)
@@ -90,7 +91,7 @@
         self.rbac_auth.roles_dict = \
             req_auth.RequirementsParser.parse("Failure")
 
-        self.assertIsNone(self.rbac_auth.roles_dict)
+        self.assertFalse(self.rbac_auth.roles_dict)
         self.assertRaises(exceptions.InvalidConfiguration,
                           self.rbac_auth.allowed, "", [""])
 
@@ -99,10 +100,10 @@
         considered as part of role itself.
         """
 
-        self.rbac_auth.roles_dict = {'api': [['!admin']]}
-        self.assertTrue(self.rbac_auth.allowed("api", ["member"]))
-        self.assertTrue(self.rbac_auth.allowed("api", ["!admin"]))
-        self.assertFalse(self.rbac_auth.allowed("api", ["admin"]))
+        self.rbac_auth.roles_dict = {'rule': [['!admin']]}
+        self.assertTrue(self.rbac_auth.allowed("rule", ["member"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["!admin"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["admin"]))
 
 
 class RequirementsAuthorityMultiRoleTest(BaseRequirementsAuthorityTest):
@@ -112,39 +113,39 @@
         considered as part of role itself.
         """
 
-        self.rbac_auth.roles_dict = {'api': [['member', '!admin']]}
-        self.assertFalse(self.rbac_auth.allowed("api", ["member", "admin"]))
-        self.assertTrue(self.rbac_auth.allowed("api", ["member", "!admin"]))
+        self.rbac_auth.roles_dict = {'rule': [['member', '!admin']]}
+        self.assertFalse(self.rbac_auth.allowed("rule", ["member", "admin"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["member", "!admin"]))
 
     def test_auth_allowed_single_rule_scenario(self):
         # member and support and not admin and not manager
-        self.rbac_auth.roles_dict = {'api': [['member', 'support',
-                                              '!admin', '!manager']]}
+        self.rbac_auth.roles_dict = {'rule': [['member', 'support',
+                                               '!admin', '!manager']]}
 
         # User is member and support and not manager or admin
-        self.assertTrue(self.rbac_auth.allowed("api", ["member",
-                                                       "support"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["member",
+                                                        "support"]))
 
         # User is member and not manager or admin, but not support
-        self.assertFalse(self.rbac_auth.allowed("api", ["member"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["member"]))
 
         # User is support and not manager or admin, but not member
-        self.assertFalse(self.rbac_auth.allowed("api", ["support"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["support"]))
 
         # User is member and support and not manager, but have admin role
-        self.assertFalse(self.rbac_auth.allowed("api", ["member",
-                                                        "support",
-                                                        "admin"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["member",
+                                                         "support",
+                                                         "admin"]))
 
         # User is member and not manager, but have admin role and not support
-        self.assertFalse(self.rbac_auth.allowed("api", ["member",
-                                                        "admin"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["member",
+                                                         "admin"]))
 
         # User is member and support, but have manager and admin roles
-        self.assertFalse(self.rbac_auth.allowed("api", ["member",
-                                                        "support",
-                                                        "admin",
-                                                        "manager"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["member",
+                                                         "support",
+                                                         "admin",
+                                                         "manager"]))
 
     def test_auth_allowed_multi_rule_scenario(self):
         rules = [
@@ -152,36 +153,36 @@
             ['member', 'admin'],
             ["manager"]
         ]
-        self.rbac_auth.roles_dict = {'api': rules}
+        self.rbac_auth.roles_dict = {'rule': rules}
 
         # Not a single role allows viewer
-        self.assertFalse(self.rbac_auth.allowed("api", ["viewer"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["viewer"]))
         # We have no rule that allows support and admin
-        self.assertFalse(self.rbac_auth.allowed("api", ["support",
-                                                        "admin"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["support",
+                                                         "admin"]))
         # There is no rule that requires member without additional requirements
-        self.assertFalse(self.rbac_auth.allowed("api", ["member"]))
+        self.assertFalse(self.rbac_auth.allowed("rule", ["member"]))
 
         # Pass with rules[2]
-        self.assertTrue(self.rbac_auth.allowed("api", ["manager"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["manager"]))
         # Pass with rules[0]
-        self.assertTrue(self.rbac_auth.allowed("api", ["member",
-                                                       "support"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["member",
+                                                        "support"]))
         # Pass with rules[1]
-        self.assertTrue(self.rbac_auth.allowed("api", ["member",
-                                                       "admin"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["member",
+                                                        "admin"]))
         # Pass with rules[2]
-        self.assertTrue(self.rbac_auth.allowed("api", ["manager",
-                                                       "admin"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["manager",
+                                                        "admin"]))
         # Pass with rules[1]
-        self.assertTrue(self.rbac_auth.allowed("api", ["member",
-                                                       "support",
-                                                       "admin"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["member",
+                                                        "support",
+                                                        "admin"]))
         # Pass with rules[1]
-        self.assertTrue(self.rbac_auth.allowed("api", ["member",
-                                                       "support",
-                                                       "admin",
-                                                       "manager"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["member",
+                                                        "support",
+                                                        "admin",
+                                                        "manager"]))
         # Pass with rules[2]
-        self.assertTrue(self.rbac_auth.allowed("api", ["admin",
-                                                       "manager"]))
+        self.assertTrue(self.rbac_auth.allowed("rule", ["admin",
+                                                        "manager"]))