Add secure-rbac test for Secrets across projects

This patch adds rbac tests to the Secrets resource to test access
across different projects.

This patch also changes the Reader, Member, and Admin test suite
inheritance to remove code duplication.

Change-Id: Icf5a52925244dfe7d98ba9cfba549fce67be44db
diff --git a/barbican_tempest_plugin/tests/rbac/v1/base.py b/barbican_tempest_plugin/tests/rbac/v1/base.py
index bd70579..75541aa 100644
--- a/barbican_tempest_plugin/tests/rbac/v1/base.py
+++ b/barbican_tempest_plugin/tests/rbac/v1/base.py
@@ -47,7 +47,10 @@
     _created_users = None
     created_objects = {}
 
-    credentials = ['system_admin']
+    credentials = [
+        'system_admin',
+        'project_alt_member'
+    ]
 
     # TODO(dmendiza): remove this and use the clients instead
     @classmethod
@@ -76,6 +79,8 @@
                 cls._setup_new_user_client(project_id, 'member'))
         setattr(cls, 'os_project_reader',
                 cls._setup_new_user_client(project_id, 'reader'))
+        setattr(cls, 'os_project_other_member',
+                cls._setup_new_user_client(project_id, 'member'))
 
     @classmethod
     def _setup_new_user_client(cls, project_id, role):
@@ -122,7 +127,7 @@
     def setup_clients(cls):
         super().setup_clients()
 
-        # setup clients for primary persona
+        # set up member clients
         os = cls.os_project_member
         cls.secret_client = os.secret_v1.SecretClient()
         cls.secret_metadata_client = os.secret_v1.SecretMetadataClient(
@@ -154,6 +159,7 @@
         cls.admin_secret_metadata_client = adm.secret_v1.SecretMetadataClient(
             service='key-manager'
         )
+        cls.other_client = cls.os_project_alt_member.secret_v1.SecretClient()
 
     @classmethod
     def resource_setup(cls):
@@ -176,7 +182,9 @@
             for secret_uuid in list(cls.created_objects['secret']):
                 cls.admin_secret_client.delete_secret(secret_uuid)
                 cls.created_objects['secret'].remove(secret_uuid)
-            for client in [cls.secret_client, cls.admin_secret_client]:
+            for client in [cls.secret_client,
+                           cls.admin_secret_client,
+                           cls.other_client]:
                 client.cleanup()
         finally:
             super(BarbicanV1RbacBase, cls).resource_cleanup()
@@ -234,3 +242,14 @@
             payload_content_encoding="base64",
             name=secret_name
         )
+
+    def create_other_project_secret(self, secret_name, payload=None):
+        kwargs = {
+            'name': secret_name,
+            'secret_type': 'passphrase',
+        }
+        if payload is not None:
+            kwargs['payload'] = payload
+            kwargs['payload_content_type'] = 'text/plain'
+        resp = self.other_client.create_secret(**kwargs)
+        return self.other_client.ref_to_uuid(resp['secret_ref'])
diff --git a/barbican_tempest_plugin/tests/rbac/v1/test_secrets.py b/barbican_tempest_plugin/tests/rbac/v1/test_secrets.py
index 9ceeec9..7df6df2 100644
--- a/barbican_tempest_plugin/tests/rbac/v1/test_secrets.py
+++ b/barbican_tempest_plugin/tests/rbac/v1/test_secrets.py
@@ -23,7 +23,7 @@
 CONF = config.CONF
 
 
-class BarbicanV1RbacSecrets(metaclass=abc.ABCMeta):
+class BarbicanV1RbacSecrets:
 
     @abc.abstractmethod
     def test_create_secret(self):
@@ -86,91 +86,50 @@
         """
         raise NotImplementedError
 
+    @abc.abstractmethod
+    def test_get_other_project_secret(self):
+        """Test get_secrets policy
 
-class ProjectMemberTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
+        Testing: GET /v1/secrets/{secret_id}
+        This test must check:
+          * whether the persona can get secret metadata for a secret that
+            belongs to a different project
+        """
+        raise NotImplementedError
 
-    @classmethod
-    def setup_clients(cls):
-        super().setup_clients()
-        cls.client = cls.os_project_member.secret_v1.SecretClient()
+    @abc.abstractmethod
+    def test_get_other_project_secret_payload(self):
+        """Test get_secrets policy
 
