Ensure default roles created during bootstrap
Expand bootstrap process to include creation of roles outlined in basic default roles spec. The bootstrap process now creates two new roles, 'reader' and 'member, in addition to the well established 'admin' role. During this process, a role implication[1] chain is created: 'admin' implies 'member' and 'member' implies 'reader'. [1] - https://developer.openstack.org/api-ref/identity/v3/#create-role-inference-rule Co-Authored-By: Juan Antonio Osorio Robles <jaosorior@redhat.com> bp basic-default-roles Depends-On: https://review.openstack.org/574149 Change-Id: Ie18a269e3d1075d955fe494acaf634a393c6bd7b
This commit is contained in:
parent
104717d458
commit
d44ed7f18c
@ -36,6 +36,12 @@ class Bootstrapper(object):
|
||||
self.project_id = None
|
||||
self.project_name = None
|
||||
|
||||
self.reader_role_id = None
|
||||
self.reader_role_name = 'reader'
|
||||
|
||||
self.member_role_id = None
|
||||
self.member_role_name = 'member'
|
||||
|
||||
self.admin_role_id = None
|
||||
self.admin_role_name = None
|
||||
|
||||
@ -55,6 +61,8 @@ class Bootstrapper(object):
|
||||
self._bootstrap_default_domain()
|
||||
self._bootstrap_project()
|
||||
self._bootstrap_admin_user()
|
||||
self._bootstrap_reader_role()
|
||||
self._bootstrap_member_role()
|
||||
self._bootstrap_admin_role()
|
||||
self._bootstrap_project_role_assignment()
|
||||
self._bootstrap_system_role_assignment()
|
||||
@ -101,6 +109,53 @@ class Bootstrapper(object):
|
||||
|
||||
self.project_id = project['id']
|
||||
|
||||
def _ensure_role_exists(self, role_name):
|
||||
# NOTE(morganfainberg): Do not create the role if it already exists.
|
||||
try:
|
||||
role_id = uuid.uuid4().hex
|
||||
role = {'name': role_name, 'id': role_id}
|
||||
role = PROVIDERS.role_api.create_role(role_id, role)
|
||||
LOG.info('Created role %s', role_name)
|
||||
return role
|
||||
except exception.Conflict:
|
||||
LOG.info('Role %s exists, skipping creation.', role_name)
|
||||
# NOTE(davechen): There is no backend method to get the role
|
||||
# by name, so build the hints to list the roles and filter by
|
||||
# name instead.
|
||||
hints = driver_hints.Hints()
|
||||
hints.add_filter('name', role_name)
|
||||
return PROVIDERS.role_api.list_roles(hints)[0]
|
||||
|
||||
def _ensure_implied_role(self, prior_role_id, implied_role_id):
|
||||
try:
|
||||
PROVIDERS.role_api.create_implied_role(prior_role_id,
|
||||
implied_role_id)
|
||||
LOG.info(
|
||||
'Created implied role where %s implies %s',
|
||||
prior_role_id,
|
||||
implied_role_id
|
||||
)
|
||||
except exception.Conflict:
|
||||
LOG.info(
|
||||
'Implied role where %s implies %s exists, skipping creation.',
|
||||
prior_role_id,
|
||||
implied_role_id
|
||||
)
|
||||
|
||||
def _bootstrap_reader_role(self):
|
||||
role = self._ensure_role_exists(self.reader_role_name)
|
||||
self.reader_role_id = role['id']
|
||||
|
||||
def _bootstrap_member_role(self):
|
||||
role = self._ensure_role_exists(self.member_role_name)
|
||||
self.member_role_id = role['id']
|
||||
self._ensure_implied_role(self.member_role_id, self.reader_role_id)
|
||||
|
||||
def _bootstrap_admin_role(self):
|
||||
role = self._ensure_role_exists(self.admin_role_name)
|
||||
self.admin_role_id = role['id']
|
||||
self._ensure_implied_role(self.admin_role_id, self.member_role_id)
|
||||
|
||||
def _bootstrap_admin_user(self):
|
||||
# NOTE(morganfainberg): Do not create the user if it already exists.
|
||||
try:
|
||||
@ -156,26 +211,6 @@ class Bootstrapper(object):
|
||||
|
||||
self.admin_user_id = user['id']
|
||||
|
||||
def _bootstrap_admin_role(self):
|
||||
# NOTE(morganfainberg): Do not create the role if it already exists.
|
||||
try:
|
||||
role_id = uuid.uuid4().hex
|
||||
role = {'name': self.admin_role_name, 'id': role_id}
|
||||
role = PROVIDERS.role_api.create_role(role_id, role)
|
||||
LOG.info('Created role %s', self.admin_role_name)
|
||||
except exception.Conflict:
|
||||
LOG.info(
|
||||
'Role %s exists, skipping creation.', self.admin_role_name
|
||||
)
|
||||
# NOTE(davechen): There is no backend method to get the role
|
||||
# by name, so build the hints to list the roles and filter by
|
||||
# name instead.
|
||||
hints = driver_hints.Hints()
|
||||
hints.add_filter('name', self.admin_role_name)
|
||||
role = PROVIDERS.role_api.list_roles(hints)[0]
|
||||
|
||||
self.admin_role_id = role['id']
|
||||
|
||||
def _bootstrap_project_role_assignment(self):
|
||||
try:
|
||||
PROVIDERS.assignment_api.add_role_to_user_and_project(
|
||||
|
@ -167,6 +167,8 @@ class BootStrap(BaseApp):
|
||||
self.bootstrapper.region_id = self.region_id
|
||||
|
||||
self.bootstrapper.bootstrap()
|
||||
self.reader_role_id = self.bootstrapper.reader_role_id
|
||||
self.member_role_id = self.bootstrapper.member_role_id
|
||||
self.role_id = self.bootstrapper.admin_role_id
|
||||
self.project_id = self.bootstrapper.project_id
|
||||
|
||||
|
@ -107,20 +107,24 @@ class CliBootStrapTestCase(unit.SQLDriverOverrides, unit.TestCase):
|
||||
user = PROVIDERS.identity_api.get_user_by_name(
|
||||
bootstrap.username,
|
||||
'default')
|
||||
role = PROVIDERS.role_api.get_role(bootstrap.role_id)
|
||||
admin_role = PROVIDERS.role_api.get_role(bootstrap.role_id)
|
||||
reader_role = PROVIDERS.role_api.get_role(bootstrap.reader_role_id)
|
||||
member_role = PROVIDERS.role_api.get_role(bootstrap.member_role_id)
|
||||
role_list = (
|
||||
PROVIDERS.assignment_api.get_roles_for_user_and_project(
|
||||
user['id'],
|
||||
project['id']))
|
||||
self.assertIs(1, len(role_list))
|
||||
self.assertEqual(role_list[0], role['id'])
|
||||
self.assertIs(3, len(role_list))
|
||||
self.assertIn(admin_role['id'], role_list)
|
||||
self.assertIn(reader_role['id'], role_list)
|
||||
self.assertIn(member_role['id'], role_list)
|
||||
system_roles = (
|
||||
PROVIDERS.assignment_api.list_system_grants_for_user(
|
||||
user['id']
|
||||
)
|
||||
)
|
||||
self.assertIs(1, len(system_roles))
|
||||
self.assertEqual(system_roles[0]['id'], role['id'])
|
||||
self.assertEqual(system_roles[0]['id'], admin_role['id'])
|
||||
# NOTE(morganfainberg): Pass an empty context, it isn't used by
|
||||
# `authenticate` method.
|
||||
PROVIDERS.identity_api.authenticate(
|
||||
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
[`blueprint basic-default-roles <https://blueprints.launchpad.net/keystone/+spec/basic-default-roles>`_]
|
||||
Support has been added for deploying two new roles during the bootstrap
|
||||
process, `reader` and `member`, in addition to the `admin` role.
|
||||
upgrades:
|
||||
- |
|
||||
If the bootstrap process is re-run, and a `reader`, `member`, or `admin`
|
||||
role already exists, a role implication chain will be created: `admin`
|
||||
implies `member` implies `reader`. If you do not want these role
|
||||
implications either skip running bootstrap or delete them after it has
|
||||
completed execution. See
|
||||
[`blueprint basic-default-roles <https://blueprints.launchpad.net/keystone/+spec/basic-default-roles>`_]
|
||||
for more details.
|
Loading…
Reference in New Issue
Block a user