Merge "Ensure default roles created during bootstrap"

This commit is contained in:
Zuul 2018-06-15 11:50:47 +00:00 committed by Gerrit Code Review
commit b106c70170
4 changed files with 80 additions and 24 deletions

View File

@ -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(

View File

@ -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

View File

@ -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(

View File

@ -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.