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
This commit is contained in:
Douglas Mendizábal 2021-04-07 16:26:45 -05:00
parent 62baff3fcc
commit 087f89dd16
2 changed files with 186 additions and 111 deletions

View File

@ -47,7 +47,10 @@ class BarbicanV1RbacBase(test.BaseTestCase):
_created_users = None _created_users = None
created_objects = {} created_objects = {}
credentials = ['system_admin'] credentials = [
'system_admin',
'project_alt_member'
]
# TODO(dmendiza): remove this and use the clients instead # TODO(dmendiza): remove this and use the clients instead
@classmethod @classmethod
@ -76,6 +79,8 @@ class BarbicanV1RbacBase(test.BaseTestCase):
cls._setup_new_user_client(project_id, 'member')) cls._setup_new_user_client(project_id, 'member'))
setattr(cls, 'os_project_reader', setattr(cls, 'os_project_reader',
cls._setup_new_user_client(project_id, 'reader')) cls._setup_new_user_client(project_id, 'reader'))
setattr(cls, 'os_project_other_member',
cls._setup_new_user_client(project_id, 'member'))
@classmethod @classmethod
def _setup_new_user_client(cls, project_id, role): def _setup_new_user_client(cls, project_id, role):
@ -122,7 +127,7 @@ class BarbicanV1RbacBase(test.BaseTestCase):
def setup_clients(cls): def setup_clients(cls):
super().setup_clients() super().setup_clients()
# setup clients for primary persona # set up member clients
os = cls.os_project_member os = cls.os_project_member
cls.secret_client = os.secret_v1.SecretClient() cls.secret_client = os.secret_v1.SecretClient()
cls.secret_metadata_client = os.secret_v1.SecretMetadataClient( cls.secret_metadata_client = os.secret_v1.SecretMetadataClient(
@ -154,6 +159,7 @@ class BarbicanV1RbacBase(test.BaseTestCase):
cls.admin_secret_metadata_client = adm.secret_v1.SecretMetadataClient( cls.admin_secret_metadata_client = adm.secret_v1.SecretMetadataClient(
service='key-manager' service='key-manager'
) )
cls.other_client = cls.os_project_alt_member.secret_v1.SecretClient()
@classmethod @classmethod
def resource_setup(cls): def resource_setup(cls):
@ -176,7 +182,9 @@ class BarbicanV1RbacBase(test.BaseTestCase):
for secret_uuid in list(cls.created_objects['secret']): for secret_uuid in list(cls.created_objects['secret']):
cls.admin_secret_client.delete_secret(secret_uuid) cls.admin_secret_client.delete_secret(secret_uuid)
cls.created_objects['secret'].remove(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() client.cleanup()
finally: finally:
super(BarbicanV1RbacBase, cls).resource_cleanup() super(BarbicanV1RbacBase, cls).resource_cleanup()
@ -234,3 +242,14 @@ class BarbicanV1RbacBase(test.BaseTestCase):
payload_content_encoding="base64", payload_content_encoding="base64",
name=secret_name 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'])

View File

@ -23,7 +23,7 @@ from barbican_tempest_plugin.tests.rbac.v1 import base as rbac_base
CONF = config.CONF CONF = config.CONF
class BarbicanV1RbacSecrets(metaclass=abc.ABCMeta): class BarbicanV1RbacSecrets:
@abc.abstractmethod @abc.abstractmethod
def test_create_secret(self): def test_create_secret(self):
@ -86,91 +86,50 @@ class BarbicanV1RbacSecrets(metaclass=abc.ABCMeta):
""" """
raise NotImplementedError 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 @abc.abstractmethod
def setup_clients(cls): def test_get_other_project_secret_payload(self):
super().setup_clients() """Test get_secrets policy
cls.client = cls.os_project_member.secret_v1.SecretClient()
def test_create_secret(self): Testing: GET /v1/secrets/{secret_id}/payload
"""Test add_secret policy.""" This test must check:
self.client.create_secret(name='test_create_secret') * whether the persona can get secret payload for a secret that
belongs to a different project
"""
raise NotImplementedError
key = rbac_base.create_aes_key() @abc.abstractmethod
expire_time = (datetime.utcnow() + timedelta(days=5)) def test_put_other_project_secret_payload(self):
self.client.create_secret( """Test put_secret policy.
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): Testing: PUT /v1/secrets/{secret_id}
"""Test get_secrets policy.""" This test must check:
# create two secrets * whether the persona can PUT the secret payload in a 2-step
self.create_empty_secret_admin('test_list_secrets') create when the first step is done by a member of a different
self.create_empty_secret_admin('test_list_secrets_2') project.
"""
raise NotImplementedError
# list secrets with name secret_1 @abc.abstractmethod
resp = self.client.list_secrets(name='test_list_secrets') def test_delete_other_project_secret(self):
secrets = resp['secrets'] """Test delete_secret policy.
self.assertEqual('test_list_secrets', secrets[0]['name'])
# list secrets with name secret_2 Testing: DELETE /v1/secrets/{secret_id}
resp = self.client.list_secrets(name='test_list_secrets_2') This test must check:
secrets = resp['secrets'] * whether the persona can delete a secret that belongs to a
self.assertEqual('test_list_secrets_2', secrets[0]['name']) different project
"""
# list all secrets raise NotImplementedError
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()
class ProjectReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets): class ProjectReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
@ -265,57 +224,126 @@ class ProjectReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
secret_id=uuid, payload=key 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 @classmethod
def setup_clients(cls): def setup_clients(cls):
super().setup_clients() super().setup_clients()
cls.client = cls.secret_client cls.client = cls.os_project_member.secret_v1.SecretClient()
def test_create_secret(self): 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): 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): 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): 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): 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): 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 @classmethod
def setup_clients(cls): def setup_clients(cls):
super().setup_clients() super().setup_clients()
cls.client = cls.secret_client cls.client = cls.os_project_admin.secret_v1.SecretClient()
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
class SystemReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets): class SystemReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
@ -342,3 +370,31 @@ class SystemReaderTests(rbac_base.BarbicanV1RbacBase, BarbicanV1RbacSecrets):
def test_put_secret_payload(self): def test_put_secret_payload(self):
pass 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