-    def test_create_secret(self):
-        """Test add_secret policy."""
-        self.client.create_secret(name='test_create_secret')
+        Testing: GET /v1/secrets/{secret_id}/payload
+        This test must check:
+          * whether the persona can get secret payload for a secret that
+            belongs to a different project
+        """
+        raise NotImplementedError
 
-        key = rbac_base.create_aes_key()
-        expire_time = (datetime.utcnow() + timedelta(days=5))
-        self.client.create_secret(
-            name='test_create_secret2',
-            expiration=expire_time.isoformat(), algorithm="aes",
-            bit_length=256, mode="cbc", payload=key,
-            payload_content_type="application/octet-stream",
-            payload_content_encoding="base64"
-        )
+    @abc.abstractmethod
+    def test_put_other_project_secret_payload(self):
+        """Test put_secret policy.
 
-    def test_list_secrets(self):
-        """Test get_secrets policy."""
-        # create two secrets
-        self.create_empty_secret_admin('test_list_secrets')
-        self.create_empty_secret_admin('test_list_secrets_2')
+        Testing: PUT /v1/secrets/{secret_id}
+        This test must check:
+          * whether the persona can PUT the secret payload in a 2-step
+            create when the first step is done by a member of a different
+            project.
+        """
+        raise NotImplementedError
 
-        # list secrets with name secret_1
-        resp = self.client.list_secrets(name='test_list_secrets')
-        secrets = resp['secrets']
-        self.assertEqual('test_list_secrets', secrets[0]['name'])
+    @abc.abstractmethod
+    def test_delete_other_project_secret(self):
+        """Test delete_secret policy.
 
