Add new default roles in Device Profile API policies

This adds new default roles in device_profile API policies.

- GET is default with system or project reader role
- Rest all APIs are system admin role

Test cases have been added to cover new defaults as well as
for deprecated rules.

- Backward compatibility:
    Old Rules and Defaults will keep working as it is because they
    are added as deprecated rules and marked for removal in future
    release. This means Existing deployement will keep working till
    deprecated rules are there.

- Below warning can be seen by operator to migrate the old policies
  to new one:

/cyborg/.tox/py36/lib/python3.6/site-packages/oslo_policy/policy.py:731:
UserWarning: Policy "cyborg:device_profile:get_all":"rule:admin_or_owner"
was deprecated in W in favor of
"cyborg:device_profile:get_all":"rule:system_or_project_reader".
Reason: request admin_or_owmer rule is too strict for listing device_profile.
Either ensure your deployment is ready for the new default or copy/paste the
deprecated policy into your policy file and maintain it manually.

Add new default rules and mapping in policy base class

Cyborg Policy Default Refresh is one of the planned blueprints for victoria
release, the specification[0] has been merged in ussuri. To be brief, we need
to do the followings to incorporate authorization scopes into cyborg:
1. Add protection test for all APIs.
   A protection test is similar to an API test, but purely focused on the
   authoritative outcome.In other words, protection testing is sufficient when
   we can assert that a user is or isn't allowed to do or see something. For
   example, Users with a reader role on the system or a project shouldn’t be
   able to make writable changes.
2. Add the following applicable personas to cyborg and deprecate old ones:
   * project reader
   * project member
   * project admin
   * system reader
   * system admin
   * system admin or owner
   * system or project reader
3. Rewrite check string(authorization rules) using new personas for all APIs
4. Update policy documentation on cyborg-doc page

This patch refreshed cyborg default RBAC policy to scoped RBAC policy, and
reorganized the policy framework into a more logical way:
    1) added five personas to basic policies and deprecated legacy roles
    2) extract API_policies from policy.py to indenpendent policy files
    3) extract authorize_wsgi.py out from policy.py

[0]https://specs.openstack.org/openstack/cyborg-specs/specs/ussuri/approved/policy-defaults-refresh.html

Story: 2007024
Task: 40834

Change-Id: I3d1620ed66221873fbe5ea5a3b703395664072e2
This commit is contained in:
Yumeng Bao 2020-09-08 11:29:38 +08:00
parent 1e46f9be32
commit b1c223afd8
3 changed files with 109 additions and 16 deletions

View File

@ -41,21 +41,6 @@ accelerator_request_policies = [
description='Update accelerator request records.'),
]
device_profile_policies = [
policy.RuleDefault('cyborg:device_profile:get_all',
'rule:default',
description='Retrieve device_profile records.'),
policy.RuleDefault('cyborg:device_profile:get_one',
'rule:default',
description='Get a device_profile record.'),
policy.RuleDefault('cyborg:device_profile:create',
'rule:is_admin',
description='Create device_profile records.'),
policy.RuleDefault('cyborg:device_profile:delete',
'rule:default',
description='Delete device_profile records.'),
]
device_policies = [
policy.RuleDefault('cyborg:device:get_one',
'rule:allow',

View File

@ -18,14 +18,15 @@ import itertools
from cyborg.common import policy as old_policy
from cyborg.policies import base
from cyborg.policies import device_profiles
def list_policies():
return itertools.chain(
base.list_policies(),
device_profiles.list_policies(),
# NOTE(yumeng)old_policies will also be loaded before they are replaced
# by new policies
old_policy.device_profile_policies,
old_policy.device_policies,
old_policy.deployable_policies,
old_policy.accelerator_request_policies,

View File

@ -0,0 +1,107 @@
# Copyright 2020 ZTE Corporation.
# All Rights Reserved.
#
# 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 oslo_log import versionutils
from oslo_policy import policy
from cyborg.policies import base
# NOTE(yumeng)During the Policy-default-refresh work, the old device_profile
# policies will be marked as deprecated device_profile policies.
# To ensure API works fine with both old policies and new policies, we set
# ``cyborg.conf [oslo_policy] enforce_scope = False`` by default. With this,
# policy authorization check will pass those who comply with either new policy
# rules or old policy rules by invoking oslo_policy.policy.OrCheck
# (REF:https://github.com/openstack/oslo.policy/blob/cab28649c689067970a51a2f9b329bdd6a0f0501/oslo_policy/policy.py#L726)
# And once we move to new defaults only world, we will set
# ``cyborg.conf [oslo_policy] enforce_scope = True`` by default, at which time
# we can totally remove these deprecated device_profile policies from code.
deprecated_get_all = policy.DeprecatedRule(
name='cyborg:device_profile:get_all',
check_str=base.deprecated_default)
deprecated_get_one = policy.DeprecatedRule(
name='cyborg:device_profile:get_one',
check_str=base.deprecated_default)
deprecated_create = policy.DeprecatedRule(
name='cyborg:device_profile:create',
check_str=base.deprecated_is_admin)
deprecated_delete = policy.DeprecatedRule(
name='cyborg:device_profile:delete',
check_str=base.deprecated_default)
# new device_profile policies
device_profile_policies = [
policy.DocumentedRuleDefault(
name='cyborg:device_profile:get_all',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
description='Retrieve all device_profiles',
operations=[
{
'path': '/v2/device_profiles',
'method': 'GET'
}],
deprecated_rule=deprecated_get_all,
deprecated_reason=('request admin_or_owmer rule is too strict for '
'listing device_profile'),
deprecated_since=versionutils.deprecated.WALLABY),
policy.DocumentedRuleDefault(
name='cyborg:device_profile:get_one',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
description='Retrieve a specific device_profile',
operations=[
{
'path': '/v2/device_profiles/{device_profiles_uuid}',
'method': 'GET'
}],
deprecated_rule=deprecated_get_one,
deprecated_reason=('request admin_or_owmer rule is too strict for '
'retrieving a device_profile'),
deprecated_since=versionutils.deprecated.WALLABY),
policy.DocumentedRuleDefault(
name='cyborg:device_profile:create',
check_str=base.SYSTEM_ADMIN,
description='Create a device_profile',
operations=[
{
'path': '/v2/device_profiles',
'method': 'POST'
}],
deprecated_rule=deprecated_create,
deprecated_reason=('project_admin_or_owner is too permissive, '
'introduce system_scoped admin for creation'),
deprecated_since=versionutils.deprecated.WALLABY),
policy.DocumentedRuleDefault(
name='cyborg:device_profile:delete',
check_str=base.SYSTEM_ADMIN,
description='Delete device_profile(s)',
operations=[
{
'path': '/v2/device_profiles/{device_profiles_uuid}',
'method': 'DELETE'},
{
'path': '/v2/device_profiles?value={device_profile_name1}',
'method': 'DELETE'},
],
deprecated_rule=deprecated_delete,
deprecated_reason=('project_admin_or_owner is too permissive, '
'introduce system_scoped admin for deletion'),
deprecated_since=versionutils.deprecated.WALLABY),
]
def list_policies():
return device_profile_policies