
RBAC community wide goal phase-2[1] is to add 'service' role for the service APIs policy rule. This commit defaults the service APIs to 'service' role. This way service APIs will be allowed for service user only. Tempest tests also modified to simulate the service-to-service communication. Tempest tests send the user with service role to nova API. - https://review.opendev.org/c/openstack/tempest/+/892639> Partial implement blueprint policy-service-role-default [1] https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#phase-2 Change-Id: I1565ea163fa2c8212f71c9ba375654d2aab28330 Signed-off-by: Ghanshyam Maan <gmaan@ghanshyammann.com>
438 lines
16 KiB
ReStructuredText
438 lines
16 KiB
ReStructuredText
Understanding Nova Policies
|
||
===========================
|
||
|
||
.. warning::
|
||
|
||
JSON formatted policy file is deprecated since Nova 22.0.0(Victoria).
|
||
Use YAML formatted file. Use `oslopolicy-convert-json-to-yaml`__ tool
|
||
to convert the existing JSON to YAML formatted policy file in backward
|
||
compatible way.
|
||
|
||
.. __: https://docs.openstack.org/oslo.policy/latest/cli/oslopolicy-convert-json-to-yaml.html
|
||
|
||
Nova supports a rich policy system that has evolved significantly over its
|
||
lifetime. Initially, this took the form of a large, mostly hand-written
|
||
``policy.yaml`` file but, starting in the Newton (14.0.0) release, policy
|
||
defaults have been defined in the codebase, requiring the ``policy.yaml``
|
||
file only to override these defaults.
|
||
|
||
In the Ussuri (21.0.0) release, further work was undertaken to address some
|
||
issues that had been identified:
|
||
|
||
#. No global vs project admin. The ``admin_only`` role is used for the global
|
||
admin that is able to make almost any change to Nova, and see all details
|
||
of the Nova system. The rule passes for any user with an admin role, it
|
||
doesn’t matter which project is used.
|
||
|
||
#. No read-only roles. Since several APIs tend to share a single policy rule
|
||
for read and write actions, they did not provide the granularity necessary
|
||
for read-only access roles.
|
||
|
||
#. The ``admin_or_owner`` role did not work as expected. For most APIs with
|
||
``admin_or_owner``, the project authentication happened in a separate
|
||
component than API in Nova that did not honor changes to policy. As a
|
||
result, policy could not override hard-coded in-project checks.
|
||
|
||
Keystone comes with ``admin``, ``manager``, ``member`` and ``reader`` roles
|
||
by default. Please refer to :keystone-doc:`this document </admin/service-api-protection.html>`
|
||
for more information about these new defaults. In addition, keystone supports
|
||
a new "system scope" concept that makes it easier to protect deployment level
|
||
resources from project or system level resources. Please refer to
|
||
:keystone-doc:`this document </admin/tokens-overview.html#authorization-scopes>`
|
||
and `system scope specification <https://specs.openstack.org/openstack/keystone-specs/specs/keystone/queens/system-scope.html>`_ to understand the scope concept.
|
||
|
||
In the Nova 25.0.0 (Yoga) release, Nova policies implemented
|
||
the scope concept and default roles provided by keystone (admin, member,
|
||
and reader). Using common roles from keystone reduces the likelihood of
|
||
similar, but different, roles implemented across projects or deployments
|
||
(e.g., a role called ``observer`` versus ``reader`` versus ``auditor``).
|
||
With the help of the new defaults it is easier to understand who can do
|
||
what across projects, reduces divergence, and increases interoperability.
|
||
|
||
The below sections explain how these new defaults in the Nova can solve the
|
||
first two issues mentioned above and extend more functionality to end users
|
||
in a safe and secure way.
|
||
|
||
More information is provided in the `nova specification <https://specs.openstack.org/openstack/nova-specs/specs/ussuri/approved/policy-defaults-refresh.html>`_.
|
||
|
||
Scope
|
||
-----
|
||
|
||
OpenStack Keystone supports different scopes in tokens.
|
||
These are described :keystone-doc:`here </admin/tokens-overview.html#authorization-scopes>`.
|
||
Token scopes represent the layer of authorization. Policy ``scope_types``
|
||
represent the layer of authorization required to access an API.
|
||
|
||
.. note::
|
||
|
||
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``
|
||
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.
|
||
|
||
.. code::
|
||
|
||
# Create a new server group
|
||
# POST /os-server-groups
|
||
# Intended scope(s): project
|
||
#"os_compute_api:os-server-groups:create": "rule:project_member_api"
|
||
|
||
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`
|
||
option to ``True``.
|
||
|
||
.. note::
|
||
|
||
[oslo_policy]
|
||
enforce_scope=True
|
||
|
||
|
||
Roles
|
||
-----
|
||
|
||
You can refer to :keystone-doc:`this </admin/service-api-protection.html>`
|
||
document to know about all available defaults from Keystone.
|
||
|
||
Along with the ``scope_type`` feature, Nova policy defines new
|
||
defaults for each policy.
|
||
|
||
.. rubric:: ``reader``
|
||
|
||
This provides read-only access to the resources. Nova policies are defaulted
|
||
to below rules:
|
||
|
||
.. code-block:: python
|
||
|
||
policy.RuleDefault(
|
||
name="project_reader",
|
||
check_str="role:reader and project_id:%(project_id)s",
|
||
description="Default rule for Project level read only APIs."
|
||
)
|
||
|
||
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``
|
||
|
||
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.
|
||
|
||
project-member persona in the policy check string:
|
||
|
||
.. code-block:: python
|
||
|
||
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:: ``manager``
|
||
|
||
``project_manager`` is denoted by someone with the manager role on a project.
|
||
It is intended to be used in project-level management APIs and perform more
|
||
privileged operations on its project resources than ``project_member``. It
|
||
inherits all the permissions of a ``project_member`` and ``project_reader``.
|
||
For example, a ``project_manager`` can migrate (cold or live) their servers
|
||
without specifying the host. Further, a ``project_manager`` will be able
|
||
to list migrations related to their own project.
|
||
|
||
``project_manager`` persona in Nova policy rule (it is defined as
|
||
``project_manager_api`` in policy yaml) looks like:
|
||
|
||
'project_id:%(project_id)s' in the check_str is important to restrict the
|
||
access within the requested project.
|
||
|
||
.. code-block:: yaml
|
||
|
||
# Default rule for Project level management APIs.
|
||
"project_manager_api": "role:manager and project_id:%(project_id)s"
|
||
|
||
To keep the legacy ``admin`` behavior unchanged, Nova allow ``admin``
|
||
also to access the project level management APIs:
|
||
|
||
.. code-block:: yaml
|
||
|
||
# Default rule for Project level management APIs.
|
||
"project_manager_or_admin": "rule:project_manager_api or rule:context_is_admin"
|
||
|
||
The above base rule are used for specific API access:
|
||
|
||
.. code-block:: yaml
|
||
|
||
# Cold migrate a server without specifying a host
|
||
# POST /servers/{server_id}/action (migrate)
|
||
# Intended scope(s): project
|
||
"os_compute_api:os-migrate-server:migrate": "rule:project_manager_or_admin"
|
||
|
||
.. rubric:: ``admin``
|
||
|
||
This role is to perform the admin level write operations. Nova policies are
|
||
defaulted to below rules:
|
||
|
||
.. code-block:: python
|
||
|
||
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:
|
||
|
||
#. Providing the read-only access to the user. Polices are made more granular
|
||
and defaulted to reader rules. For example: If you need to let someone audit
|
||
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 operations within
|
||
their project only.
|
||
|
||
.. rubric:: ``service``
|
||
|
||
The ``service`` role is a special role in Keystone, which is used for the
|
||
internal service-to-service communication. It is assigned to service users
|
||
i.e. nova or neutron which model the OpenStack services. Nova defaults its
|
||
service-to-service APIs to require the ``service`` role so that they cannot
|
||
be used by any non-service users. Allowing access to service-to-service APIs
|
||
to non-service users can be destructive to resources and leave the deployment
|
||
in an invalid state. It's advisable to audit the ``policy.yaml`` files and
|
||
keystone users to make sure those APIs are not allowed to any non-service
|
||
users and the service role is not granted to human admin accounts.
|
||
|
||
.. note::
|
||
|
||
Make sure the configured nova service user in other services has the
|
||
``service`` role otherwise communication from the other services to
|
||
Nova will fail. For example, user configured as ``username`` option in
|
||
``neutron.conf`` file under ``[nova]`` section has the ``service`` role.
|
||
|
||
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 ``project`` scope. This is an administrator to
|
||
perform the admin level operations. Example: enable/disable compute
|
||
service, Live migrate server etc.
|
||
|
||
#. PROJECT_MANAGER: ``manager`` role on ``project`` scope. This is used to
|
||
perform project management operations within project. For example: migrate
|
||
a server.
|
||
|
||
#. 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_MANAGER_OR_ADMIN: ``admin`` or ``manager`` role on ``project`` scope.
|
||
Such policy rules are default to project management level APIs and along
|
||
with ``manager`` role, legacy admin can continue to access those APIs.
|
||
|
||
#. PROJECT_MEMBER_OR_ADMIN: ``admin`` or ``member`` role on ``project`` scope.
|
||
Such policy rules are default to most of the owner level APIs and align
|
||
with ``member`` role legacy admin can continue to access those APIs.
|
||
|
||
#. 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.
|
||
|
||
#. SERVICE_ROLE (Internal): ``service`` role on service users with ``project``
|
||
scope. Such policy rules are default to the service-to-service APIs (The
|
||
APIs only meant to be called by the OpenStack services).
|
||
|
||
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 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
|
||
backwards compatibility.
|
||
|
||
Migration Plan
|
||
--------------
|
||
|
||
To have a graceful migration, Nova provides two flags to switch to the new
|
||
policy completely. You do not need to overwrite the policy file to adopt the
|
||
new policy defaults.
|
||
|
||
Here is step wise guide for migration:
|
||
|
||
#. Create scoped token:
|
||
|
||
You need to create the new token with scope knowledge via below CLI:
|
||
|
||
- :keystone-doc:`Create Project Scoped Token </admin/tokens-overview.html#operation_create_project_scoped_token>`.
|
||
|
||
#. Create new default roles in keystone if not done:
|
||
|
||
If you do not have new defaults in Keystone then you can create and re-run
|
||
the :keystone-doc:`Keystone Bootstrap </admin/bootstrap.html>`. Keystone
|
||
added this support in 14.0.0 (Rocky) release.
|
||
|
||
#. Enable Scope Checks
|
||
|
||
The :oslo.config:option:`oslo_policy.enforce_scope` flag is to enable the
|
||
``scope_type`` features. The scope of the token used in the request is
|
||
always compared to the ``scope_type`` of the policy. If the scopes do not
|
||
match, one of two things can happen. If :oslo.config:option:`oslo_policy.enforce_scope`
|
||
is True, the request will be rejected. If :oslo.config:option:`oslo_policy.enforce_scope`
|
||
is False, an warning will be logged, but the request will be accepted
|
||
(assuming the rest of the policy passes). The default value of this flag
|
||
is False.
|
||
|
||
#. Enable new defaults
|
||
|
||
The :oslo.config:option:`oslo_policy.enforce_new_defaults` flag switches
|
||
the policy to new defaults-only. This flag controls whether or not to use
|
||
old deprecated defaults when evaluating policies. If True, the old
|
||
deprecated defaults are not evaluated. This means if any existing
|
||
token is allowed for old defaults but is disallowed for new defaults,
|
||
it will be rejected. The default value of this flag is False.
|
||
|
||
.. 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
|
||
policy names are available to use. If old policy names which are renamed
|
||
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:
|
||
|
||
.. list-table::
|
||
:widths: 25 45 15 15
|
||
:header-rows: 1
|
||
|
||
* - Legacy Rule
|
||
- New Rule
|
||
- Operation
|
||
- Scope
|
||
* - RULE_ADMIN_API
|
||
- ADMIN
|
||
- Global resource Write & Read
|
||
- project
|
||
* - RULE_ADMIN_API
|
||
- PROJECT_MANAGER_OR_ADMIN
|
||
- Project management level
|
||
- project
|
||
* - RULE_ADMIN_OR_OWNER
|
||
- PROJECT_MEMBER_OR_ADMIN
|
||
- Project resource write
|
||
- project
|
||
* - RULE_ADMIN_OR_OWNER
|
||
- PROJECT_READER_OR_ADMIN
|
||
- Project resource read
|
||
- project
|
||
|
||
We expect all deployments to migrate to the new policy by OpenStack 2023.1
|
||
(Nova 27.0.0) release (``project_manager`` role is available from Nova 32.0.0)
|
||
so that we can remove the support of old policies.
|