Merge "Removing unused admin_client"
diff --git a/patrole_tempest_plugin/rbac_exceptions.py b/patrole_tempest_plugin/rbac_exceptions.py
index c6165ff..ee42e19 100644
--- a/patrole_tempest_plugin/rbac_exceptions.py
+++ b/patrole_tempest_plugin/rbac_exceptions.py
@@ -26,3 +26,7 @@
 
 class RbacOverPermission (exceptions.TempestException):
     message = "Action performed that should not be permitted"
+
+
+class RbacInvalidService (exceptions.TempestException):
+    message = "Attempted to test an invalid service"
diff --git a/patrole_tempest_plugin/rbac_policy_parser.py b/patrole_tempest_plugin/rbac_policy_parser.py
index 045a9f8..9926613 100644
--- a/patrole_tempest_plugin/rbac_policy_parser.py
+++ b/patrole_tempest_plugin/rbac_policy_parser.py
@@ -20,6 +20,8 @@
 from oslo_policy import generator
 from oslo_policy import policy
 
+from tempest.common import credentials_factory as credentials
+
 from patrole_tempest_plugin import rbac_exceptions
 
 LOG = logging.getLogger(__name__)
@@ -57,7 +59,17 @@
         :param service: type string
         :param path: type string
         """
-        service = service.lower().strip()
+        # First check if the service is valid
+        service = service.lower().strip() if service else None
+        self.admin_mgr = credentials.AdminManager()
+        services = self.admin_mgr.identity_services_v3_client.\
+            list_services()['services']
+        service_names = [s['name'] for s in services]
+        if not service or not any(service in name for name in service_names):
+            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:
@@ -65,7 +77,7 @@
 
         policy_data = "{}"
 
-        # First check whether policy file exists.
+        # 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.
diff --git a/patrole_tempest_plugin/rbac_rule_validation.py b/patrole_tempest_plugin/rbac_rule_validation.py
index 36784b7..284d8f0 100644
--- a/patrole_tempest_plugin/rbac_rule_validation.py
+++ b/patrole_tempest_plugin/rbac_rule_validation.py
@@ -41,6 +41,12 @@
 
             try:
                 func(*args)
+            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:
                 if allowed:
                     msg = ("Role %s was not allowed to perform %s." %
diff --git a/patrole_tempest_plugin/rbac_utils.py b/patrole_tempest_plugin/rbac_utils.py
index 69c6ccd..ae018de 100644
--- a/patrole_tempest_plugin/rbac_utils.py
+++ b/patrole_tempest_plugin/rbac_utils.py
@@ -88,8 +88,8 @@
 
         finally:
             test_obj.auth_provider.clear_auth()
-            # Sleep to avoid 401 errors caused by rounding
-            # In timing of fernet token creation
+            # Sleep to avoid 401 errors caused by rounding in timing of fernet
+            # token creation.
             time.sleep(1)
             test_obj.auth_provider.set_auth()
 
diff --git a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_password_rbac.py b/patrole_tempest_plugin/tests/api/compute/admin/test_admin_password_rbac.py
index 7d057c5..c1c92d9 100644
--- a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_password_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/admin/test_admin_password_rbac.py
@@ -59,10 +59,3 @@
         self.client.change_password(
             self.server_id,
             adminPass=data_utils.rand_password())
-
-    @rbac_rule_validation.action(
-        service="nova", rule="os_compute_api:os-admin-password:discoverable")
-    @decorators.idempotent_id('379fce8a-f1ff-11e6-bc64-92361f002671')
-    def test_admin_password_discoverable(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.extensions_client.show_extension('os-admin-password')
diff --git a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_server_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/admin/test_admin_server_actions_rbac.py
index 888f9a4..b2bc2b6 100644
--- a/patrole_tempest_plugin/tests/api/compute/admin/test_admin_server_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/admin/test_admin_server_actions_rbac.py
@@ -72,11 +72,3 @@
     def test_reset_network(self):
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.client.reset_network(self.server_id)
-
-    @rbac_rule_validation.action(
-        service="nova",
-        rule="os_compute_api:os-admin-actions:discoverable")
-    @decorators.idempotent_id('e9d2991f-a05e-4116-881b-e2a82bb173cf')
-    def test_admin_actions_discoverable(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.extensions_client.show_extension('os-admin-actions')
diff --git a/patrole_tempest_plugin/tests/api/compute/rbac_base.py b/patrole_tempest_plugin/tests/api/compute/rbac_base.py
index fc24c03..de544bb 100644
--- a/patrole_tempest_plugin/tests/api/compute/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/compute/rbac_base.py
@@ -23,7 +23,8 @@
 
 
 class BaseV2ComputeRbacTest(compute_base.BaseV2ComputeTest):
-    credentials = ['admin']
+
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -33,11 +34,6 @@
                 '%s skipped as RBAC flag not enabled' % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseV2ComputeRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseV2ComputeRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
@@ -46,7 +42,7 @@
 
 class BaseV2ComputeAdminRbacTest(compute_base.BaseV2ComputeAdminTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -56,11 +52,6 @@
                 '%s skipped as RBAC flag not enabled' % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseV2ComputeAdminRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseV2ComputeAdminRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
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 8416fe9..e7cca4a 100644
--- a/patrole_tempest_plugin/tests/api/identity/v2/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/identity/v2/rbac_base.py
@@ -25,7 +25,7 @@
 
 class BaseIdentityV2AdminRbacTest(base.BaseIdentityV2AdminTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -35,11 +35,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseIdentityV2AdminRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseIdentityV2AdminRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
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 aa9170a..4cd3d43 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
@@ -19,7 +19,6 @@
 from tempest.lib import decorators
 
 from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.rbac_utils import rbac_utils
 from patrole_tempest_plugin.tests.api.identity.v2 import rbac_base
 
 CONF = config.CONF
@@ -28,7 +27,7 @@
 class IdentityRoleV2AdminRbacTest(rbac_base.BaseIdentityV2AdminRbacTest):
 
     def tearDown(self):
-        rbac_utils.switch_role(self, switchToRbacRole=False)
+        self.rbac_utils.switch_role(self, switchToRbacRole=False)
         super(IdentityRoleV2AdminRbacTest, self).tearDown()
 
     @classmethod
@@ -43,10 +42,10 @@
                         self.roles_client.delete_role, role['id'])
         return role
 
-    def _create_tenant_user_role(self):
-        role = self._create_role()
+    def _create_tenant_user_and_role(self):
         tenant = self._create_tenant()
         user = self._create_user(tenantid=tenant['id'])
+        role = self._create_role()
         return tenant, user, role
 
     def _create_role_on_project(self, tenant, user, role):
@@ -67,7 +66,7 @@
         RBAC test for Identity Admin 2.0 role-create
         """
 