-        # list secrets with name secret_2
-        resp = self.client.list_secrets(name='test_list_secrets_2')
-        secrets = resp['secrets']
-        self.assertEqual('test_list_secrets_2', secrets[0]['name'])
-
-        # list all secrets
-        resp = self.client.list_secrets()
-        secrets = resp['secrets']
-        self.assertGreaterEqual(len(secrets), 2)
-
-    def test_delete_secret(self):
-        """Test delete_secrets policy."""
-        sec = self.create_empty_secret_admin('test_delete_secret_1')
-        uuid = self.client.ref_to_uuid(sec['secret_ref'])
-        self.client.delete_secret(uuid)
-
-    def test_get_secret(self):
-        """Test get_secret policy."""
-        sec = self.create_empty_secret_admin('test_get_secret')
-        uuid = self.client.ref_to_uuid(sec['secret_ref'])
-        resp = self.client.get_secret_metadata(uuid)
-        self.assertEqual(uuid, self.client.ref_to_uuid(resp['secret_ref']))
-
-    def test_get_secret_payload(self):
-        """Test get_secret payload policy."""
-        key, sec = self.create_aes_secret_admin('test_get_secret_payload')
-        uuid = self.client.ref_to_uuid(sec['secret_ref'])
-
-        # Retrieve the payload
-        payload = self.client.get_secret_payload(uuid)
-        self.assertEqual(key, base64.b64encode(payload))
-
-    def test_put_secret_payload(self):
-        """Test put_secret policy."""
-        sec = self.create_empty_secret_admin('test_put_secret_payload')
-        uuid = self.client.ref_to_uuid(sec['secret_ref'])
-
-        key = rbac_base.create_aes_key()
-
-        # Associate the payload with the created secret
-        self.client.put_secret_payload(uuid, key)
-
-        # Retrieve the payload
-        payload = self.client.get_secret_payload(uuid)
-        self.assertEqual(key, base64.b64encode(payload))
-
-
-class ProjectAdminTests(ProjectMemberTests):
-    @classmethod
-    def setup_clients(cls):
-        super().setup_clients()
-        cls.client = cls.os_project_admin.secret_v1.SecretClient()
+        Testing: DELETE /v1/secrets/{secret_id}
+        This test must check:
+          * whether the persona can delete a secret that belongs to a
+            different project
+        """
+        raise NotImplementedError
 
 
 class ProjectReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
@@ -265,57 +224,126 @@
             secret_id=uuid, payload=key
         )
 
+    def test_get_other_project_secret(self):
+        other_secret_id = self.create_other_project_secret(
+            'get_other_secret',
+            payload='¡Muy secreto!')
+        self.assertRaises(
+            exceptions.Forbidden,
+            self.client.get_secret_metadata,
+            other_secret_id)
 
-class SystemAdminTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
+    def test_get_other_project_secret_payload(self):
+        other_secret_id = self.create_other_project_secret(
+            'get_other_payload',
+            payload='¡Más secreto!')
+        self.assertRaises(
+            exceptions.Forbidden,
+            self.client.get_secret_payload,
+            other_secret_id)
+
+    def test_put_other_project_secret_payload(self):
+        other_secret_id = self.create_other_project_secret('put_other_payload')
+        self.assertRaises(
+            exceptions.Forbidden,
+            self.client.put_secret_payload,
+            other_secret_id,
+            'Shhhh... secret!')
+
+    def test_delete_other_project_secret(self):
+        other_secret_id = self.create_other_project_secret(
+            'get_other_payload',
+            payload='loremipsumloremipsum')
+        self.assertRaises(
+            exceptions.Forbidden,
+            self.client.delete_secret,
+            other_secret_id)
+
+
+class ProjectMemberTests(ProjectReaderTests):
 
     @classmethod
     def setup_clients(cls):
         super().setup_clients()
-        cls.client = cls.secret_client
+        cls.client = cls.os_project_member.secret_v1.SecretClient()
 
     def test_create_secret(self):
-        pass
+        """Test add_secret policy."""
+        self.client.create_secret(name='test_create_secret')
+
+        key = rbac_base.create_aes_key()
+        expire_time = (datetime.utcnow() + timedelta(days=5))
+        self.client.create_secret(
+            name='test_create_secret2',
+            expiration=expire_time.isoformat(), algorithm="aes",
+            bit_length=256, mode="cbc", payload=key,
+            payload_content_type="application/octet-stream",
+            payload_content_encoding="base64"
+        )
 
     def test_list_secrets(self):
-        pass
+        """Test get_secrets policy."""
+        # create two secrets
+        self.create_empty_secret_admin('test_list_secrets')
+        self.create_empty_secret_admin('test_list_secrets_2')
+
+        # list secrets with name secret_1
+        resp = self.client.list_secrets(name='test_list_secrets')
+        secrets = resp['secrets']
+        self.assertEqual('test_list_secrets', secrets[0]['name'])
+
+        # list secrets with name secret_2
+        resp = self.client.list_secrets(name='test_list_secrets_2')
+        secrets = resp['secrets']
+        self.assertEqual('test_list_secrets_2', secrets[0]['name'])
+
+        # list all secrets
+        resp = self.client.list_secrets()
+        secrets = resp['secrets']
+        self.assertGreaterEqual(len(secrets), 2)
 
     def test_delete_secret(self):
-        pass
+        """Test delete_secrets policy."""
+        sec = self.create_empty_secret_admin('test_delete_secret_1')
+        uuid = self.client.ref_to_uuid(sec['secret_ref'])
+        self.client.delete_secret(uuid)
 
     def test_get_secret(self):
-        pass
+        """Test get_secret policy."""
+        sec = self.create_empty_secret_admin('test_get_secret')
+        uuid = self.client.ref_to_uuid(sec['secret_ref'])
+        resp = self.client.get_secret_metadata(uuid)
+        self.assertEqual(uuid, self.client.ref_to_uuid(resp['secret_ref']))
 
     def test_get_secret_payload(self):
-        pass
+        """Test get_secret payload policy."""
+        key, sec = self.create_aes_secret_admin('test_get_secret_payload')
+        uuid = self.client.ref_to_uuid(sec['secret_ref'])
+
+        # Retrieve the payload
+        payload = self.client.get_secret_payload(uuid)
+        self.assertEqual(key, base64.b64encode(payload))
 
     def test_put_secret_payload(self):
-        pass
+        """Test put_secret policy."""
+        sec = self.create_empty_secret_admin('test_put_secret_payload')
+        uuid = self.client.ref_to_uuid(sec['secret_ref'])
+
+        key = rbac_base.create_aes_key()
+
+        # Associate the payload with the created secret
+        self.client.put_secret_payload(uuid, key)
+
+        # Retrieve the payload
+        payload = self.client.get_secret_payload(uuid)
+        self.assertEqual(key, base64.b64encode(payload))
 
 
-class SystemMemberTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
-
+class ProjectAdminTests(ProjectMemberTests):
     @classmethod
     def setup_clients(cls):
         super().setup_clients()
-        cls.client = cls.secret_client
-
-    def test_create_secret(self):
-        pass
-
-    def test_list_secrets(self):
-        pass
-
-    def test_delete_secret(self):
-        pass
-
-    def test_get_secret(self):
-        pass
-
-    def test_get_secret_payload(self):
-        pass
-
-    def test_put_secret_payload(self):
-        pass
+        cls.client = cls.os_project_admin.secret_v1.SecretClient()
 
 
 class SystemReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
@@ -342,3 +370,31 @@
 
     def test_put_secret_payload(self):
         pass
+
+    def test_get_other_project_secret(self):
+        pass
+
+    def test_get_other_project_secret_payload(self):
+        pass
+
+    def test_put_other_project_secret_payload(self):
+        pass
+
+    def test_delete_other_project_secret(self):
+        pass
+
+
+class SystemMemberTests(SystemReaderTests):
+
+    @classmethod
+    def setup_clients(cls):
+        super().setup_clients()
+        cls.client = cls.secret_client
+
+
+class SystemAdminTests(SystemMemberTests):
+
+    @classmethod
+    def setup_clients(cls):
+        super().setup_clients()
+        cls.client = cls.secret_client