Add system role functionality
This commit adds the necessary bits to expose system role assignments to openstackclient via python-keystoneclient. bp system-scope Depends-On: Iecbcbf020a15f2bec777334c648d4477f89f3b2c Change-Id: I261e84700b51e8715eaebdc3f8f8bc46b68542c2
This commit is contained in:
parent
47d0d0e0c0
commit
8bfa180430
@ -95,7 +95,7 @@ python-heatclient==1.10.0
|
||||
python-ironic-inspector-client==1.5.0
|
||||
python-ironicclient==2.3.0
|
||||
python-karborclient==0.6.0
|
||||
python-keystoneclient==3.8.0
|
||||
python-keystoneclient==3.15.0
|
||||
python-mimeparse==1.6.0
|
||||
python-mistralclient==3.1.0
|
||||
python-muranoclient==0.8.2
|
||||
|
@ -31,13 +31,18 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _add_identity_and_resource_options_to_parser(parser):
|
||||
domain_or_project = parser.add_mutually_exclusive_group()
|
||||
domain_or_project.add_argument(
|
||||
system_or_domain_or_project = parser.add_mutually_exclusive_group()
|
||||
system_or_domain_or_project.add_argument(
|
||||
'--system',
|
||||
metavar='<system>',
|
||||
help=_('Include <system> (all)'),
|
||||
)
|
||||
system_or_domain_or_project.add_argument(
|
||||
'--domain',
|
||||
metavar='<domain>',
|
||||
help=_('Include <domain> (name or ID)'),
|
||||
)
|
||||
domain_or_project.add_argument(
|
||||
system_or_domain_or_project.add_argument(
|
||||
'--project',
|
||||
metavar='<project>',
|
||||
help=_('Include <project> (name or ID)'),
|
||||
@ -62,7 +67,14 @@ def _add_identity_and_resource_options_to_parser(parser):
|
||||
def _process_identity_and_resource_options(parsed_args,
|
||||
identity_client_manager):
|
||||
kwargs = {}
|
||||
if parsed_args.user and parsed_args.domain:
|
||||
if parsed_args.user and parsed_args.system:
|
||||
kwargs['user'] = common.find_user(
|
||||
identity_client_manager,
|
||||
parsed_args.user,
|
||||
parsed_args.user_domain,
|
||||
).id
|
||||
kwargs['system'] = parsed_args.system
|
||||
elif parsed_args.user and parsed_args.domain:
|
||||
kwargs['user'] = common.find_user(
|
||||
identity_client_manager,
|
||||
parsed_args.user,
|
||||
@ -83,6 +95,13 @@ def _process_identity_and_resource_options(parsed_args,
|
||||
parsed_args.project,
|
||||
parsed_args.project_domain,
|
||||
).id
|
||||
elif parsed_args.group and parsed_args.system:
|
||||
kwargs['group'] = common.find_group(
|
||||
identity_client_manager,
|
||||
parsed_args.group,
|
||||
parsed_args.group_domain,
|
||||
).id
|
||||
kwargs['system'] = parsed_args.system
|
||||
elif parsed_args.group and parsed_args.domain:
|
||||
kwargs['group'] = common.find_group(
|
||||
identity_client_manager,
|
||||
@ -109,8 +128,8 @@ def _process_identity_and_resource_options(parsed_args,
|
||||
|
||||
|
||||
class AddRole(command.Command):
|
||||
_description = _("Adds a role assignment to a user or group on a domain "
|
||||
"or project")
|
||||
_description = _("Adds a role assignment to a user or group on the "
|
||||
"system, a domain, or a project")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(AddRole, self).get_parser(prog_name)
|
||||
@ -381,7 +400,7 @@ class ListRole(command.Lister):
|
||||
|
||||
|
||||
class RemoveRole(command.Command):
|
||||
_description = _("Removes a role assignment from domain/project : "
|
||||
_description = _("Removes a role assignment from system/domain/project : "
|
||||
"user/group")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
|
@ -55,17 +55,22 @@ class ListRoleAssignment(command.Lister):
|
||||
help=_('Group to filter (name or ID)'),
|
||||
)
|
||||
common.add_group_domain_option_to_parser(parser)
|
||||
domain_or_project = parser.add_mutually_exclusive_group()
|
||||
domain_or_project.add_argument(
|
||||
system_or_domain_or_project = parser.add_mutually_exclusive_group()
|
||||
system_or_domain_or_project.add_argument(
|
||||
'--domain',
|
||||
metavar='<domain>',
|
||||
help=_('Domain to filter (name or ID)'),
|
||||
)
|
||||
domain_or_project.add_argument(
|
||||
system_or_domain_or_project.add_argument(
|
||||
'--project',
|
||||
metavar='<project>',
|
||||
help=_('Project to filter (name or ID)'),
|
||||
)
|
||||
system_or_domain_or_project.add_argument(
|
||||
'--system',
|
||||
metavar='<system>',
|
||||
help=_('Filter based on system role assignments'),
|
||||
)
|
||||
common.add_project_domain_option_to_parser(parser)
|
||||
common.add_inherited_option_to_parser(parser)
|
||||
parser.add_argument(
|
||||
@ -85,7 +90,8 @@ class ListRoleAssignment(command.Lister):
|
||||
|
||||
def _as_tuple(self, assignment):
|
||||
return (assignment.role, assignment.user, assignment.group,
|
||||
assignment.project, assignment.domain, assignment.inherited)
|
||||
assignment.project, assignment.domain, assignment.system,
|
||||
assignment.inherited)
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
identity_client = self.app.client_manager.identity
|
||||
@ -117,6 +123,10 @@ class ListRoleAssignment(command.Lister):
|
||||
auth_ref.user_id
|
||||
)
|
||||
|
||||
system = None
|
||||
if parsed_args.system:
|
||||
system = parsed_args.system
|
||||
|
||||
domain = None
|
||||
if parsed_args.domain:
|
||||
domain = common.find_domain(
|
||||
@ -149,7 +159,9 @@ class ListRoleAssignment(command.Lister):
|
||||
|
||||
include_names = True if parsed_args.names else False
|
||||
effective = True if parsed_args.effective else False
|
||||
columns = ('Role', 'User', 'Group', 'Project', 'Domain', 'Inherited')
|
||||
columns = (
|
||||
'Role', 'User', 'Group', 'Project', 'Domain', 'System', 'Inherited'
|
||||
)
|
||||
|
||||
inherited_to = 'projects' if parsed_args.inherited else None
|
||||
data = identity_client.role_assignments.list(
|
||||
@ -157,6 +169,7 @@ class ListRoleAssignment(command.Lister):
|
||||
user=user,
|
||||
group=group,
|
||||
project=project,
|
||||
system=system,
|
||||
role=role,
|
||||
effective=effective,
|
||||
os_inherit_extension_inherited_to=inherited_to,
|
||||
@ -174,14 +187,24 @@ class ListRoleAssignment(command.Lister):
|
||||
else:
|
||||
setattr(assignment, 'project', scope['project']['id'])
|
||||
assignment.domain = ''
|
||||
assignment.system = ''
|
||||
elif 'domain' in scope:
|
||||
if include_names:
|
||||
setattr(assignment, 'domain', scope['domain']['name'])
|
||||
else:
|
||||
setattr(assignment, 'domain', scope['domain']['id'])
|
||||
assignment.project = ''
|
||||
|
||||
assignment.system = ''
|
||||
elif 'system' in scope:
|
||||
# NOTE(lbragstad): If, or when, keystone supports role
|
||||
# assignments on subsets of a system, this will have to evolve
|
||||
# to handle that case instead of hardcoding to the entire
|
||||
# system.
|
||||
setattr(assignment, 'system', 'all')
|
||||
assignment.domain = ''
|
||||
assignment.project = ''
|
||||
else:
|
||||
assignment.system = ''
|
||||
assignment.domain = ''
|
||||
assignment.project = ''
|
||||
|
||||
|
@ -192,6 +192,12 @@ class IssueToken(command.ShowOne):
|
||||
data['user_id'] = auth_ref.user_id
|
||||
if auth_ref.domain_id:
|
||||
data['domain_id'] = auth_ref.domain_id
|
||||
if auth_ref.system_scoped:
|
||||
# NOTE(lbragstad): This could change in the future when, or if,
|
||||
# keystone supports the ability to scope to a subset of the entire
|
||||
# deployment system. When that happens, this will have to relay
|
||||
# scope information and IDs like we do for projects and domains.
|
||||
data['system'] = 'all'
|
||||
return zip(*sorted(six.iteritems(data)))
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'Group',
|
||||
'Project',
|
||||
'Domain',
|
||||
'System',
|
||||
'Inherited',
|
||||
)
|
||||
|
||||
@ -95,6 +96,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
group=None,
|
||||
effective=False,
|
||||
role=None,
|
||||
@ -110,12 +112,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
), (identity_fakes.role_id,
|
||||
'',
|
||||
identity_fakes.group_id,
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
@ -143,6 +147,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', identity_fakes.user_name),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', None),
|
||||
('role', None),
|
||||
@ -159,6 +164,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
user=self.users_mock.get(),
|
||||
group=None,
|
||||
project=None,
|
||||
@ -174,12 +180,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
'',
|
||||
identity_fakes.domain_id,
|
||||
'',
|
||||
False
|
||||
), (identity_fakes.role_id,
|
||||
identity_fakes.user_id,
|
||||
'',
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
@ -207,6 +215,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', identity_fakes.group_name),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', None),
|
||||
('role', None),
|
||||
@ -223,6 +232,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
group=self.groups_mock.get(),
|
||||
effective=False,
|
||||
project=None,
|
||||
@ -238,12 +248,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
identity_fakes.group_id,
|
||||
'',
|
||||
identity_fakes.domain_id,
|
||||
'',
|
||||
False
|
||||
), (identity_fakes.role_id,
|
||||
'',
|
||||
identity_fakes.group_id,
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
@ -271,6 +283,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', identity_fakes.domain_name),
|
||||
('project', None),
|
||||
('role', None),
|
||||
@ -287,6 +300,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=self.domains_mock.get(),
|
||||
system=None,
|
||||
group=None,
|
||||
effective=False,
|
||||
project=None,
|
||||
@ -302,12 +316,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
'',
|
||||
identity_fakes.domain_id,
|
||||
'',
|
||||
False
|
||||
), (identity_fakes.role_id,
|
||||
'',
|
||||
identity_fakes.group_id,
|
||||
'',
|
||||
identity_fakes.domain_id,
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
@ -335,6 +351,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', identity_fakes.project_name),
|
||||
('role', None),
|
||||
@ -351,6 +368,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
group=None,
|
||||
effective=False,
|
||||
project=self.projects_mock.get(),
|
||||
@ -366,12 +384,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
), (identity_fakes.role_id,
|
||||
'',
|
||||
identity_fakes.group_id,
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
@ -398,6 +418,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', None),
|
||||
('role', None),
|
||||
@ -416,6 +437,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
user=self.users_mock.get(),
|
||||
group=None,
|
||||
project=self.projects_mock.get(),
|
||||
@ -431,6 +453,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
@ -456,6 +479,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', None),
|
||||
('role', None),
|
||||
@ -472,6 +496,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
group=None,
|
||||
effective=True,
|
||||
project=None,
|
||||
@ -487,12 +512,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
False
|
||||
), (identity_fakes.role_id,
|
||||
identity_fakes.user_id,
|
||||
'',
|
||||
'',
|
||||
identity_fakes.domain_id,
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
@ -520,6 +547,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', None),
|
||||
('role', None),
|
||||
@ -536,6 +564,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
group=None,
|
||||
effective=False,
|
||||
project=None,
|
||||
@ -551,12 +580,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
identity_fakes.project_id,
|
||||
'',
|
||||
'',
|
||||
True
|
||||
), (identity_fakes.role_id,
|
||||
identity_fakes.user_id,
|
||||
'',
|
||||
'',
|
||||
identity_fakes.domain_id,
|
||||
'',
|
||||
True
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
@ -584,6 +615,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', None),
|
||||
('role', None),
|
||||
@ -602,6 +634,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
group=None,
|
||||
effective=False,
|
||||
project=None,
|
||||
@ -610,7 +643,9 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
os_inherit_extension_inherited_to=None,
|
||||
include_names=True)
|
||||
|
||||
collist = ('Role', 'User', 'Group', 'Project', 'Domain', 'Inherited')
|
||||
collist = (
|
||||
'Role', 'User', 'Group', 'Project', 'Domain', 'System', 'Inherited'
|
||||
)
|
||||
self.assertEqual(columns, collist)
|
||||
|
||||
datalist1 = ((
|
||||
@ -620,12 +655,14 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'@'.join([identity_fakes.project_name,
|
||||
identity_fakes.domain_name]),
|
||||
'',
|
||||
'',
|
||||
False
|
||||
), (identity_fakes.role_name,
|
||||
'@'.join([identity_fakes.user_name, identity_fakes.domain_name]),
|
||||
'',
|
||||
'',
|
||||
identity_fakes.domain_name,
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(tuple(data), datalist1)
|
||||
@ -648,6 +685,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
verifylist = [
|
||||
('user', None),
|
||||
('group', None),
|
||||
('system', None),
|
||||
('domain', None),
|
||||
('project', None),
|
||||
('role', identity_fakes.ROLE_2['name']),
|
||||
@ -664,6 +702,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
|
||||
self.role_assignments_mock.list.assert_called_with(
|
||||
domain=None,
|
||||
system=None,
|
||||
user=None,
|
||||
group=None,
|
||||
project=None,
|
||||
@ -679,6 +718,7 @@ class TestRoleAssignmentList(TestRoleAssignment):
|
||||
'',
|
||||
'',
|
||||
identity_fakes.domain_id,
|
||||
'',
|
||||
False
|
||||
),)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for system-scope. This includes support for the ability to
|
||||
generate system-scoped tokens using ``system_scope: all`` in ``cloud.yaml``
|
||||
or ``OS_SYSTEM_SCOPE=all`` in an environment variable. Support is also
|
||||
included for managing role assignments on the system using ``--system``
|
||||
when adding and removing roles.
|
@ -12,6 +12,6 @@ osc-lib>=1.8.0 # Apache-2.0
|
||||
oslo.i18n>=3.15.3 # Apache-2.0
|
||||
oslo.utils>=3.33.0 # Apache-2.0
|
||||
python-glanceclient>=2.8.0 # Apache-2.0
|
||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||
python-keystoneclient>=3.15.0 # Apache-2.0
|
||||
python-novaclient>=9.1.0 # Apache-2.0
|
||||
python-cinderclient>=3.3.0 # Apache-2.0
|
||||
|
Loading…
Reference in New Issue
Block a user