Merge "Identity: Add support for system role assignment"
This commit is contained in:
commit
d4e13ba34a
|
@ -87,7 +87,10 @@ Role Assignment Operations
|
|||
unassign_project_role_from_group, validate_group_has_project_role,
|
||||
assign_domain_role_to_user, unassign_domain_role_from_user,
|
||||
validate_user_has_domain_role, assign_domain_role_to_group,
|
||||
unassign_domain_role_from_group, validate_group_has_domain_role
|
||||
unassign_domain_role_from_group, validate_group_has_domain_role,
|
||||
assign_system_role_to_user, unassign_system_role_from_user,
|
||||
validate_user_has_system_role, assign_system_role_to_group,
|
||||
unassign_system_role_from_group, validate_group_has_system_role
|
||||
|
||||
Service Operations
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -945,6 +945,7 @@ class IdentityCloudMixin:
|
|||
* 'group' (string) - Group ID to be used as query filter.
|
||||
* 'project' (string) - Project ID to be used as query filter.
|
||||
* 'domain' (string) - Domain ID to be used as query filter.
|
||||
* 'system' (string) - System name to be used as query filter.
|
||||
* 'role' (string) - Role ID to be used as query filter.
|
||||
* 'os_inherit_extension_inherited_to' (string) - Return inherited
|
||||
role assignments for either 'projects' or 'domains'
|
||||
|
@ -991,6 +992,10 @@ class IdentityCloudMixin:
|
|||
if k in filters:
|
||||
filters['scope_%s_id' % k] = filters.pop(k)
|
||||
|
||||
if 'system' in filters:
|
||||
system_scope = filters.pop('system')
|
||||
filters['scope.system'] = system_scope
|
||||
|
||||
return list(self.identity.role_assignments(**filters))
|
||||
|
||||
@_utils.valid_kwargs('domain_id')
|
||||
|
@ -1055,7 +1060,7 @@ class IdentityCloudMixin:
|
|||
raise
|
||||
|
||||
def _get_grant_revoke_params(self, role, user=None, group=None,
|
||||
project=None, domain=None):
|
||||
project=None, domain=None, system=None):
|
||||
data = {}
|
||||
search_args = {}
|
||||
if domain:
|
||||
|
@ -1083,9 +1088,9 @@ class IdentityCloudMixin:
|
|||
if data.get('user') is None and data.get('group') is None:
|
||||
raise exc.OpenStackCloudException(
|
||||
'Must specify either a user or a group')
|
||||
if project is None and domain is None:
|
||||
if project is None and domain is None and system is None:
|
||||
raise exc.OpenStackCloudException(
|
||||
'Must specify either a domain or project')
|
||||
'Must specify either a domain, project or system')
|
||||
|
||||
if project:
|
||||
data['project'] = self.identity.find_project(
|
||||
|
@ -1093,7 +1098,8 @@ class IdentityCloudMixin:
|
|||
return data
|
||||
|
||||
def grant_role(self, name_or_id, user=None, group=None,
|
||||
project=None, domain=None, wait=False, timeout=60):
|
||||
project=None, domain=None, system=None, wait=False,
|
||||
timeout=60):
|
||||
"""Grant a role to a user.
|
||||
|
||||
:param string name_or_id: The name or id of the role.
|
||||
|
@ -1101,6 +1107,7 @@ class IdentityCloudMixin:
|
|||
:param string group: The name or id of the group. (v3)
|
||||
:param string project: The name or id of the project.
|
||||
:param string domain: The id of the domain. (v3)
|
||||
:param bool system: The name of the system. (v3)
|
||||
:param bool wait: Wait for role to be granted
|
||||
:param int timeout: Timeout to wait for role to be granted
|
||||
|
||||
|
@ -1112,13 +1119,15 @@ class IdentityCloudMixin:
|
|||
NOTE: for wait and timeout, sometimes granting roles is not
|
||||
instantaneous.
|
||||
|
||||
NOTE: precedence is given first to project, then domain, then system
|
||||
|
||||
:returns: True if the role is assigned, otherwise False
|
||||
|
||||
:raise OpenStackCloudException: if the role cannot be granted
|
||||
"""
|
||||
data = self._get_grant_revoke_params(
|
||||
name_or_id, user=user, group=group,
|
||||
project=project, domain=domain)
|
||||
project=project, domain=domain, system=system)
|
||||
|
||||
user = data.get('user')
|
||||
group = data.get('group')
|
||||
|
@ -1127,7 +1136,7 @@ class IdentityCloudMixin:
|
|||
role = data.get('role')
|
||||
|
||||
if project:
|
||||
# Proceed with project - precedence over domain
|
||||
# Proceed with project - precedence over domain and system
|
||||
if user:
|
||||
has_role = self.identity.validate_user_has_project_role(
|
||||
project, user, role)
|
||||
|
@ -1144,8 +1153,8 @@ class IdentityCloudMixin:
|
|||
return False
|
||||
self.identity.assign_project_role_to_group(
|
||||
project, group, role)
|
||||
else:
|
||||
# Proceed with domain
|
||||
elif domain:
|
||||
# Proceed with domain - precedence over system
|
||||
if user:
|
||||
has_role = self.identity.validate_user_has_domain_role(
|
||||
domain, user, role)
|
||||
|
@ -1162,10 +1171,31 @@ class IdentityCloudMixin:
|
|||
return False
|
||||
self.identity.assign_domain_role_to_group(
|
||||
domain, group, role)
|
||||
else:
|
||||
# Proceed with system
|
||||
# System name must be 'all' due to checks performed in
|
||||
# _get_grant_revoke_params
|
||||
if user:
|
||||
has_role = self.identity.validate_user_has_system_role(
|
||||
user, role, system)
|
||||
if has_role:
|
||||
self.log.debug('Assignment already exists')
|
||||
return False
|
||||
self.identity.assign_system_role_to_user(
|
||||
user, role, system)
|
||||
else:
|
||||
has_role = self.identity.validate_group_has_system_role(
|
||||
group, role, system)
|
||||
if has_role:
|
||||
self.log.debug('Assignment already exists')
|
||||
return False
|
||||
self.identity.assign_system_role_to_group(
|
||||
group, role, system)
|
||||
return True
|
||||
|
||||
def revoke_role(self, name_or_id, user=None, group=None,
|
||||
project=None, domain=None, wait=False, timeout=60):
|
||||
project=None, domain=None, system=None,
|
||||
wait=False, timeout=60):
|
||||
"""Revoke a role from a user.
|
||||
|
||||
:param string name_or_id: The name or id of the role.
|
||||
|
@ -1173,6 +1203,7 @@ class IdentityCloudMixin:
|
|||
:param string group: The name or id of the group. (v3)
|
||||
:param string project: The name or id of the project.
|
||||
:param string domain: The id of the domain. (v3)
|
||||
:param bool system: The name of the system. (v3)
|
||||
:param bool wait: Wait for role to be revoked
|
||||
:param int timeout: Timeout to wait for role to be revoked
|
||||
|
||||
|
@ -1181,13 +1212,15 @@ class IdentityCloudMixin:
|
|||
|
||||
NOTE: project is required for keystone v2
|
||||
|
||||
NOTE: precedence is given first to project, then domain, then system
|
||||
|
||||
:returns: True if the role is revoke, otherwise False
|
||||
|
||||
:raise OpenStackCloudException: if the role cannot be removed
|
||||
"""
|
||||
data = self._get_grant_revoke_params(
|
||||
name_or_id, user=user, group=group,
|
||||
project=project, domain=domain)
|
||||
project=project, domain=domain, system=system)
|
||||
|
||||
user = data.get('user')
|
||||
group = data.get('group')
|
||||
|
@ -1196,7 +1229,7 @@ class IdentityCloudMixin:
|
|||
role = data.get('role')
|
||||
|
||||
if project:
|
||||
# Proceed with project - precedence over domain
|
||||
# Proceed with project - precedence over domain and system
|
||||
if user:
|
||||
has_role = self.identity.validate_user_has_project_role(
|
||||
project, user, role)
|
||||
|
@ -1213,8 +1246,8 @@ class IdentityCloudMixin:
|
|||
return False
|
||||
self.identity.unassign_project_role_from_group(
|
||||
project, group, role)
|
||||
else:
|
||||
# Proceed with domain
|
||||
elif domain:
|
||||
# Proceed with domain - precedence over system
|
||||
if user:
|
||||
has_role = self.identity.validate_user_has_domain_role(
|
||||
domain, user, role)
|
||||
|
@ -1231,6 +1264,26 @@ class IdentityCloudMixin:
|
|||
return False
|
||||
self.identity.unassign_domain_role_from_group(
|
||||
domain, group, role)
|
||||
else:
|
||||
# Proceed with system
|
||||
# System name must be 'all' due to checks performed in
|
||||
# _get_grant_revoke_params
|
||||
if user:
|
||||
has_role = self.identity.validate_user_has_system_role(
|
||||
user, role, system)
|
||||
if not has_role:
|
||||
self.log.debug('Assignment does not exist')
|
||||
return False
|
||||
self.identity.unassign_system_role_from_user(
|
||||
user, role, system)
|
||||
else:
|
||||
has_role = self.identity.validate_group_has_system_role(
|
||||
group, role, system)
|
||||
if not has_role:
|
||||
self.log.debug('Assignment does not exist')
|
||||
return False
|
||||
self.identity.unassign_system_role_from_group(
|
||||
group, role, system)
|
||||
return True
|
||||
|
||||
def _get_identity_params(self, domain_id=None, project=None):
|
||||
|
|
|
@ -35,7 +35,12 @@ from openstack.identity.v3 import role_project_group_assignment \
|
|||
as _role_project_group_assignment
|
||||
from openstack.identity.v3 import role_project_user_assignment \
|
||||
as _role_project_user_assignment
|
||||
from openstack.identity.v3 import role_system_group_assignment \
|
||||
as _role_system_group_assignment
|
||||
from openstack.identity.v3 import role_system_user_assignment \
|
||||
as _role_system_user_assignment
|
||||
from openstack.identity.v3 import service as _service
|
||||
from openstack.identity.v3 import system as _system
|
||||
from openstack.identity.v3 import trust as _trust
|
||||
from openstack.identity.v3 import user as _user
|
||||
from openstack import proxy
|
||||
|
@ -949,8 +954,8 @@ class Proxy(proxy.Proxy):
|
|||
"""
|
||||
return self._update(_role.Role, role, **attrs)
|
||||
|
||||
def role_assignments_filter(self, domain=None, project=None, group=None,
|
||||
user=None):
|
||||
def role_assignments_filter(self, domain=None, project=None, system=None,
|
||||
group=None, user=None):
|
||||
"""Retrieve a generator of roles assigned to user/group
|
||||
|
||||
:param domain: Either the ID of a domain or a
|
||||
|
@ -958,6 +963,9 @@ class Proxy(proxy.Proxy):
|
|||
:param project: Either the ID of a project or a
|
||||
:class:`~openstack.identity.v3.project.Project`
|
||||
instance.
|
||||
:param system: Either the system name or a
|
||||
:class:`~openstack.identity.v3.system.System`
|
||||
instance.
|
||||
:param group: Either the ID of a group or a
|
||||
:class:`~openstack.identity.v3.group.Group` instance.
|
||||
:param user: Either the ID of a user or a
|
||||
|
@ -965,13 +973,13 @@ class Proxy(proxy.Proxy):
|
|||
:return: A generator of role instances.
|
||||
:rtype: :class:`~openstack.identity.v3.role.Role`
|
||||
"""
|
||||
if domain and project:
|
||||
if domain and project and system:
|
||||
raise exception.InvalidRequest(
|
||||
'Only one of domain or project can be specified')
|
||||
'Only one of domain, project, or system can be specified')
|
||||
|
||||
if domain is None and project is None:
|
||||
if domain is None and project is None and system is None:
|
||||
raise exception.InvalidRequest(
|
||||
'Either domain or project should be specified')
|
||||
'Either domain, project, or system should be specified')
|
||||
|
||||
if group and user:
|
||||
raise exception.InvalidRequest(
|
||||
|
@ -993,7 +1001,7 @@ class Proxy(proxy.Proxy):
|
|||
return self._list(
|
||||
_role_domain_user_assignment.RoleDomainUserAssignment,
|
||||
domain_id=domain.id, user_id=user.id)
|
||||
else:
|
||||
elif project:
|
||||
project = self._get_resource(_project.Project, project)
|
||||
if group:
|
||||
group = self._get_resource(_group.Group, group)
|
||||
|
@ -1005,6 +1013,18 @@ class Proxy(proxy.Proxy):
|
|||
return self._list(
|
||||
_role_project_user_assignment.RoleProjectUserAssignment,
|
||||
project_id=project.id, user_id=user.id)
|
||||
else:
|
||||
system = self._get_resource(_project.System, system)
|
||||
if group:
|
||||
group = self._get_resource(_group.Group, group)
|
||||
return self._list(
|
||||
_role_system_group_assignment.RoleSystemGroupAssignment,
|
||||
system_id=system.id, group_id=group.id)
|
||||
else:
|
||||
user = self._get_resource(_user.User, user)
|
||||
return self._list(
|
||||
_role_system_user_assignment.RoleSystemUserAssignment,
|
||||
system_id=system.id, user_id=user.id)
|
||||
|
||||
def role_assignments(self, **query):
|
||||
"""Retrieve a generator of role assignments
|
||||
|
@ -1355,6 +1375,96 @@ class Proxy(proxy.Proxy):
|
|||
role = self._get_resource(_role.Role, role)
|
||||
return project.validate_group_has_role(self, group, role)
|
||||
|
||||
def assign_system_role_to_user(self, user, role, system):
|
||||
"""Assign a role to user on a system
|
||||
|
||||
:param user: Either the ID of a user or a
|
||||
:class:`~openstack.identity.v3.user.User` instance.
|
||||
:param role: Either the ID of a role or a
|
||||
:class:`~openstack.identity.v3.role.Role` instance.
|
||||
:param system: The system name
|
||||
:return: ``None``
|
||||
"""
|
||||
user = self._get_resource(_user.User, user)
|
||||
role = self._get_resource(_role.Role, role)
|
||||
system = self._get_resource(_system.System, system)
|
||||
system.assign_role_to_user(self, user, role)
|
||||
|
||||
def unassign_system_role_from_user(self, user, role, system):
|
||||
"""Unassign a role from user on a system
|
||||
|
||||
:param user: Either the ID of a user or a
|
||||
:class:`~openstack.identity.v3.user.User` instance.
|
||||
:param role: Either the ID of a role or a
|
||||
:class:`~openstack.identity.v3.role.Role` instance.
|
||||
:param system: The system name
|
||||
:return: ``None``
|
||||
"""
|
||||
user = self._get_resource(_user.User, user)
|
||||
role = self._get_resource(_role.Role, role)
|
||||
system = self._get_resource(_system.System, system)
|
||||
system.unassign_role_from_user(self, user, role)
|
||||
|
||||
def validate_user_has_system_role(self, user, role, system):
|
||||
"""Validates that a user has a role on a system
|
||||
|
||||
:param user: Either the ID of a user or a
|
||||
:class:`~openstack.identity.v3.user.User` instance.
|
||||
:param role: Either the ID of a role or a
|
||||
:class:`~openstack.identity.v3.role.Role` instance.
|
||||
:param system: The system name
|
||||
:returns: True if user has role in system
|
||||
"""
|
||||
user = self._get_resource(_user.User, user)
|
||||
role = self._get_resource(_role.Role, role)
|
||||
system = self._get_resource(_system.System, system)
|
||||
return system.validate_user_has_role(self, user, role)
|
||||
|
||||
def assign_system_role_to_group(self, group, role, system):
|
||||
"""Assign a role to group on a system
|
||||
|
||||
:param group: Either the ID of a group or a
|
||||
:class:`~openstack.identity.v3.group.Group` instance.
|
||||
:param role: Either the ID of a role or a
|
||||
:class:`~openstack.identity.v3.role.Role` instance.
|
||||
:param system: The system name
|
||||
:return: ``None``
|
||||
"""
|
||||
group = self._get_resource(_group.Group, group)
|
||||
role = self._get_resource(_role.Role, role)
|
||||
system = self._get_resource(_system.System, system)
|
||||
system.assign_role_to_group(self, group, role)
|
||||
|
||||
def unassign_system_role_from_group(self, group, role, system):
|
||||
"""Unassign a role from group on a system
|
||||
|
||||
:param group: Either the ID of a group or a
|
||||
:class:`~openstack.identity.v3.group.Group` instance.
|
||||
:param role: Either the ID of a role or a
|
||||
:class:`~openstack.identity.v3.role.Role` instance.
|
||||
:param system: The system name
|
||||
:return: ``None``
|
||||
"""
|
||||
group = self._get_resource(_group.Group, group)
|
||||
role = self._get_resource(_role.Role, role)
|
||||
system = self._get_resource(_system.System, system)
|
||||
system.unassign_role_from_group(self, group, role)
|
||||
|
||||
def validate_group_has_system_role(self, group, role, system):
|
||||
"""Validates that a group has a role on a system
|
||||
|
||||
:param group: Either the ID of a group or a
|
||||
:class:`~openstack.identity.v3.group.Group` instance.
|
||||
:param role: Either the ID of a role or a
|
||||
:class:`~openstack.identity.v3.role.Role` instance.
|
||||
:param system: The system name
|
||||
:returns: True if group has role on system
|
||||
"""
|
||||
group = self._get_resource(_group.Group, group)
|
||||
role = self._get_resource(_role.Role, role)
|
||||
system = self._get_resource(_system.System, system)
|
||||
return system.validate_group_has_role(self, group, role)
|
||||
|
||||
def application_credentials(self, user, **query):
|
||||
"""Retrieve a generator of application credentials
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack import resource
|
||||
|
||||
|
||||
class RoleSystemGroupAssignment(resource.Resource):
|
||||
resource_key = 'role'
|
||||
resources_key = 'roles'
|
||||
base_path = '/system/groups/%(group_id)s/roles'
|
||||
|
||||
# capabilities
|
||||
allow_list = True
|
||||
|
||||
# Properties
|
||||
#: The ID of the group to list assignment from. *Type: string*
|
||||
group_id = resource.URI('group_id')
|
||||
#: The name of the system to list assignment from. *Type: string*
|
||||
system_id = resource.URI('system_id')
|
|
@ -0,0 +1,28 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack import resource
|
||||
|
||||
|
||||
class RoleSystemUserAssignment(resource.Resource):
|
||||
resource_key = 'role'
|
||||
resources_key = 'roles'
|
||||
base_path = '/system/users/%(user_id)s/roles'
|
||||
|
||||
# capabilities
|
||||
allow_list = True
|
||||
|
||||
# Properties
|
||||
#: The name of the system to list assignment from. *Type: string*
|
||||
system_id = resource.URI('system_id')
|
||||
#: The ID of the user to list assignment from. *Type: string*
|
||||
user_id = resource.URI('user_id')
|
|
@ -0,0 +1,75 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack import resource
|
||||
from openstack import utils
|
||||
|
||||
|
||||
class System(resource.Resource):
|
||||
resource_key = 'system'
|
||||
base_path = '/system'
|
||||
|
||||
# capabilities
|
||||
|
||||
def assign_role_to_user(self, session, user, role):
|
||||
"""Assign role to user on system"""
|
||||
url = utils.urljoin(self.base_path, 'users', user.id,
|
||||
'roles', role.id)
|
||||
resp = session.put(url,)
|
||||
if resp.status_code == 204:
|
||||
return True
|
||||
return False
|
||||
|
||||
def validate_user_has_role(self, session, user, role):
|
||||
"""Validates that a user has a role on a system"""
|
||||
url = utils.urljoin(self.base_path, 'users', user.id,
|
||||
'roles', role.id)
|
||||
resp = session.head(url,)
|
||||
if resp.status_code == 204:
|
||||
return True
|
||||
return False
|
||||
|
||||
def unassign_role_from_user(self, session, user, role):
|
||||
"""Unassigns a role from a user on a system"""
|
||||
url = utils.urljoin(self.base_path, 'users', user.id,
|
||||
'roles', role.id)
|
||||
resp = session.delete(url,)
|
||||
if resp.status_code == 204:
|
||||
return True
|
||||
return False
|
||||
|
||||
def assign_role_to_group(self, session, group, role):
|
||||
"""Assign role to group on system"""
|
||||
url = utils.urljoin(self.base_path, 'groups', group.id,
|
||||
'roles', role.id)
|
||||
resp = session.put(url,)
|
||||
if resp.status_code == 204:
|
||||
return True
|
||||
return False
|
||||
|
||||
def validate_group_has_role(self, session, group, role):
|
||||
"""Validates that a group has a role on a system"""
|
||||
url = utils.urljoin(self.base_path, 'groups', group.id,
|
||||
'roles', role.id)
|
||||
resp = session.head(url,)
|
||||
if resp.status_code == 204:
|
||||
return True
|
||||
return False
|
||||
|
||||
def unassign_role_from_group(self, session, group, role):
|
||||
"""Unassigns a role from a group on a system"""
|
||||
url = utils.urljoin(self.base_path, 'groups', group.id,
|
||||
'roles', role.id)
|
||||
resp = session.delete(url,)
|
||||
if resp.status_code == 204:
|
||||
return True
|
||||
return False
|
|
@ -248,3 +248,58 @@ class TestIdentity(base.KeystoneBaseFunctionalTest):
|
|||
})
|
||||
self.assertIsInstance(assignments, list)
|
||||
self.assertEqual(0, len(assignments))
|
||||
|
||||
def test_grant_revoke_role_user_system(self):
|
||||
role_name = self.role_prefix + '_grant_user_system'
|
||||
role = self.operator_cloud.create_role(role_name)
|
||||
user_name = self.user_prefix + '_user_system'
|
||||
user_email = 'nobody@nowhere.com'
|
||||
user = self._create_user(name=user_name,
|
||||
email=user_email,
|
||||
default_project='demo')
|
||||
self.assertTrue(self.operator_cloud.grant_role(
|
||||
role_name, user=user['id'], system='all'))
|
||||
assignments = self.operator_cloud.list_role_assignments({
|
||||
'role': role['id'],
|
||||
'user': user['id'],
|
||||
'system': 'all'
|
||||
})
|
||||
self.assertIsInstance(assignments, list)
|
||||
self.assertEqual(1, len(assignments))
|
||||
self.assertTrue(self.operator_cloud.revoke_role(
|
||||
role_name, user=user['id'], system='all'))
|
||||
assignments = self.operator_cloud.list_role_assignments({
|
||||
'role': role['id'],
|
||||
'user': user['id'],
|
||||
'system': 'all'
|
||||
})
|
||||
self.assertIsInstance(assignments, list)
|
||||
self.assertEqual(0, len(assignments))
|
||||
|
||||
def test_grant_revoke_role_group_system(self):
|
||||
if self.identity_version in ('2', '2.0'):
|
||||
self.skipTest("Identity service does not support system or group")
|
||||
role_name = self.role_prefix + '_grant_group_system'
|
||||
role = self.operator_cloud.create_role(role_name)
|
||||
group_name = self.group_prefix + '_group_system'
|
||||
group = self.operator_cloud.create_group(
|
||||
name=group_name,
|
||||
description='test group')
|
||||
self.assertTrue(self.operator_cloud.grant_role(
|
||||
role_name, group=group['id'], system='all'))
|
||||
assignments = self.operator_cloud.list_role_assignments({
|
||||
'role': role['id'],
|
||||
'group': group['id'],
|
||||
'system': 'all'
|
||||
})
|
||||
self.assertIsInstance(assignments, list)
|
||||
self.assertEqual(1, len(assignments))
|
||||
self.assertTrue(self.operator_cloud.revoke_role(
|
||||
role_name, group=group['id'], system='all'))
|
||||
assignments = self.operator_cloud.list_role_assignments({
|
||||
'role': role['id'],
|
||||
'group': group['id'],
|
||||
'system': 'all'
|
||||
})
|
||||
self.assertIsInstance(assignments, list)
|
||||
self.assertEqual(0, len(assignments))
|
||||
|
|
|
@ -1364,14 +1364,14 @@ class TestRoleAssignment(base.TestCase):
|
|||
|
||||
with testtools.ExpectedException(
|
||||
exc.OpenStackCloudException,
|
||||
'Must specify either a domain or project'
|
||||
'Must specify either a domain, project or system'
|
||||
):
|
||||
self.cloud.grant_role(
|
||||
self.role_data.role_name,
|
||||
user=self.user_data.name)
|
||||
self.assert_calls()
|
||||
|
||||
def test_revoke_no_project_or_domain(self):
|
||||
def test_revoke_no_project_or_domain_or_system(self):
|
||||
uris = self._get_mock_role_query_urls(
|
||||
self.role_data,
|
||||
user_data=self.user_data,
|
||||
|
@ -1381,7 +1381,7 @@ class TestRoleAssignment(base.TestCase):
|
|||
|
||||
with testtools.ExpectedException(
|
||||
exc.OpenStackCloudException,
|
||||
'Must specify either a domain or project'
|
||||
'Must specify either a domain, project or system'
|
||||
):
|
||||
self.cloud.revoke_role(
|
||||
self.role_data.role_name,
|
||||
|
|
|
@ -499,3 +499,75 @@ class TestIdentityProxyRoleAssignments(TestIdentityProxyBase):
|
|||
self.proxy._get_resource(role.Role, 'rid')
|
||||
]
|
||||
)
|
||||
|
||||
def test_assign_system_role_to_user(self):
|
||||
self._verify(
|
||||
"openstack.identity.v3.system.System.assign_role_to_user",
|
||||
self.proxy.assign_system_role_to_user,
|
||||
method_kwargs={'user': 'uid', 'role': 'rid', 'system': 'all'},
|
||||
expected_args=[
|
||||
self.proxy,
|
||||
self.proxy._get_resource(user.User, 'uid'),
|
||||
self.proxy._get_resource(role.Role, 'rid')
|
||||
]
|
||||
)
|
||||
|
||||
def test_unassign_system_role_from_user(self):
|
||||
self._verify(
|
||||
"openstack.identity.v3.system.System.unassign_role_from_user",
|
||||
self.proxy.unassign_system_role_from_user,
|
||||
method_kwargs={'user': 'uid', 'role': 'rid', 'system': 'all'},
|
||||
expected_args=[
|
||||
self.proxy,
|
||||
self.proxy._get_resource(user.User, 'uid'),
|
||||
self.proxy._get_resource(role.Role, 'rid')
|
||||
]
|
||||
)
|
||||
|
||||
def test_validate_user_has_system_role(self):
|
||||
self._verify(
|
||||
"openstack.identity.v3.system.System.validate_user_has_role",
|
||||
self.proxy.validate_user_has_system_role,
|
||||
method_kwargs={'user': 'uid', 'role': 'rid', 'system': 'all'},
|
||||
expected_args=[
|
||||
self.proxy,
|
||||
self.proxy._get_resource(user.User, 'uid'),
|
||||
self.proxy._get_resource(role.Role, 'rid')
|
||||
]
|
||||
)
|
||||
|
||||
def test_assign_system_role_to_group(self):
|
||||
self._verify(
|
||||
"openstack.identity.v3.system.System.assign_role_to_group",
|
||||
self.proxy.assign_system_role_to_group,
|
||||
method_kwargs={'group': 'uid', 'role': 'rid', 'system': 'all'},
|
||||
expected_args=[
|
||||
self.proxy,
|
||||
self.proxy._get_resource(group.Group, 'uid'),
|
||||
self.proxy._get_resource(role.Role, 'rid')
|
||||
]
|
||||
)
|
||||
|
||||
def test_unassign_system_role_from_group(self):
|
||||
self._verify(
|
||||
"openstack.identity.v3.system.System.unassign_role_from_group",
|
||||
self.proxy.unassign_system_role_from_group,
|
||||
method_kwargs={'group': 'uid', 'role': 'rid', 'system': 'all'},
|
||||
expected_args=[
|
||||
self.proxy,
|
||||
self.proxy._get_resource(group.Group, 'uid'),
|
||||
self.proxy._get_resource(role.Role, 'rid')
|
||||
]
|
||||
)
|
||||
|
||||
def test_validate_group_has_system_role(self):
|
||||
self._verify(
|
||||
"openstack.identity.v3.system.System.validate_group_has_role",
|
||||
self.proxy.validate_group_has_system_role,
|
||||
method_kwargs={'group': 'uid', 'role': 'rid', 'system': 'all'},
|
||||
expected_args=[
|
||||
self.proxy,
|
||||
self.proxy._get_resource(group.Group, 'uid'),
|
||||
self.proxy._get_resource(role.Role, 'rid')
|
||||
]
|
||||
)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.identity.v3 import role_system_group_assignment
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
'id': IDENTIFIER,
|
||||
'name': '2',
|
||||
'group_id': '4'
|
||||
}
|
||||
|
||||
|
||||
class TestRoleSystemGroupAssignment(base.TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
sot = role_system_group_assignment.RoleSystemGroupAssignment()
|
||||
self.assertEqual('role', sot.resource_key)
|
||||
self.assertEqual('roles', sot.resources_key)
|
||||
self.assertEqual('/system/groups/%(group_id)s/roles',
|
||||
sot.base_path)
|
||||
self.assertTrue(sot.allow_list)
|
||||
|
||||
def test_make_it(self):
|
||||
sot = \
|
||||
role_system_group_assignment.RoleSystemGroupAssignment(**EXAMPLE)
|
||||
self.assertEqual(EXAMPLE['id'], sot.id)
|
||||
self.assertEqual(EXAMPLE['name'], sot.name)
|
||||
self.assertEqual(EXAMPLE['group_id'], sot.group_id)
|
|
@ -0,0 +1,39 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.identity.v3 import role_system_user_assignment
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
IDENTIFIER = 'IDENTIFIER'
|
||||
EXAMPLE = {
|
||||
'id': IDENTIFIER,
|
||||
'name': '2',
|
||||
'user_id': '4'
|
||||
}
|
||||
|
||||
|
||||
class TestRoleSystemUserAssignment(base.TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
sot = role_system_user_assignment.RoleSystemUserAssignment()
|
||||
self.assertEqual('role', sot.resource_key)
|
||||
self.assertEqual('roles', sot.resources_key)
|
||||
self.assertEqual('/system/users/%(user_id)s/roles',
|
||||
sot.base_path)
|
||||
self.assertTrue(sot.allow_list)
|
||||
|
||||
def test_make_it(self):
|
||||
sot = \
|
||||
role_system_user_assignment.RoleSystemUserAssignment(**EXAMPLE)
|
||||
self.assertEqual(EXAMPLE['id'], sot.id)
|
||||
self.assertEqual(EXAMPLE['name'], sot.name)
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Add support for system role assignment. A system role assignment
|
||||
ultimately controls access to system-level API calls.
|
||||
|
||||
Good examples of system-level APIs include management of the
|
||||
service catalog and compute hypervisors.
|
||||
|
||||
`System role assignment API reference
|
||||
<https://docs.openstack.org/api-ref/identity/v3/#system-role-assignments>`_.
|
Loading…
Reference in New Issue