Merge "Implement the Domain Manager Persona for Keystone"
This commit is contained in:
commit
dd30a921a2
@ -26,10 +26,14 @@ functionality to their team, auditors, customers, and users without maintaining
|
||||
custom policies.
|
||||
|
||||
In addition to ``admin``, ``member``, and ``reader`` role, from 2023.2 (Bobcat)
|
||||
release keystone will provide ``service`` role by default as well. Operators
|
||||
can use this role for service to service API calls instead of using ``admin``
|
||||
role for the same. The service role will be separate from ``admin``,
|
||||
``member``, ``reader`` and will not implicate any of these roles.
|
||||
release keystone will provide the ``service`` and ``manager`` roles by default
|
||||
as well. Operators can use the ``service`` role for service to service API
|
||||
calls instead of using ``admin`` role for the same. The service role will be
|
||||
separate from ``admin``, ``member``, ``reader`` and will not implicate any of
|
||||
these roles.
|
||||
Operators can give the ``manager`` role to users to within a domain to enable
|
||||
self-service management of users, groups, projects and role assignments within
|
||||
their domain.
|
||||
|
||||
.. _`token guide`: https://docs.openstack.org/keystone/latest/admin/tokens-overview.html#authorization-scopes
|
||||
|
||||
@ -39,14 +43,16 @@ Roles Definitions
|
||||
|
||||
The default roles provided by keystone via ``keystone-manage bootstrap``
|
||||
(except for the ``service`` role) are related through role implications. The
|
||||
``admin`` role implies the ``member`` role, and the ``member`` role implies
|
||||
the ``reader`` role. These implications mean users with the ``admin`` role
|
||||
automatically have the ``member`` and ``reader`` roles. Additionally,
|
||||
users with the ``member`` role automatically have the ``reader`` role.
|
||||
Implying roles reduces role assignments and forms a natural hierarchy between
|
||||
the default roles. It also reduces the complexity of default policies by
|
||||
making check strings short. For example, a policy that requires ``reader``
|
||||
can be expressed as:
|
||||
``admin`` role implies the ``manager`` role, the ``manager`` implies the
|
||||
``member`` role, and the ``member`` role implies the ``reader`` role. These
|
||||
implications mean users with the ``admin`` role automatically have the
|
||||
``manager``, ``member`` and ``reader`` roles. Additionally, users with the
|
||||
``manager`` role automatically have the ``member`` and ``reader`` roles. Users
|
||||
with the ``member`` role automatically have the ``reader`` role. Implying roles
|
||||
reduces role assignments and forms a natural hierarchy between the default
|
||||
roles. It also reduces the complexity of default policies by making check
|
||||
strings short. For example, a policy that requires ``reader`` can be expressed
|
||||
as:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
@ -56,7 +62,7 @@ Instead of:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
"identity:list_foo": "role:admin or role:member or role:reader"
|
||||
"identity:list_foo": "role:admin or role:manager or role:member or role:reader"
|
||||
|
||||
Reader
|
||||
======
|
||||
@ -122,6 +128,30 @@ users with ``admin`` on a project can list, create, and delete instances.
|
||||
Service developers can use the ``member`` role to provide more flexibility
|
||||
between ``admin`` and ``reader`` on different scopes.
|
||||
|
||||
Manager
|
||||
=======
|
||||
|
||||
The ``manager`` role takes a special place in keystone. It sits between the
|
||||
``admin`` and ``member`` role, allowing limited identity management while being
|
||||
clearly differentiated from the ``admin`` role both in terms of purpose and
|
||||
privileges. The ``manager`` role is meant to be assigned in a domain scope and
|
||||
enables users to manage identity assets in a whole domain including users,
|
||||
projects, groups and role assignments. This enables identity self-service
|
||||
management capabilities for users within a domain without the need to assign
|
||||
the most privileged ``admin`` role to them.
|
||||
|
||||
The keystone default policies include a special rule that specifies the list of
|
||||
roles a user with the ``manager`` role is be able to assign and revoke within
|
||||
the domain scope. This prevents such user from escalating their own privileges
|
||||
or those of others beyond ``manager`` and for this purpose the list excludes
|
||||
the ``admin`` role. The list can be adjusted by cloud administrators via policy
|
||||
definitions in case the role model differs. For example, if a new role is
|
||||
introduced for a specific cloud environment, the list can be adjusted to allow
|
||||
users with the ``manager`` role to also assign it.
|
||||
|
||||
Other services might write default policies to enable the ``manager`` role to
|
||||
have more privileged managing rights or cross-project privileges in a domain.
|
||||
|
||||
Admin
|
||||
=====
|
||||
|
||||
@ -255,14 +285,15 @@ role assignments on a specific domain using the following query:
|
||||
.. code-block:: console
|
||||
|
||||
$ openstack role assignment list --names --domain foobar
|
||||
+--------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
| Role | User | Group | Project | Domain | System | Inherited |
|
||||
+--------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
| reader | support@Default | | | foobar | | False |
|
||||
| admin | jsmith@Default | | | foobar | | False |
|
||||
| admin | | foobar-admins@foobar | | foobar | | False |
|
||||
| member | jdoe@foobar | | | foobar | | False |
|
||||
+--------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
+---------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
| Role | User | Group | Project | Domain | System | Inherited |
|
||||
+---------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
| reader | support@Default | | | foobar | | False |
|
||||
| admin | jsmith@Default | | | foobar | | False |
|
||||
| admin | | foobar-admins@foobar | | foobar | | False |
|
||||
| manager | alice@foobar | | | foobar | | False |
|
||||
| member | jdoe@foobar | | | foobar | | False |
|
||||
+---------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
|
||||
Domain Administrators
|
||||
=====================
|
||||
@ -288,6 +319,32 @@ assignment:
|
||||
| admin | | foobar-admins@foobar | | foobar | | False |
|
||||
+-------+----------------+----------------------+---------+--------+--------+-----------+
|
||||
|
||||
Domain Managers
|
||||
===============
|
||||
|
||||
*Domain managers* can only manage specific resources related to identity
|
||||
management within their domain. This includes creating new users, projects and
|
||||
groups as well as updating and deleting them. They can also assign and revoke
|
||||
roles between those or in relation to the domain. Furthermore, they can inspect
|
||||
role assignments within the domain.
|
||||
|
||||
*Domain managers* cannot change any aspects of the domain itself. The role
|
||||
assignments they can apply within their domain is limited to a specific list of
|
||||
applicable roles and in the default configuration, this excludes the ``admin``
|
||||
role to prevent privilege escalation.
|
||||
|
||||
You can find *domain managers* in your deployment with the following role
|
||||
assignment:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ openstack role assignment list --names --domain foobar --role manager
|
||||
+---------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
| Role | User | Group | Project | Domain | System | Inherited |
|
||||
+---------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
| manager | alice@foobar | | | foobar | | False |
|
||||
+---------+-----------------+----------------------+---------+--------+--------+-----------+
|
||||
|
||||
Domain Members & Domain Readers
|
||||
===============================
|
||||
|
||||
|
@ -111,7 +111,10 @@ class RoleResource(ks_flask.ResourceBase):
|
||||
"""
|
||||
role = self.request_body_json.get('role', {})
|
||||
if self._is_domain_role(role):
|
||||
ENFORCER.enforce_call(action='identity:create_domain_role')
|
||||
target = {'role': role}
|
||||
ENFORCER.enforce_call(
|
||||
action='identity:create_domain_role', target_attr=target
|
||||
)
|
||||
else:
|
||||
ENFORCER.enforce_call(action='identity:create_role')
|
||||
validation.lazy_validate(schema.role_create, role)
|
||||
|
@ -65,6 +65,18 @@ ADMIN_OR_CRED_OWNER = (
|
||||
'(' + RULE_ADMIN_REQUIRED + ') ' 'or user_id:%(target.credential.user_id)s'
|
||||
)
|
||||
|
||||
# This rule template is meant for restricting role assignments done by domain
|
||||
# managers. It is intended to restrict the roles a domain manager can assign or
|
||||
# revoke to a sensible default set while allowing overrides via policy file by
|
||||
# adjusting the corresponding rule definition.
|
||||
# For the default, any roles with higher-level privileges than "manager" (e.g.
|
||||
# "admin") must be omitted to avoid privilege escalation.
|
||||
DOMAIN_MANAGER_ALLOWED_ROLES = (
|
||||
"'manager':%(target.role.name)s or "
|
||||
"'member':%(target.role.name)s or "
|
||||
"'reader':%(target.role.name)s"
|
||||
)
|
||||
|
||||
rules = [
|
||||
policy.RuleDefault(
|
||||
name='admin_required', check_str='role:admin or is_admin:1'
|
||||
@ -89,6 +101,10 @@ rules = [
|
||||
name='service_admin_or_token_subject',
|
||||
check_str='rule:service_or_admin or rule:token_subject',
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name="domain_managed_target_role",
|
||||
check_str=DOMAIN_MANAGER_ALLOWED_ROLES,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
@ -61,6 +61,17 @@ GRANTS_DOMAIN_ADMIN = (
|
||||
' ' + DOMAIN_MATCHES_TARGET_DOMAIN + ')'
|
||||
)
|
||||
|
||||
GRANTS_DOMAIN_MANAGER = (
|
||||
'(role:manager and ' + DOMAIN_MATCHES_USER_DOMAIN + ' and'
|
||||
' ' + DOMAIN_MATCHES_PROJECT_DOMAIN + ') or '
|
||||
'(role:manager and ' + DOMAIN_MATCHES_USER_DOMAIN + ' and'
|
||||
' ' + DOMAIN_MATCHES_TARGET_DOMAIN + ') or '
|
||||
'(role:manager and ' + DOMAIN_MATCHES_GROUP_DOMAIN + ' and'
|
||||
' ' + DOMAIN_MATCHES_PROJECT_DOMAIN + ') or '
|
||||
'(role:manager and ' + DOMAIN_MATCHES_GROUP_DOMAIN + ' and'
|
||||
' ' + DOMAIN_MATCHES_TARGET_DOMAIN + ')'
|
||||
)
|
||||
|
||||
ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER = (
|
||||
'(' + base.RULE_ADMIN_REQUIRED + ') or '
|
||||
'(' + SYSTEM_READER_OR_DOMAIN_READER + ')'
|
||||
@ -71,10 +82,12 @@ ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER_LIST = (
|
||||
'(' + SYSTEM_READER_OR_DOMAIN_READER_LIST + ')'
|
||||
)
|
||||
|
||||
ADMIN_OR_DOMAIN_ADMIN = (
|
||||
ADMIN_OR_DOMAIN_ADMIN_OR_DOMAIN_MANAGER = (
|
||||
'(' + base.RULE_ADMIN_REQUIRED + ') or '
|
||||
'(' + GRANTS_DOMAIN_ADMIN + ') and '
|
||||
'(' + DOMAIN_MATCHES_ROLE + ')'
|
||||
'(' + DOMAIN_MATCHES_ROLE + ') or '
|
||||
'(' + GRANTS_DOMAIN_MANAGER + ') and '
|
||||
'rule:domain_managed_target_role'
|
||||
)
|
||||
|
||||
DEPRECATED_REASON = (
|
||||
@ -236,7 +249,7 @@ grant_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'create_grant',
|
||||
check_str=ADMIN_OR_DOMAIN_ADMIN,
|
||||
check_str=ADMIN_OR_DOMAIN_ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description=(
|
||||
'Create a role grant between a target and an actor. A '
|
||||
@ -251,7 +264,7 @@ grant_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'revoke_grant',
|
||||
check_str=ADMIN_OR_DOMAIN_ADMIN,
|
||||
check_str=ADMIN_OR_DOMAIN_ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description=(
|
||||
'Revoke a role grant between a target and an actor. A '
|
||||
|
@ -33,6 +33,14 @@ SYSTEM_READER_OR_DOMAIN_READER_FOR_TARGET_GROUP_USER = (
|
||||
'domain_id:%(target.group.domain_id)s and '
|
||||
'domain_id:%(target.user.domain_id)s)'
|
||||
)
|
||||
DOMAIN_MANAGER_FOR_TARGET_GROUP = (
|
||||
'role:manager and domain_id:%(target.group.domain_id)s'
|
||||
)
|
||||
DOMAIN_MANAGER_FOR_TARGET_GROUP_USER = (
|
||||
'role:manager and '
|
||||
'domain_id:%(target.group.domain_id)s and '
|
||||
'domain_id:%(target.user.domain_id)s'
|
||||
)
|
||||
ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER_FOR_TARGET_GROUP = (
|
||||
'('
|
||||
+ base.RULE_ADMIN_REQUIRED
|
||||
@ -53,6 +61,21 @@ SYSTEM_ADMIN_OR_DOMAIN_ADMIN = (
|
||||
'(role:admin and domain_id:%(target.group.domain_id)s)'
|
||||
)
|
||||
|
||||
ADMIN_OR_DOMAIN_MANAGER_FOR_GROUPS = (
|
||||
'('
|
||||
+ base.RULE_ADMIN_REQUIRED
|
||||
+ ') or ('
|
||||
+ DOMAIN_MANAGER_FOR_TARGET_GROUP
|
||||
+ ')'
|
||||
)
|
||||
ADMIN_OR_DOMAIN_MANAGER_FOR_GROUP_ASSIGNMENTS = (
|
||||
'('
|
||||
+ base.RULE_ADMIN_REQUIRED
|
||||
+ ') or ('
|
||||
+ DOMAIN_MANAGER_FOR_TARGET_GROUP_USER
|
||||
+ ')'
|
||||
)
|
||||
|
||||
DEPRECATED_REASON = (
|
||||
"The group API is now aware of system scope and default roles."
|
||||
)
|
||||
@ -154,7 +177,7 @@ group_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'create_group',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER_FOR_GROUPS,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Create group.',
|
||||
operations=[{'path': '/v3/groups', 'method': 'POST'}],
|
||||
@ -162,7 +185,7 @@ group_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'update_group',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER_FOR_GROUPS,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Update group.',
|
||||
operations=[{'path': '/v3/groups/{group_id}', 'method': 'PATCH'}],
|
||||
@ -170,7 +193,7 @@ group_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'delete_group',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER_FOR_GROUPS,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Delete group.',
|
||||
operations=[{'path': '/v3/groups/{group_id}', 'method': 'DELETE'}],
|
||||
@ -189,7 +212,7 @@ group_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'remove_user_from_group',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER_FOR_GROUP_ASSIGNMENTS,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Remove user from group.',
|
||||
operations=[
|
||||
@ -216,7 +239,7 @@ group_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'add_user_to_group',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER_FOR_GROUP_ASSIGNMENTS,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Add user to group.',
|
||||
operations=[
|
||||
|
@ -49,7 +49,7 @@ SYSTEM_READER_OR_DOMAIN_READER_OR_OWNER = (
|
||||
# the context user_id to the target user id.
|
||||
'user_id:%(target.user.id)s'
|
||||
)
|
||||
ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER_OR_OWNER = (
|
||||
ADMIN_SYSTEM_READER_OR_DOMAIN_READER_OR_OWNER = (
|
||||
'('
|
||||
+ base.RULE_ADMIN_REQUIRED
|
||||
+ ') or '
|
||||
@ -65,9 +65,9 @@ ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER = (
|
||||
'(' + base.RULE_ADMIN_REQUIRED + ') or ' + SYSTEM_READER_OR_DOMAIN_READER
|
||||
)
|
||||
|
||||
SYSTEM_ADMIN_OR_DOMAIN_ADMIN = (
|
||||
'(role:admin and system_scope:all) or '
|
||||
'(role:admin and domain_id:%(target.project.domain_id)s)'
|
||||
ADMIN_OR_DOMAIN_MANAGER = (
|
||||
'(' + base.RULE_ADMIN_REQUIRED + ') or '
|
||||
'(role:manager and domain_id:%(target.project.domain_id)s)'
|
||||
)
|
||||
|
||||
DEPRECATED_REASON = (
|
||||
@ -175,7 +175,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'list_user_projects',
|
||||
check_str=ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER_OR_OWNER,
|
||||
check_str=ADMIN_SYSTEM_READER_OR_DOMAIN_READER_OR_OWNER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='List projects for user.',
|
||||
operations=[{'path': '/v3/users/{user_id}/projects', 'method': 'GET'}],
|
||||
@ -183,7 +183,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'create_project',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Create project.',
|
||||
operations=[{'path': '/v3/projects', 'method': 'POST'}],
|
||||
@ -191,7 +191,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'update_project',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Update project.',
|
||||
operations=[{'path': '/v3/projects/{project_id}', 'method': 'PATCH'}],
|
||||
@ -199,7 +199,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'delete_project',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Delete project.',
|
||||
operations=[{'path': '/v3/projects/{project_id}', 'method': 'DELETE'}],
|
||||
@ -235,7 +235,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'update_project_tags',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Replace all tags on a project with the new set of tags.',
|
||||
operations=[
|
||||
@ -245,7 +245,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'create_project_tag',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Add a single tag to a project.',
|
||||
operations=[
|
||||
@ -255,7 +255,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'delete_project_tags',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Remove all tags from a project.',
|
||||
operations=[
|
||||
@ -265,7 +265,7 @@ project_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'delete_project_tag',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Delete a specified tag from project.',
|
||||
operations=[
|
||||
|
@ -15,6 +15,19 @@ from oslo_policy import policy
|
||||
|
||||
from keystone.common.policies import base
|
||||
|
||||
ADMIN_OR_SYSTEM_READER_OR_DOMAIN_MANAGER_ROLE = (
|
||||
'(' + base.RULE_ADMIN_OR_SYSTEM_READER + ') or '
|
||||
'(role:manager and rule:domain_managed_target_role)'
|
||||
)
|
||||
|
||||
# For the domain manager persona we only check for a domain id in the token
|
||||
# that is not None here to exclude scopes like a project manager. Since most
|
||||
# roles are global we do not have a target domain attribute to match against.
|
||||
ADMIN_OR_SYSTEM_READER_OR_DOMAIN_MANAGER = (
|
||||
'(' + base.RULE_ADMIN_OR_SYSTEM_READER + ') or '
|
||||
'(role:manager and not domain_id:None)'
|
||||
)
|
||||
|
||||
DEPRECATED_REASON = (
|
||||
"The role API is now aware of system scope and default roles."
|
||||
)
|
||||
@ -84,7 +97,7 @@ deprecated_delete_domain_role = policy.DeprecatedRule(
|
||||
role_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'get_role',
|
||||
check_str=base.RULE_ADMIN_OR_SYSTEM_READER,
|
||||
check_str=ADMIN_OR_SYSTEM_READER_OR_DOMAIN_MANAGER_ROLE,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Show role details.',
|
||||
operations=[
|
||||
@ -95,7 +108,7 @@ role_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'list_roles',
|
||||
check_str=base.RULE_ADMIN_OR_SYSTEM_READER,
|
||||
check_str=ADMIN_OR_SYSTEM_READER_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='List roles.',
|
||||
operations=[
|
||||
|
@ -30,10 +30,16 @@ ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER_OR_USER = (
|
||||
SYSTEM_READER_OR_DOMAIN_READER = (
|
||||
'(' + base.SYSTEM_READER + ') or (' + base.DOMAIN_READER + ')'
|
||||
)
|
||||
ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER = (
|
||||
|
||||
ADMIN_SYSTEM_READER_OR_DOMAIN_READER = (
|
||||
'(' + base.RULE_ADMIN_REQUIRED + ') or ' + SYSTEM_READER_OR_DOMAIN_READER
|
||||
)
|
||||
|
||||
ADMIN_OR_DOMAIN_MANAGER = (
|
||||
'(' + base.RULE_ADMIN_REQUIRED + ') or '
|
||||
'(role:manager and token.domain.id:%(target.user.domain_id)s)'
|
||||
)
|
||||
|
||||
DEPRECATED_REASON = (
|
||||
"The user API is now aware of system scope and default roles."
|
||||
)
|
||||
@ -83,7 +89,7 @@ user_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'list_users',
|
||||
check_str=ADMIN_OR_SYSTEM_READER_OR_DOMAIN_READER,
|
||||
check_str=ADMIN_SYSTEM_READER_OR_DOMAIN_READER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='List users.',
|
||||
operations=[
|
||||
@ -120,7 +126,7 @@ user_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'create_user',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Create a user.',
|
||||
operations=[{'path': '/v3/users', 'method': 'POST'}],
|
||||
@ -128,7 +134,7 @@ user_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'update_user',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Update a user, including administrative password resets.',
|
||||
operations=[{'path': '/v3/users/{user_id}', 'method': 'PATCH'}],
|
||||
@ -136,7 +142,7 @@ user_policies = [
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'delete_user',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
check_str=ADMIN_OR_DOMAIN_MANAGER,
|
||||
scope_types=['system', 'domain', 'project'],
|
||||
description='Delete a user.',
|
||||
operations=[{'path': '/v3/users/{user_id}', 'method': 'DELETE'}],
|
||||
|
@ -243,6 +243,7 @@ class PolicyJsonTestCase(unit.TestCase):
|
||||
'service_or_admin',
|
||||
'service_role',
|
||||
'token_subject',
|
||||
'domain_managed_target_role',
|
||||
]
|
||||
|
||||
def read_doc_targets():
|
||||
|
@ -0,0 +1,12 @@
|
||||
---
|
||||
features:
|
||||
- >
|
||||
[`bug 2045974 <https://bugs.launchpad.net/keystone/+bug/2045974>`_]
|
||||
The Domain Manager Persona has been added. This makes identity-related
|
||||
self-service capabilities for users within domains possible without
|
||||
requiring the 'admin' role. Assigning the 'manager' role to users in domain
|
||||
scope now allows them to manage projects, groups, users and role
|
||||
assignments within the domain. This is subject to the following
|
||||
restriction: the roles that domain managers can assign and revoke are
|
||||
limited by a new ``domain_managed_target_role`` policy rule which defaults
|
||||
to 'reader', 'member' and 'manager'.
|
Loading…
Reference in New Issue
Block a user