Merge "Deprecate legacy policies, update project scoped docs"
This commit is contained in:
@@ -213,13 +213,44 @@ from "Does the user user broadly has access to the API?" to
|
|||||||
"Does user have access to the node, and then do they have access
|
"Does user have access to the node, and then do they have access
|
||||||
to the specific resource?".
|
to the specific resource?".
|
||||||
|
|
||||||
|
What is an owner or lessee?
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
An ``owner`` or ``lessee`` is the project which has been assigned baremetal
|
||||||
|
resources. Generally these should be service projects as opposed to a project
|
||||||
|
dedicated to a specific user. This will help prevent the need to involve a
|
||||||
|
``system`` scoped administrator from having to correct ownership records
|
||||||
|
should a project need to be removed due to an individual's departure.
|
||||||
|
|
||||||
|
The underlying ``project_id`` is used to represent and associate the owner or
|
||||||
|
lessee.
|
||||||
|
|
||||||
How do I assign an owner?
|
How do I assign an owner?
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
.. todo: need to add information on the owner assignment
|
.. code-block:: console
|
||||||
and also cover what this generally means... maybe?
|
|
||||||
|
# baremetal node set --owner <project_id> <node>
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
With the default access policy, an ``owner`` is able to change
|
||||||
|
the assigned ``lessee`` of a node. However the ``lessee`` is unable to do
|
||||||
|
the same.
|
||||||
|
|
||||||
How do I assign a lessee?
|
How do I assign a lessee?
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
.. todo: Need to cover how to assign a lessee.
|
.. code-block:: console
|
||||||
|
|
||||||
|
# baremetal node set --lessee <project_id> <node>
|
||||||
|
|
||||||
|
What is the difference between an owner and lessee?
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
This is largely covered in `How Project Scoped Works`_ although
|
||||||
|
as noted it is largely in means of access. A ``lessee`` is far more
|
||||||
|
restrictive and an ``owner`` may revoke access to ``lessee``.
|
||||||
|
|
||||||
|
Access to the underlying baremetal node is not exclusive between the
|
||||||
|
``owner`` and ``lessee``, and this use model expects that some level of
|
||||||
|
communication takes place between the appropriate parties.
|
||||||
|
@@ -52,6 +52,9 @@ class RequestContext(context.RequestContext):
|
|||||||
def get_admin_context():
|
def get_admin_context():
|
||||||
"""Create an administrator context."""
|
"""Create an administrator context."""
|
||||||
|
|
||||||
|
# TODO(TheJulia): Revise in Xena, is_admin should
|
||||||
|
# no longer be a default, much less passed as it is
|
||||||
|
# deprecated.
|
||||||
context = RequestContext(auth_token=None,
|
context = RequestContext(auth_token=None,
|
||||||
project_id=None,
|
project_id=None,
|
||||||
is_admin=True,
|
is_admin=True,
|
||||||
|
@@ -110,8 +110,15 @@ def is_image_available(context, image):
|
|||||||
# The presence of an auth token implies this is an authenticated
|
# The presence of an auth token implies this is an authenticated
|
||||||
# request and we need not handle the noauth use-case.
|
# request and we need not handle the noauth use-case.
|
||||||
if hasattr(context, 'auth_token') and context.auth_token:
|
if hasattr(context, 'auth_token') and context.auth_token:
|
||||||
|
# We return true here since we want the *user* request context to
|
||||||
|
# be able to be used.
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# TODO(TheJulia): This is potentially a bug below. Admin context doesn't
|
||||||
|
# necessarilly mean the object is *actually* accessible. We should likely
|
||||||
|
# just ask glance... Although everything should also have an auth_token
|
||||||
|
# as noted above. Ultimately we need to tease the is_admin logic apart
|
||||||
|
# and treat things appropriately by checking them as needed.
|
||||||
if getattr(image, 'visibility', None) == 'public' or context.is_admin:
|
if getattr(image, 'visibility', None) == 'public' or context.is_admin:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@@ -148,13 +148,19 @@ TARGET_PROPERTIES_READER = (
|
|||||||
'(' + SYSTEM_READER + ') or (role:admin)'
|
'(' + SYSTEM_READER + ') or (role:admin)'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pre_rbac_deprecated_reason = 'Pre-RBAC default rule. This rule does not support scoping system scoping and as such is deprecated.' # noqa
|
||||||
|
|
||||||
default_policies = [
|
default_policies = [
|
||||||
# Legacy setting, don't remove. Likely to be overridden by operators who
|
# Legacy setting, don't remove. Likely to be overridden by operators who
|
||||||
# forget to update their policy.json configuration file.
|
# forget to update their policy.json configuration file.
|
||||||
# This gets rolled into the new "is_admin" rule below.
|
# This gets rolled into the new "is_admin" rule below.
|
||||||
policy.RuleDefault('admin_api',
|
policy.RuleDefault('admin_api',
|
||||||
'role:admin or role:administrator',
|
'role:admin or role:administrator',
|
||||||
description='Legacy rule for cloud admin access'),
|
description='Legacy rule for cloud admin access',
|
||||||
|
deprecated_for_removal=True,
|
||||||
|
deprecated_since=versionutils.deprecated.WALLABY,
|
||||||
|
deprecated_reason=pre_rbac_deprecated_reason
|
||||||
|
),
|
||||||
# is_public_api is set in the environment from AuthPublicRoutes
|
# is_public_api is set in the environment from AuthPublicRoutes
|
||||||
# TODO(TheJulia): Once legacy policy rules are removed, is_public_api
|
# TODO(TheJulia): Once legacy policy rules are removed, is_public_api
|
||||||
# can be removed from the code base.
|
# can be removed from the code base.
|
||||||
@@ -178,22 +184,40 @@ default_policies = [
|
|||||||
# TODO(TheJulia): Lets nuke demo from high orbit.
|
# TODO(TheJulia): Lets nuke demo from high orbit.
|
||||||
policy.RuleDefault('is_member',
|
policy.RuleDefault('is_member',
|
||||||
'(project_domain_id:default or project_domain_id:None) and (project_name:demo or project_name:baremetal)', # noqa
|
'(project_domain_id:default or project_domain_id:None) and (project_name:demo or project_name:baremetal)', # noqa
|
||||||
description='May be used to restrict access to specific projects'), # noqa
|
description='May be used to restrict access to specific projects', # noqa
|
||||||
|
deprecated_for_removal=True,
|
||||||
|
deprecated_since=versionutils.deprecated.WALLABY,
|
||||||
|
deprecated_reason=pre_rbac_deprecated_reason),
|
||||||
policy.RuleDefault('is_observer',
|
policy.RuleDefault('is_observer',
|
||||||
'rule:is_member and (role:observer or role:baremetal_observer)', # noqa
|
'rule:is_member and (role:observer or role:baremetal_observer)', # noqa
|
||||||
description='Read-only API access'),
|
description='Read-only API access',
|
||||||
|
deprecated_for_removal=True,
|
||||||
|
deprecated_since=versionutils.deprecated.WALLABY,
|
||||||
|
deprecated_reason=pre_rbac_deprecated_reason),
|
||||||
policy.RuleDefault('is_admin',
|
policy.RuleDefault('is_admin',
|
||||||
'rule:admin_api or (rule:is_member and role:baremetal_admin)', # noqa
|
'rule:admin_api or (rule:is_member and role:baremetal_admin)', # noqa
|
||||||
description='Full read/write API access'),
|
description='Full read/write API access',
|
||||||
|
deprecated_for_removal=True,
|
||||||
|
deprecated_since=versionutils.deprecated.WALLABY,
|
||||||
|
deprecated_reason=pre_rbac_deprecated_reason),
|
||||||
policy.RuleDefault('is_node_owner',
|
policy.RuleDefault('is_node_owner',
|
||||||
'project_id:%(node.owner)s',
|
'project_id:%(node.owner)s',
|
||||||
description='Owner of node'),
|
description='Owner of node',
|
||||||
|
deprecated_for_removal=True,
|
||||||
|
deprecated_since=versionutils.deprecated.WALLABY,
|
||||||
|
deprecated_reason=pre_rbac_deprecated_reason),
|
||||||
policy.RuleDefault('is_node_lessee',
|
policy.RuleDefault('is_node_lessee',
|
||||||
'project_id:%(node.lessee)s',
|
'project_id:%(node.lessee)s',
|
||||||
description='Lessee of node'),
|
description='Lessee of node',
|
||||||
|
deprecated_for_removal=True,
|
||||||
|
deprecated_since=versionutils.deprecated.WALLABY,
|
||||||
|
deprecated_reason=pre_rbac_deprecated_reason),
|
||||||
policy.RuleDefault('is_allocation_owner',
|
policy.RuleDefault('is_allocation_owner',
|
||||||
'project_id:%(allocation.owner)s',
|
'project_id:%(allocation.owner)s',
|
||||||
description='Owner of allocation'),
|
description='Owner of allocation',
|
||||||
|
deprecated_for_removal=True,
|
||||||
|
deprecated_since=versionutils.deprecated.WALLABY,
|
||||||
|
deprecated_reason=pre_rbac_deprecated_reason),
|
||||||
]
|
]
|
||||||
|
|
||||||
# NOTE(tenbrae): to follow policy-in-code spec, we define defaults for
|
# NOTE(tenbrae): to follow policy-in-code spec, we define defaults for
|
||||||
@@ -582,21 +606,6 @@ node_policies = [
|
|||||||
deprecated_reason=deprecated_node_reason,
|
deprecated_reason=deprecated_node_reason,
|
||||||
deprecated_since=versionutils.deprecated.WALLABY
|
deprecated_since=versionutils.deprecated.WALLABY
|
||||||
),
|
),
|
||||||
# TODO(TheJulia): So multiple additional fields need policies. This needs
|
|
||||||
# to be reviewed/audited/addressed.
|
|
||||||
# * Get ability on last_error - policy added
|
|
||||||
# * Get ability on reservation (conductor names) - policy added
|
|
||||||
# * get ability on driver_internal_info (internal addressing) added
|
|
||||||
# * ability to get driver_info - policy added
|
|
||||||
# * ability to set driver_info - policy added
|
|
||||||
# * ability to set properties. - added
|
|
||||||
# * ability to set chassis_uuid - added
|
|
||||||
# * ability to set instance_uuid - added
|
|
||||||
# * ability to set a lessee - default only to admin or owner. added
|
|
||||||
# * ability to set driver/*_interface - added
|
|
||||||
# * ability to set network_data - added
|
|
||||||
# * ability to set conductor_group -added
|
|
||||||
# * ability to set name -added
|
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
name='baremetal:node:update_instance_info',
|
name='baremetal:node:update_instance_info',
|
||||||
check_str=SYSTEM_OR_OWNER_MEMBER_AND_LESSEE_ADMIN,
|
check_str=SYSTEM_OR_OWNER_MEMBER_AND_LESSEE_ADMIN,
|
||||||
|
@@ -1345,6 +1345,10 @@ class AgentDeployMixin(HeartbeatMixin, AgentOobStepsMixin):
|
|||||||
image_source = node.instance_info.get('image_source')
|
image_source = node.instance_info.get('image_source')
|
||||||
try:
|
try:
|
||||||
context = task.context
|
context = task.context
|
||||||
|
# TODO(TheJulia): Uhh, is_admin likely needs to be
|
||||||
|
# addressed in Xena as undesirable behavior may
|
||||||
|
# result, or just outright break in an entirely
|
||||||
|
# system scoped configuration.
|
||||||
context.is_admin = True
|
context.is_admin = True
|
||||||
glance = image_service.GlanceImageService(
|
glance = image_service.GlanceImageService(
|
||||||
context=context)
|
context=context)
|
||||||
|
45
releasenotes/notes/project-scoped-rbac-063c44ba593bb82a.yaml
Normal file
45
releasenotes/notes/project-scoped-rbac-063c44ba593bb82a.yaml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds capability to use ``project`` scoped requests in concert with
|
||||||
|
``system`` scoped requests for a composite Role Based Access Control
|
||||||
|
(RBAC) model. As Ironic is mainly an administrative service,
|
||||||
|
this capability has only been extended to API endpoints which are
|
||||||
|
not purely administrative in nature. This consists of the following
|
||||||
|
API endpoints: nodes, ports, portgroups, volume connectors, volume
|
||||||
|
targets, and allocations.
|
||||||
|
- |
|
||||||
|
Project ``scoped`` requests for baremetal allocations, will automatically
|
||||||
|
record the ``project_id`` of the requestor as the ``owner`` of the node.
|
||||||
|
deprecations:
|
||||||
|
- >
|
||||||
|
Pre-RBAC support rules have been deprecated. These consist of:
|
||||||
|
* admin_api
|
||||||
|
* is_member
|
||||||
|
* is_observer
|
||||||
|
* is_node_owner
|
||||||
|
* is_node_lessee
|
||||||
|
* is_allocation_owner
|
||||||
|
|
||||||
|
These rules will likely be removed in the Xena development cycle.
|
||||||
|
Operators are advised to review any custom policy rules for these
|
||||||
|
rules and move to the `Secure Role Based Access Controls <https://docs.openstack.org/ironic/latest/admin/secure-rbac.html>`_
|
||||||
|
model.
|
||||||
|
issues:
|
||||||
|
- |
|
||||||
|
The addition of both ``project`` and ``system`` scoped Role Based Access
|
||||||
|
controls does add additional database queries when linked resources are
|
||||||
|
accessed. Example, when attempting to access a ``port`` or ``portgroup``,
|
||||||
|
the associated node needs to be checked as this helps govern overall
|
||||||
|
object access to the object for ``project`` scoped requests. This does not
|
||||||
|
impact ``system`` scoped requests. Operators who adopt project scoped
|
||||||
|
access may find it necessary to verify or add additional database indexes
|
||||||
|
in relation to the node ``uuid`` column as well as ``node_id`` field in
|
||||||
|
any table which may recieve heavy project query scope activity.
|
||||||
|
The ``ironic`` project anticipates that this will be a future work item
|
||||||
|
of the project to help improve database performance.
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Legacy policy rules have been deprecated. Operators are advised to review
|
||||||
|
and update any custom policy files in use. Please see
|
||||||
|
`Secure Role Based Access Controls`_ for more information.
|
Reference in New Issue
Block a user