-        rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self._create_role()
 
     @rbac_rule_validation.action(service="keystone",
@@ -81,7 +80,7 @@
         """
         role = self._create_role()
 
-        rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.delete_role(role['id'])
 
     @rbac_rule_validation.action(service="keystone",
@@ -95,7 +94,7 @@
         """
         role = self._create_role()
 
-        rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.show_role(role['id'])
 
     @rbac_rule_validation.action(service="keystone",
@@ -107,7 +106,7 @@
 
         RBAC test for Identity Admin 2.0 role-list
         """
-        rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.list_roles()
 
     @rbac_rule_validation.action(service="keystone",
@@ -119,8 +118,8 @@
 
         RBAC test for Identity Admin 2.0 create_user_role_on_project
         """
-        tenant, user, role = self._create_tenant_user_role()
-        rbac_utils.switch_role(self, switchToRbacRole=True)
+        tenant, user, role = self._create_tenant_user_and_role()
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self._create_role_on_project(tenant, user, role)
 
     @rbac_rule_validation.action(service="keystone",
@@ -132,10 +131,10 @@
 
         RBAC test for Identity Admin 2.0 delete_role_from_user_on_project
         """
-        tenant, user, role = self._create_tenant_user_role()
+        tenant, user, role = self._create_tenant_user_and_role()
         self._create_role_on_project(tenant, user, role)
 
-        rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.delete_role_from_user_on_project(
             tenant['id'], user['id'], role['id'])
 
@@ -151,6 +150,6 @@
         tenant = self._create_tenant()
         user = self._create_user(tenantid=tenant['id'])
 
-        rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.list_user_roles_on_project(
             tenant['id'], user['id'])
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 1fccbe1..3f045f2 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
@@ -25,7 +25,7 @@
 
 class BaseIdentityV3RbacAdminTest(base.BaseIdentityV3AdminTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -35,11 +35,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseIdentityV3RbacAdminTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseIdentityV3RbacAdminTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
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 16e2dce..bbdf49d 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
@@ -33,9 +33,8 @@
 
     def _create_group(self):
         """Creates a group for test."""
-        name = data_utils.rand_name('Group')
-        group = self.groups_client \
-                    .create_group(name=name)['group']
+        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'])
diff --git a/patrole_tempest_plugin/tests/api/image/rbac_base.py b/patrole_tempest_plugin/tests/api/image/rbac_base.py
index 9725ffc..daea89c 100644
--- a/patrole_tempest_plugin/tests/api/image/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/image/rbac_base.py
@@ -21,7 +21,7 @@
 
 class BaseV1ImageRbacTest(image_base.BaseV1ImageTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -31,11 +31,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseV1ImageRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseV1ImageRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
@@ -44,7 +39,7 @@
 
 class BaseV2ImageRbacTest(image_base.BaseV2ImageTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -54,11 +49,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseV2ImageRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseV2ImageRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
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 81d03d6..81bad5f 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
@@ -33,6 +33,7 @@
     @classmethod
     def resource_setup(cls):
         super(ImagesMemberRbacTest, cls).resource_setup()
+        cls.tenant_id = cls.image_member_client.tenant_id
         cls.alt_tenant_id = cls.alt_image_member_client.tenant_id
 
     @classmethod
@@ -120,15 +121,18 @@
 
         RBAC test for the glance modify_member policy
         """
-        image_id = self.create_image()['id']
-        self.alt_image_member_client.create_image_member(
+        image_id = self.create_image(visibility='shared')['id']
+        self.image_member_client.create_image_member(
             image_id,
-            member=self.image_client.tenant_id)
+            member=self.tenant_id)
+        self.image_member_client.update_image_member(
+            image_id, self.tenant_id,
+            status='accepted')
         # Toggle role and update member
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.image_member_client.update_image_member(
-            image_id, self.image_client.tenant_id,
-            status='accepted')
+            image_id, self.tenant_id,
+            status='pending')
 
     @rbac_rule_validation.action(service="glance",
                                  rule="get_members")
diff --git a/patrole_tempest_plugin/tests/api/network/rbac_base.py b/patrole_tempest_plugin/tests/api/network/rbac_base.py
index 64ae985..af5d110 100644
--- a/patrole_tempest_plugin/tests/api/network/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/network/rbac_base.py
@@ -23,7 +23,7 @@
 
 class BaseNetworkRbacTest(network_base.BaseNetworkTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -33,11 +33,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseNetworkRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseNetworkRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
diff --git a/patrole_tempest_plugin/tests/api/orchestration/rbac_base.py b/patrole_tempest_plugin/tests/api/orchestration/rbac_base.py
index eb21637..562c66e 100644
--- a/patrole_tempest_plugin/tests/api/orchestration/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/orchestration/rbac_base.py
@@ -21,7 +21,7 @@
 
 class BaseOrchestrationRbacTest(heat_base.BaseOrchestrationTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -31,11 +31,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseOrchestrationRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseOrchestrationRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
diff --git a/patrole_tempest_plugin/tests/api/volume/rbac_base.py b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
index e826f3a..005986d 100644
--- a/patrole_tempest_plugin/tests/api/volume/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
@@ -21,7 +21,7 @@
 
 class BaseVolumeRbacTest(vol_base.BaseVolumeTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -31,11 +31,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseVolumeRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseVolumeRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
@@ -44,7 +39,7 @@
 
 class BaseVolumeAdminRbacTest(vol_base.BaseVolumeAdminTest):
 
-    credentials = ['admin']
+    credentials = ['admin', 'primary']
 
     @classmethod
     def skip_checks(cls):
@@ -54,11 +49,6 @@
                 "%s skipped as RBAC Flag not enabled" % cls.__name__)
 
     @classmethod
-    def setup_credentials(cls):
-        super(BaseVolumeAdminRbacTest, cls).setup_credentials()
-        cls.os = cls.os_adm
-
-    @classmethod
     def setup_clients(cls):
         super(BaseVolumeAdminRbacTest, cls).setup_clients()
         cls.auth_provider = cls.os.auth_provider
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 35aaa82..edc63b8 100644
--- a/patrole_tempest_plugin/tests/unit/test_rbac_policy_parser.py
+++ b/patrole_tempest_plugin/tests/unit/test_rbac_policy_parser.py
@@ -19,6 +19,7 @@
 from tempest import config
 from tempest.tests import base
 
+from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_policy_parser
 
 CONF = config.CONF
@@ -28,6 +29,8 @@
 
     def setUp(self):
         super(RbacPolicyTest, self).setUp()
+        self.mock_admin_mgr = mock.patch.object(
+            rbac_policy_parser, 'credentials').start()
 
         current_directory = os.path.dirname(os.path.realpath(__file__))
         self.custom_policy_file = os.path.join(current_directory,
@@ -42,6 +45,35 @@
         self.tenant_policy_file = os.path.join(current_directory,
                                                'resources',
                                                'tenant_rbac_policy.json')
+        services = {
+            'services': [
+                {'name': 'cinder', 'links': 'link', 'enabled': True,
+                 'type': 'volume', 'id': 'id',
+                 'description': 'description'},
+                {'name': 'glance', 'links': 'link', 'enabled': True,
+                 'type': 'image', 'id': 'id',
+                 'description': 'description'},
+                {'name': 'nova', 'links': 'link', 'enabled': True,
+                 'type': 'compute', 'id': 'id',
+                 'description': 'description'},
+                {'name': 'keystone', 'links': 'link', 'enabled': True,
+                 'type': 'identity', 'id': 'id',
+                 'description': 'description'},
+                {'name': 'heat', 'links': 'link', 'enabled': True,
+                 'type': 'orchestration', 'id': 'id',
+                 'description': 'description'},
+                {'name': 'neutron', 'links': 'link', 'enabled': True,
+                 'type': 'networking', 'id': 'id',
+                 'description': 'description'},
+                {'name': 'test', 'links': 'link', 'enabled': True,
+                 'type': 'unit_test', 'id': 'id',
+                 'description': 'description'}
+            ]
+        }
+
+        self.mock_admin_mgr.AdminManager.return_value.\
+            identity_services_v3_client.list_services.return_value = \
+            services
 
     @mock.patch.object(rbac_policy_parser, 'LOG', autospec=True)
     def test_custom_policy(self, m_log):
@@ -203,3 +235,33 @@
                 mock_try_rule.assert_called_once_with(
                     rule, expected_target, expected_access_data, mock.ANY)
                 mock_try_rule.reset_mock()
+
+    @mock.patch.object(rbac_policy_parser, 'LOG', autospec=True)
+    def test_invalid_service_raises_exception(self, m_log):
+        test_tenant_id = mock.sentinel.tenant_id
+        test_user_id = mock.sentinel.user_id
+        service = 'invalid_service'
+
+        self.assertRaises(rbac_exceptions.RbacInvalidService,
+                          rbac_policy_parser.RbacPolicyParser,
+                          test_tenant_id,
+                          test_user_id,
+                          service)
+
+        m_log.debug.assert_called_once_with(
+            "{0} is NOT a valid service.".format(str(service)))
+
+    @mock.patch.object(rbac_policy_parser, 'LOG', autospec=True)
+    def test_service_is_none_raises_exception(self, m_log):
+        test_tenant_id = mock.sentinel.tenant_id
+        test_user_id = mock.sentinel.user_id
+        service = None
+
+        self.assertRaises(rbac_exceptions.RbacInvalidService,
+                          rbac_policy_parser.RbacPolicyParser,
+                          test_tenant_id,
+                          test_user_id,
+                          service)
+
+        m_log.debug.assert_called_once_with(
+            "{0} is NOT a valid service.".format(str(service)))