Add documentation and releasenotes for RBAC change

We have droped the system scope from Nova policy
and keeping the legacy admin behaviour same. This
commit adds the releasenotes and update the policy
configuration documentation accordingly.

Also, remove the upgrade check for policy which was
added for the system scope configuration protection.

Change-Id: I127cc4da689a82dbde07059de90c451eb09ea4cf
This commit is contained in:
ghanshyam mann 2022-08-27 22:12:20 +05:30
parent 0bab2e5a88
commit 6903456820
6 changed files with 189 additions and 269 deletions

View File

@ -137,7 +137,7 @@ Upgrade
* Checks for the Placement API are modified to require version 1.35.
* Checks for the policy files are not automatically overwritten with
new defaults.
new defaults. This check has been dropped in 26.0.0 (Zed) release.
**22.0.0 (Victoria)**

View File

@ -65,36 +65,13 @@ represent the layer of authorization required to access an API.
.. note::
The ``scope_type`` of each policy is hardcoded and is not
overridable via the policy file.
The ``scope_type`` of each policy is hardcoded to ``project`` scoped
and is not overridable via the policy file.
Nova policies have implemented the scope concept by defining the ``scope_type``
in policies. To know each policy's ``scope_type``, please refer to the
:doc:`Policy Reference </configuration/policy>` and look for ``Scope Types`` or
``Intended scope(s)`` in :doc:`Policy Sample File </configuration/sample-policy>`
as shown in below examples.
.. rubric:: ``system`` scope
Policies with a ``scope_type`` of ``system`` means a user with a
``system-scoped`` token has permission to access the resource. This can be
seen as a global role. All the system-level operation's policies
have defaulted to ``scope_type`` of ``['system']``.
For example, consider the ``GET /os-hypervisors`` API.
.. code::
# List all hypervisors.
# GET /os-hypervisors
# Intended scope(s): system
#"os_compute_api:os-hypervisors:list": "rule:system_reader_api"
.. rubric:: ``project`` scope
Policies with a ``scope_type`` of ``project`` means a user with a
``project-scoped`` token has permission to access the resource. Project-level
only operation's policies are defaulted to ``scope_type`` of ``['project']``.
for all the policies to ``project`` scoped. It means if user tries to access
nova APIs with ``system`` scoped token they will get 403 permission denied
error.
For example, consider the ``POST /os-server-groups`` API.
@ -105,28 +82,6 @@ For example, consider the ``POST /os-server-groups`` API.
# Intended scope(s): project
#"os_compute_api:os-server-groups:create": "rule:project_member_api"
.. rubric:: ``system and project`` scope
Policies with a ``scope_type`` of ``system and project`` means a user with a
``system-scoped`` or ``project-scoped`` token has permission to access the
resource. All the system and project level operation's policies have defaulted
to ``scope_type`` of ``['system', 'project']``.
For example, consider the ``GET /flavors/{flavor_id}/os-extra_specs/{flavor_extra_spec_key}``
API.
.. code::
# Show an extra spec for a flavor
# GET /flavors/{flavor_id}/os-extra_specs/{flavor_extra_spec_key}
# Intended scope(s): system, project
#"os_compute_api:os-flavor-extra-specs:show": "rule:project_reader_or_admin"
These scope types provide a way to differentiate between system-level and
project-level access roles. You can control the information with scope of the
users. This means you can control that none of the project level role can get
the hypervisor information.
Policy scope is disabled by default to allow operators to migrate from
the old policy enforcement system in a graceful way. This can be
enabled by configuring the :oslo.config:option:`oslo_policy.enforce_scope`
@ -149,52 +104,129 @@ defaults for each policy.
.. rubric:: ``reader``
This provides read-only access to the resources within the ``system`` or
``project``. Nova policies are defaulted to below rules:
This provides read-only access to the resources. Nova policies are defaulted
to below rules:
.. code::
.. code-block:: python
system_reader_api
Default
role:reader and system_scope:all
policy.RuleDefault(
name="project_reader",
check_str="role:reader and project_id:%(project_id)s",
description="Default rule for Project level read only APIs."
)
system_or_project_reader
Default
(rule:system_reader_api) or (role:reader and project_id:%(project_id)s)
Using it in policy rule (with admin + reader access): (because we want to keep legacy admin behavior the same we need to give access of reader APIs to admin role too.)
.. code-block:: python
policy.DocumentedRuleDefault(
name='os_compute_api:servers:show',
check_str='role:admin or (' + 'role:reader and project_id:%(project_id)s)',
description="Show a server",
operations=[
{
'method': 'GET',
'path': '/servers/{server_id}'
}
],
scope_types=['project'],
)
OR
.. code-block:: python
policy.RuleDefault(
name="admin_api",
check_str="role:admin",
description="Default rule for administrative APIs."
)
policy.DocumentedRuleDefault(
name='os_compute_api:servers:show',
check_str='rule: admin or rule:project_reader',
description='Show a server',
operations=[
{
'method': 'GET',
'path': '/servers/{server_id}'
}
],
scope_types=['project'],
)
.. rubric:: ``member``
This role is to perform the project level write operation with combination
to the system admin. Nova policies are defaulted to below rules:
project-member is denoted by someone with the member role on a project. It is
intended to be used by end users who consume resources within a project
which requires higher permission than reader role but less than admin role.
It inherits all the permissions of a project-reader.
.. code::
project-member persona in the policy check string:
project_member_api
Default
role:member and project_id:%(project_id)s
.. code-block:: python
system_admin_or_owner
Default
(role:admin and system_scope:all) or (role:member and project_id:%(project_id)s)
policy.RuleDefault(
name="project_member",
check_str="role:member and project_id:%(project_id)s",
description="Default rule for Project level non admin APIs."
)
Using it in policy rule (with admin + member access): (because we want to keep legacy admin behavior, admin role gets access to the project level member APIs.)
.. code-block:: python
policy.DocumentedRuleDefault(
name='os_compute_api:servers:create',
check_str='role:admin or (' + 'role:member and project_id:%(project_id)s)',
description='Create a server',
operations=[
{
'method': 'POST',
'path': '/servers'
}
],
scope_types=['project'],
)
OR
.. code-block:: python
policy.RuleDefault(
name="admin_api",
check_str="role:admin",
description="Default rule for administrative APIs."
)
policy.DocumentedRuleDefault(
name='os_compute_api:servers:create',
check_str='rule_admin or rule:project_member',
description='Create a server',
operations=[
{
'method': 'POST',
'path': '/servers'
}
],
scope_types=['project'],
)
'project_id:%(project_id)s' in the check_str is important to restrict the
access within the requested project.
.. rubric:: ``admin``
This role is to perform the admin level write operation at system as well
as at project-level operations. Nova policies are defaulted to below rules:
This role is to perform the admin level write operations. Nova policies are
defaulted to below rules:
.. code::
.. code-block:: python
system_admin_api
Default
role:admin and system_scope:all
project_admin_api
Default
role:admin and project_id:%(project_id)s
system_admin_or_owner
Default
(role:admin and system_scope:all) or (role:member and project_id:%(project_id)s)
policy.DocumentedRuleDefault(
name='os_compute_api:os-hypervisors:list',
check_str='role:admin',
scope_types=['project']
)
With these new defaults, you can solve the problem of:
@ -203,8 +235,8 @@ With these new defaults, you can solve the problem of:
your deployment for security purposes.
#. Customize the policy in better way. For example, you will be able
to provide access to project level user to perform live migration for their
server or any other project with their token.
to provide access to project level user to perform operations within
their project only.
Nova supported scope & Roles
-----------------------------
@ -212,40 +244,21 @@ Nova supported scope & Roles
Nova supports the below combination of scopes and roles where roles can be
overridden in the policy.yaml file but scope is not override-able.
#. ADMIN: ``admin`` role on ``system`` scope. This is System Administrator to
perform the system level resource operations. Example: enable/disable compute
services.
#. PROJECT_ADMIN: ``admin`` role on ``project`` scope. This is used to perform
admin level operation within project. For example: Live migrate server.
.. note::
PROJECT_ADMIN has the limitation for the below policies
* ``os_compute_api:servers:create:forced_host``
* ``os_compute_api:servers:compute:servers:create:requested_destination``
To create a server on specific host via force host or requested
destination, you need to pass the hostname in ``POST /servers``
API request but there is no way for PROJECT_ADMIN to get the hostname
via API. This limitation will be addressed in a future release.
#. ADMIN: ``admin`` role on ``project`` scope. This is an administrator to
perform the admin level operations. Example: enable/disable compute
service, Live migrate server etc.
#. PROJECT_MEMBER: ``member`` role on ``project`` scope. This is used to perform
resource owner level operation within project. For example: Pause a server.
#. PROJECT_READER: ``reader`` role on ``project`` scope. This is used to perform
read-only operation within project. For example: Get server.
#. PROJECT_MEMBER_OR_ADMIN: ``admin`` or ``member`` role on ``project`` scope. Such policy rules are default to most of the owner level APIs and aling
with `member` role legacy admin can continue to access those APIs.
#. PROJECT_READER_OR_ADMIN: ``admin`` role on ``system`` scope
or ``reader`` role on ``project`` scope. Such policy rules are scoped
as both ``system`` as well as ``project``. Example: to allow system
admin and project reader to list flavor extra specs.
.. note:: As of now, only ``system`` and ``project`` scopes are supported in Nova.
#. PROJECT_READER_OR_ADMIN: ``admin`` or ``reader`` role on ``project`` scope. Such policy rules are default to most of the read only APIs so that legacy
admin can continue to access those APIs.
Backward Compatibility
----------------------
@ -253,10 +266,10 @@ Backward Compatibility
Backward compatibility with versions prior to 21.0.0 (Ussuri) is maintained by
supporting the old defaults and disabling the ``scope_type`` feature by default.
This means the old defaults and deployments that use them will keep working
as-is. However, we encourage every deployment to switch to new policy.
Scope checks are disabled by default and will be enabled by default starting
Nova 26.0.0 (OpenStack Zed release) and the old defaults will be removed
starting in the Nova 27.0.0 release.
as-is. However, we encourage every deployment to switch to the new policy. The
new defaults will be enabled by default in OpenStack 2023.1 (Nova 27.0.0)
release and old defaults will be removed starting in the OpenStack 2023.2
(Nova 28.0.0) release.
To implement the new default reader roles, some policies needed to become
granular. They have been renamed, with the old names still supported for
@ -275,7 +288,6 @@ Here is step wise guide for migration:
You need to create the new token with scope knowledge via below CLI:
- :keystone-doc:`Create System Scoped Token </admin/tokens-overview.html#operation_create_system_token>`.
- :keystone-doc:`Create Project Scoped Token </admin/tokens-overview.html#operation_create_project_scoped_token>`.
#. Create new default roles in keystone if not done:
@ -295,10 +307,6 @@ Here is step wise guide for migration:
(assuming the rest of the policy passes). The default value of this flag
is False.
.. note:: Before you enable this flag, you need to audit your users and make
sure everyone who needs system-level access has a system role
assignment in keystone.
#. Enable new defaults
The :oslo.config:option:`oslo_policy.enforce_new_defaults` flag switches
@ -311,7 +319,6 @@ Here is step wise guide for migration:
.. note:: Before you enable this flag, you need to educate users about the
different roles they need to use to continue using Nova APIs.
#. Check for deprecated policies
A few policies were made more granular to implement the reader roles. New
@ -319,28 +326,31 @@ Here is step wise guide for migration:
are overwritten in policy file, then warning will be logged. Please migrate
those policies to new policy names.
NOTE::
We recommend to enable the both scope as well new defaults together
otherwise you may experience some late failures with unclear error
messages. For example, if you enable new defaults and disable scope
check then it will allow system users to access the APIs but fail
later due to the project check which can be difficult to debug.
Below table show how legacy rules are mapped to new rules:
+--------------------+----------------------------------+-----------------+-------------------+
| Legacy Rules | New Rules | | |
+====================+==================================+=================+===================+
| | | *Roles* | *Scope* |
| +----------------------------------+-----------------+-------------------+
| | ADMIN | admin | system |
| Project Admin +----------------------------------+-----------------+ |
| Role | PROJECT_ADMIN | admin | project |
| | | | |
+--------------------+----------------------------------+-----------------+-------------------+
| | PROJECT_ADMIN | admin | project |
| +----------------------------------+-----------------+ |
| | PROJECT_MEMBER | member | |
| +----------------------------------+-----------------+ |
| Project admin or | PROJECT_READER | reader | |
| owner role +----------------------------------+-----------------+-------------------+
| | PROJECT_READER_OR_ADMIN | admin on system | system |
| | | or reader on | OR |
| | | project | project |
+--------------------+----------------------------------+-----------------+-------------------+
+--------------------+---------------------------+----------------+-----------+
| Legacy Rule | New Rules |Operation |scope_type |
+====================+===========================+================+===========+
| RULE_ADMIN_API |-> ADMIN |Global resource | [project] |
| | |Write & Read | |
+--------------------+---------------------------+----------------+-----------+
| |-> ADMIN |Project admin | [project] |
| | |level operation | |
| +---------------------------+----------------+-----------+
| RULE_ADMIN_OR_OWNER|-> PROJECT_MEMBER_OR_ADMIN |Project resource| [project] |
| | |Write | |
| +---------------------------+----------------+-----------+
| |-> PROJECT_READER_OR_ADMIN |Project resource| [project] |
| | |Read | |
+--------------------+---------------------------+----------------+-----------+
We expect all deployments to migrate to new policy by 27.0.0 release so that
we can remove the support of old policies.
We expect all deployments to migrate to the new policy by OpenStack 2023.1
(Nova 27.0.0) release so that we can remove the support of old policies.

