Add default RBAC personas to pre-provisioned creds
This change adds support for the nine default personas for the
pre-provisioned credentials provider, as well as a sample accounts.yaml
file. With this, service projects should be able to use either dynamic
or pre-provisioned credentials for testing new policy defaults that use
system, domain, or project scope and the admin, member or reader default
roles.
Change-Id: Ifda77fb8d875b18c4507da2c9d98f17bcdac2e21
diff --git a/etc/rbac-persona-accounts.yaml.sample b/etc/rbac-persona-accounts.yaml.sample
new file mode 100644
index 0000000..0b59538
--- /dev/null
+++ b/etc/rbac-persona-accounts.yaml.sample
@@ -0,0 +1,108 @@
+- user_domain_name: Default
+ password: password
+ roles:
+ - admin
+ username: tempest-system-admin-1
+ system: all
+- user_domain_name: Default
+ password: password
+ username: tempest-system-member-1
+ roles:
+ - member
+ system: all
+- user_domain_name: Default
+ password: password
+ username: tempest-system-reader-1
+ roles:
+ - reader
+ system: all
+- user_domain_name: Default
+ password: password
+ domain_name: tempest-test-domain
+ username: tempest-domain-admin-1
+ roles:
+ - admin
+- user_domain_name: Default
+ password: password
+ domain_name: tempest-test-domain
+ username: tempest-domain-member-1
+ roles:
+ - member
+- user_domain_name: Default
+ password: password
+ domain_name: tempest-test-domain
+ username: tempest-domain-reader-1
+ roles:
+ - reader
+- user_domain_name: Default
+ password: password
+ project_name: tempest-test-project
+ username: tempest-project-admin-1
+ roles:
+ - admin
+- user_domain_name: Default
+ password: password
+ project_name: tempest-test-project
+ username: tempest-project-member-1
+ roles:
+ - member
+- user_domain_name: Default
+ password: password
+ project_name: tempest-test-project
+ username: tempest-project-reader-1
+ roles:
+ - reader
+- user_domain_name: Default
+ password: password
+ username: tempest-system-admin-2
+ roles:
+ - admin
+ system: all
+- user_domain_name: Default
+ password: password
+ username: tempest-system-member-2
+ roles:
+ - member
+ system: all
+- user_domain_name: Default
+ password: password
+ system: all
+ username: tempest-system-reader-2
+ roles:
+ - reader
+- user_domain_name: Default
+ password: password
+ domain_name: tempest-test-domain
+ username: tempest-domain-admin-2
+ roles:
+ - admin
+- user_domain_name: Default
+ password: password
+ domain_name: tempest-test-domain
+ username: tempest-domain-member-2
+ roles:
+ - member
+- user_domain_name: Default
+ password: password
+ domain_name: tempest-test-domain
+ username: tempest-domain-reader-2
+ roles:
+ - reader
+- user_domain_name: Default
+ password: password
+ project_name: tempest-test-project
+ username: tempest-project-admin-2
+ roles:
+ - admin
+- user_domain_name: Default
+ password: password
+ project_name: tempest-test-project
+ username: tempest-project-member-2
+ roles:
+ - member
+- user_domain_name: Default
+ password: password
+ project_name: tempest-test-project
+ username: tempest-project-reader-2
+ roles:
+ - reader
diff --git a/releasenotes/notes/system-scope-44244cc955a7825f.yaml b/releasenotes/notes/system-scope-44244cc955a7825f.yaml
new file mode 100644
index 0000000..969a71f
--- /dev/null
+++ b/releasenotes/notes/system-scope-44244cc955a7825f.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Adds new personas that can be used to test service policies for all
+ default scopes (project, domain, and system) and roles (reader, member,
+ and admin). Both dynamic credentials and pre-provisioned credentials are
+ supported.
diff --git a/tempest/lib/common/preprov_creds.py b/tempest/lib/common/preprov_creds.py
index 641d727..8325f44 100644
--- a/tempest/lib/common/preprov_creds.py
+++ b/tempest/lib/common/preprov_creds.py
@@ -104,15 +104,24 @@
return hash_dict
@classmethod
+ def _append_scoped_role(cls, scope, role, account_hash, hash_dict):
+ key = "%s_%s" % (scope, role)
+ hash_dict['scoped_roles'].setdefault(key, [])
+ hash_dict['scoped_roles'][key].append(account_hash)
+ return hash_dict
+
+ @classmethod
def get_hash_dict(cls, accounts, admin_role,
object_storage_operator_role=None,
object_storage_reseller_admin_role=None):
- hash_dict = {'roles': {}, 'creds': {}, 'networks': {}}
+ hash_dict = {'roles': {}, 'creds': {}, 'networks': {},
+ 'scoped_roles': {}}
# Loop over the accounts read from the yaml file
for account in accounts:
roles = []
types = []
+ scope = None
resources = []
if 'roles' in account:
roles = account.pop('roles')
@@ -120,6 +129,12 @@
types = account.pop('types')
if 'resources' in account:
resources = account.pop('resources')
+ if 'project_name' in account:
+ scope = 'project'
+ elif 'domain_name' in account:
+ scope = 'domain'
+ elif 'system' in account:
+ scope = 'system'
temp_hash = hashlib.md5()
account_for_hash = dict((k, v) for (k, v) in account.items()
if k in cls.HASH_CRED_FIELDS)
@@ -129,6 +144,9 @@
for role in roles:
hash_dict = cls._append_role(role, temp_hash_key,
hash_dict)
+ if scope:
+ hash_dict = cls._append_scoped_role(
+ scope, role, temp_hash_key, hash_dict)
# If types are set for the account append the matching role
# subdict with the hash
for type in types:
@@ -201,17 +219,25 @@
'the credentials for this allocation request' % ','.join(names))
raise lib_exc.InvalidCredentials(msg)
- def _get_match_hash_list(self, roles=None):
+ def _get_match_hash_list(self, roles=None, scope=None):
hashes = []
if roles:
# Loop over all the creds for each role in the subdict and generate
# a list of cred lists for each role
for role in roles:
- temp_hashes = self.hash_dict['roles'].get(role, None)
- if not temp_hashes:
- raise lib_exc.InvalidCredentials(
- "No credentials with role: %s specified in the "
- "accounts ""file" % role)
+ if scope:
+ key = "%s_%s" % (scope, role)
+ temp_hashes = self.hash_dict['scoped_roles'].get(key)
+ if not temp_hashes:
+ raise lib_exc.InvalidCredentials(
+ "No credentials matching role: %s, scope: %s "
+ "specified in the accounts file" % (role, scope))
+ else:
+ temp_hashes = self.hash_dict['roles'].get(role, None)
+ if not temp_hashes:
+ raise lib_exc.InvalidCredentials(
+ "No credentials with role: %s specified in the "
+ "accounts file" % role)
hashes.append(temp_hashes)
# Take the list of lists and do a boolean and between each list to
# find the creds which fall under all the specified roles
@@ -239,8 +265,8 @@
temp_creds.pop('password')
return temp_creds
- def _get_creds(self, roles=None):
- useable_hashes = self._get_match_hash_list(roles)
+ def _get_creds(self, roles=None, scope=None):
+ useable_hashes = self._get_match_hash_list(roles, scope)
if not useable_hashes:
msg = 'No users configured for type/roles %s' % roles
raise lib_exc.InvalidCredentials(msg)
@@ -296,6 +322,69 @@
self._creds['alt'] = net_creds
return net_creds
+ def get_system_admin_creds(self):
+ if self._creds.get('system_admin'):
+ return self._creds.get('system_admin')
+ system_admin = self._get_creds(['admin'], scope='system')
+ self._creds['system_admin'] = system_admin
+ return system_admin
+
+ def get_system_member_creds(self):
+ if self._creds.get('system_member'):
+ return self._creds.get('system_member')
+ system_member = self._get_creds(['member'], scope='system')
+ self._creds['system_member'] = system_member
+ return system_member
+
+ def get_system_reader_creds(self):
+ if self._creds.get('system_reader'):
+ return self._creds.get('system_reader')
+ system_reader = self._get_creds(['reader'], scope='system')
+ self._creds['system_reader'] = system_reader
+ return system_reader
+
+ def get_domain_admin_creds(self):
+ if self._creds.get('domain_admin'):
+ return self._creds.get('domain_admin')
+ domain_admin = self._get_creds(['admin'], scope='domain')
+ self._creds['domain_admin'] = domain_admin
+ return domain_admin
+
+ def get_domain_member_creds(self):
+ if self._creds.get('domain_member'):
+ return self._creds.get('domain_member')
+ domain_member = self._get_creds(['member'], scope='domain')
+ self._creds['domain_member'] = domain_member
+ return domain_member
+
+ def get_domain_reader_creds(self):
+ if self._creds.get('domain_reader'):
+ return self._creds.get('domain_reader')
+ domain_reader = self._get_creds(['reader'], scope='domain')
+ self._creds['domain_reader'] = domain_reader
+ return domain_reader
+
+ def get_project_admin_creds(self):
+ if self._creds.get('project_admin'):
+ return self._creds.get('project_admin')
+ project_admin = self._get_creds(['admin'], scope='project')
+ self._creds['project_admin'] = project_admin
+ return project_admin
+
+ def get_project_member_creds(self):
+ if self._creds.get('project_member'):
+ return self._creds.get('project_member')
+ project_member = self._get_creds(['member'], scope='project')
+ self._creds['project_member'] = project_member
+ return project_member
+
+ def get_project_reader_creds(self):
+ if self._creds.get('project_reader'):
+ return self._creds.get('project_reader')
+ project_reader = self._get_creds(['reader'], scope='project')
+ self._creds['project_reader'] = project_reader
+ return project_reader
+
def get_creds_by_roles(self, roles, force_new=False):
roles = list(set(roles))
exist_creds = self._creds.get(six.text_type(roles).encode(