View File

@ -119,10 +119,6 @@ Verify operation of the Compute service.
| Result: Success |
| Details: None |
+--------------------------------------------------------------------+
| Check: Policy Scope-based Defaults |
| Result: Success |
| Details: None |
+--------------------------------------------------------------------+
| Check: Policy File JSON to YAML Migration |
| Result: Success |
| Details: None |

View File

@ -41,7 +41,6 @@ from nova.objects import cell_mapping as cell_mapping_obj
# to be registered under nova.objects when called via _check_machine_type_set
from nova.objects import image_meta as image_meta_obj # noqa: F401
from nova.objects import instance as instance_obj # noqa: F401
from nova import policy
from nova import utils
from nova import version
from nova.virt.libvirt import machine_type_utils
@ -249,70 +248,6 @@ class UpgradeCommands(upgradecheck.UpgradeCommands):
str(ex))
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
def _check_policy(self):
"""Checks to see if policy file is overwritten with the new
defaults.
"""
msg = _("Your policy file contains rules which examine token scope, "
"which may be due to generation with the new defaults. "
"If that is done intentionally to migrate to the new rule "
"format, then you are required to enable the flag "
"'oslo_policy.enforce_scope=True' and educate end users on "
"how to request scoped tokens from Keystone. Another easy "
"and recommended way for you to achieve the same is via two "
"flags, 'oslo_policy.enforce_scope=True' and "
"'oslo_policy.enforce_new_defaults=True' and avoid "
"overwriting the file. Please refer to this document to "
"know the complete migration steps: "
"https://docs.openstack.org/nova/latest/configuration"
"/policy-concepts.html. If you did not intend to migrate "
"to new defaults in this upgrade, then with your current "
"policy file the scope checking rule will fail. A possible "
"reason for such a policy file is that you generated it with "
"'oslopolicy-sample-generator' in json format. "
"Three ways to fix this until you are ready to migrate to "
"scoped policies: 1. Generate the policy file with "
"'oslopolicy-sample-generator' in yaml format, keep "
"the generated content commented out, and update "
"the generated policy.yaml location in "
"``oslo_policy.policy_file``. "
"2. Use a pre-existing sample config file from the Train "
"release. 3. Use an empty or non-existent file to take all "
"the defaults.")
rule = "context_is_admin"
rule_new_default = "role:admin and system_scope:all"
status = upgradecheck.Result(upgradecheck.Code.SUCCESS)
# NOTE(gmann): Initialise the policy if it not initialized.
# We need policy enforcer with all the rules loaded to check
# their value with defaults.
try:
if policy._ENFORCER is None:
policy.init(suppress_deprecation_warnings=True)
# For safer side, recheck that the enforcer is available before
# upgrade checks. If something is wrong on oslo side and enforcer
# is still not available the return warning to avoid any false
# result.
if policy._ENFORCER is not None:
current_rule = str(policy._ENFORCER.rules[rule]).strip("()")
if (current_rule == rule_new_default and
not CONF.oslo_policy.enforce_scope):
status = upgradecheck.Result(upgradecheck.Code.WARNING,
msg)
else:
status = upgradecheck.Result(
upgradecheck.Code.WARNING,
_('Policy is not initialized to check the policy rules'))
except Exception as ex:
status = upgradecheck.Result(
upgradecheck.Code.WARNING,
_('Unable to perform policy checks due to error: %s') %
str(ex))
# reset the policy state so that it can be initialized from fresh if
# operator changes policy file after running this upgrade checks.
policy.reset()
return status
def _check_old_computes(self):
# warn if there are computes in the system older than the previous
# major release
@ -350,8 +285,6 @@ https://docs.openstack.org/latest/nova/admin/hw_machine_type.html"""))
(_('Placement API'), _check_placement),
# Added in Train
(_('Cinder API'), _check_cinder),
# Added in Ussuri
(_('Policy Scope-based Defaults'), _check_policy),
# Added in Victoria
(
_('Policy File JSON to YAML Migration'),

View File

@ -39,7 +39,6 @@ from nova import exception
# in the tests, we don't use them in the actual CLI.
from nova import objects
from nova.objects import service
from nova import policy
from nova import test
from nova.tests import fixtures as nova_fixtures
@ -393,60 +392,6 @@ class TestUpgradeCheckCinderAPI(test.NoDBTestCase):
self.assertEqual(upgradecheck.Code.SUCCESS, result.code)
class TestUpgradeCheckPolicy(test.NoDBTestCase):
new_default_status = upgradecheck.Code.WARNING
def setUp(self):
super(TestUpgradeCheckPolicy, self).setUp()
self.cmd = status.UpgradeCommands()
self.rule_name = "context_is_admin"
def tearDown(self):
super(TestUpgradeCheckPolicy, self).tearDown()
# Check if policy is reset back after the upgrade check
self.assertIsNone(policy._ENFORCER)
def test_policy_rule_with_new_defaults(self):
new_default = "role:admin and system_scope:all"
rule = {self.rule_name: new_default}
self.policy.set_rules(rule, overwrite=False)
self.assertEqual(self.new_default_status,
self.cmd._check_policy().code)
def test_policy_rule_with_old_defaults(self):
new_default = "is_admin:True"
rule = {self.rule_name: new_default}
self.policy.set_rules(rule, overwrite=False)
self.assertEqual(upgradecheck.Code.SUCCESS,
self.cmd._check_policy().code)
def test_policy_rule_with_both_defaults(self):
new_default = "(role:admin and system_scope:all) or is_admin:True"
rule = {self.rule_name: new_default}
self.policy.set_rules(rule, overwrite=False)
self.assertEqual(upgradecheck.Code.SUCCESS,
self.cmd._check_policy().code)
def test_policy_checks_with_fresh_init_and_no_policy_override(self):
self.policy = self.useFixture(nova_fixtures.OverridePolicyFixture(
rules_in_file={}))
policy.reset()
self.assertEqual(upgradecheck.Code.SUCCESS,
self.cmd._check_policy().code)
class TestUpgradeCheckPolicyEnableScope(TestUpgradeCheckPolicy):
new_default_status = upgradecheck.Code.SUCCESS
def setUp(self):
super(TestUpgradeCheckPolicyEnableScope, self).setUp()
self.flags(enforce_scope=True, group="oslo_policy")
class TestUpgradeCheckOldCompute(test.NoDBTestCase):
def setUp(self):

View File

@ -0,0 +1,36 @@
---
features:
- |
The Nova policies have been modified to drop the system scope. Every
API policy is scoped to project. This means that system scoped users
will get 403 permission denied error.
Also, the project reader role is ready to use. Users with reader role
can only perform the read-only operations within their project. This
role can be used for the audit purposes.
Currently, nova supports the following roles:
* ``admin`` (Legacy admin)
* ``project member``
* ``project reader``
For the details on what changed from the existing policy, please refer
to the `RBAC new guidelines`_. We have implemented only phase-1 of the
`RBAC new guidelines`_.
Currently, scope checks and new defaults are disabled by default. You can
enable them by switching the below config option in ``nova.conf`` file::
[oslo_policy]
enforce_new_defaults=True
enforce_scope=True
We recommend to enable the both scope as well new defaults together
otherwise you may experience some late failures with unclear error
messages.
Please refer `Policy New Defaults`_ for detail about policy new defaults
and migration plan.
.. _`RBAC new guidelines`: https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#phase-1
.. _`Policy New Defaults`: https://docs.openstack.org/nova/latest/configuration/policy-concepts.html