Implement access control for DC API
This commit implements access control for DC API. The reference doc can be found at "https://docs.starlingx.io/api-ref/distcloud/api-ref-dcmanager-v1.html". Unit tests and YAML file support will be done in other tasks. The access control implementation for GET requests requires the user to have "reader" role and to be present in either "admin" or "services" project. For other requests, it requires the user to have "admin" role and to be present in either "admin" or "services" project. Requests using public API URLs require no credentials. As all default system users of StarlingX have "admin" role and are present in either project "admin" or "services", there should be no regression with the change introduced here. The implementation done here is a little bit different from the one done for sysinv and FM APIs, because the routing of requests is not done when "before()" method of Pecan hooks are called, so the controller is not defined at this point. To test the access control of DC API, the following commands are used (long list of parameters is replaced by "<params>"): dcmanager subcloud add <params> dcmanager subcloud manage subcloud2 dcmanager subcloud list dcmanager subcloud delete subcloud2 dcmanager subcloud-deploy upload <params> dcmanager subcloud-deploy show dcmanager alarm summary dcmanager patch-strategy create dcmanager patch-strategy show dcmanager patch-strategy apply dcmanager patch-strategy abort dcmanager patch-strategy delete dcmanager strategy-config update <params> subcloud1 dcmanager strategy-config list dcmanager strategy-config delete subcloud1 dcmanager subcloud-group add --name group01 dcmanager subcloud-group update --description test group01 dcmanager subcloud-group list dcmanager subcloud-group delete group01 dcmanager subcloud-backup create --subcloud subcloud1 On test plan, these commands are reffered as "test commands". The access control is not implemented for "dcdbsync" and "dcorch" servers. Also, it is also not implemented for action POST "/v1.0/notifications" in dcmanager API server, as it it is only called indirectly by sysinv controllers. Test Plan: PASS: Successfully deploy a Distributed Cloud (with 1 subcloud) using a CentOS image with this commit present. Successfully create, through openstack CLI, the users: 'testreader' with role 'reader' in project 'admin', 'adminsvc' with role 'admin' in project 'services' and 'otheradmin' with role 'admin' in project 'notadminproject'. Create openrc files for all new users. Note: the other user used is the already existing 'admin' with role 'admin' in project 'admin'. PASS: In the deployed DC, check the behavior of test commands through different users: for "admin" and "adminsvc" users, all commands are successful; for "testreader" user, only the test commands ending with "list" or "summary" (GET requests) are successful; for "otheradmin" user, all commands fail. PASS: In the deployed DC, to assert that public API works without authentication, execute the command "curl -v http://<MGMT_IP>:8119/" and verify that it is accepted and that the HTTP response is 200, and execute the command "curl -v http://<MGMT_IP>:8119/v1.0/subclouds" and verify that it is rejected and that the HTTP response is 401. PASS: In the deployed DC, check through Horizon interface that DC management works correctly with default admin user. Story: 2010149 Task: 46287 Signed-off-by: Joao Victor Portal <Joao.VictorPortal@windriver.com> Change-Id: Icfe24fd62096c7bf0bbb1f97e819dee5aac675e4
This commit is contained in:
parent
be55504cf3
commit
28a4b568b1
|
@ -1,76 +0,0 @@
|
|||
# Copyright 2017 Ericsson AB.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
"""Policy enforcer for DC DBsync Agent."""
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
|
||||
from dcdbsync.common import exceptions as exc
|
||||
|
||||
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def enforce(action, context, target=None, do_raise=True,
|
||||
exc=exc.NotAuthorized):
|
||||
"""Verify that the action is valid on the target in this context.
|
||||
|
||||
:param action: String, representing the action to be checked.
|
||||
This should be colon separated for clarity.
|
||||
i.e. ``sync:list``
|
||||
:param context: DC DBsync context.
|
||||
:param target: Dictionary, representing the object of the action.
|
||||
For object creation, this should be a dictionary
|
||||
representing the location of the object.
|
||||
e.g. ``{'project_id': context.project}``
|
||||
:param do_raise: if True (the default), raises specified exception.
|
||||
:param exc: Exception to be raised if not authorized. Default is
|
||||
dcdbsync.common.exceptions.NotAuthorized.
|
||||
|
||||
:return: returns True if authorized and False if not authorized and
|
||||
do_raise is False.
|
||||
"""
|
||||
if cfg.CONF.auth_strategy != 'keystone':
|
||||
# Policy enforcement is supported now only with Keystone
|
||||
# authentication.
|
||||
return
|
||||
|
||||
target_obj = {
|
||||
'project_id': context.project,
|
||||
'user_id': context.user,
|
||||
}
|
||||
|
||||
target_obj.update(target or {})
|
||||
_ensure_enforcer_initialization()
|
||||
|
||||
try:
|
||||
_ENFORCER.enforce(action, target_obj, context.to_dict(),
|
||||
do_raise=do_raise, exc=exc)
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _ensure_enforcer_initialization():
|
||||
global _ENFORCER
|
||||
if not _ENFORCER:
|
||||
_ENFORCER = policy.Enforcer(cfg.CONF)
|
||||
_ENFORCER.load_rules()
|
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import itertools
|
||||
|
||||
from dcdbsync.api.policies import base
|
||||
|
||||
|
||||
def list_rules():
|
||||
return itertools.chain(
|
||||
base.list_rules()
|
||||
)
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from oslo_policy import policy
|
||||
|
||||
ADMIN_IN_SYSTEM_PROJECTS = 'admin_in_system_projects'
|
||||
READER_IN_SYSTEM_PROJECTS = 'reader_in_system_projects'
|
||||
|
||||
|
||||
base_rules = [
|
||||
policy.RuleDefault(
|
||||
name=ADMIN_IN_SYSTEM_PROJECTS,
|
||||
check_str='role:admin and (project_name:admin or ' +
|
||||
'project_name:services)',
|
||||
description="Base rule.",
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name=READER_IN_SYSTEM_PROJECTS,
|
||||
check_str='role:reader and (project_name:admin or ' +
|
||||
'project_name:services)',
|
||||
description="Base rule."
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return base_rules
|
|
@ -0,0 +1,62 @@
|
|||
# Copyright (c) 2011 OpenStack Foundation
|
||||
# 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.
|
||||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
"""Policy Engine For DC."""
|
||||
|
||||
from dcdbsync.api import policies as controller_policies
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
from webob import exc
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def reset():
|
||||
"""Discard current Enforcer object."""
|
||||
global _ENFORCER
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def init(policy_file='policy.yaml'):
|
||||
"""Init an Enforcer class.
|
||||
|
||||
:param policy_file: Custom policy file to be used.
|
||||
|
||||
:return: Returns a Enforcer instance.
|
||||
"""
|
||||
global _ENFORCER
|
||||
if not _ENFORCER:
|
||||
|
||||
# https://docs.openstack.org/oslo.policy/latest/user/usage.html
|
||||
_ENFORCER = policy.Enforcer(CONF,
|
||||
policy_file=policy_file,
|
||||
default_rule='default',
|
||||
use_conf=True,
|
||||
overwrite=True)
|
||||
_ENFORCER.register_defaults(controller_policies.list_rules())
|
||||
return _ENFORCER
|
||||
|
||||
|
||||
def authorize(rule, target, creds, do_raise=True):
|
||||
"""A wrapper around 'authorize' from 'oslo_policy.policy'."""
|
||||
init()
|
||||
return _ENFORCER.authorize(rule, target, creds, do_raise=do_raise,
|
||||
exc=exc.HTTPForbidden)
|
|
@ -10,7 +10,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copyright (c) 2019, 2022 Wind River Systems, Inc.
|
||||
# Copyright (c) 2019-2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
@ -21,7 +21,8 @@ from pecan import hooks
|
|||
from oslo_context import context as base_context
|
||||
from oslo_utils import encodeutils
|
||||
|
||||
from dcdbsync.common import policy
|
||||
from dcdbsync.api.policies import base as base_policy
|
||||
from dcdbsync.api import policy
|
||||
from dcdbsync.db.identity import api as db_api
|
||||
|
||||
ALLOWED_WITHOUT_AUTH = '/'
|
||||
|
@ -78,9 +79,9 @@ class RequestContext(base_context.RequestContext):
|
|||
|
||||
# Check user is admin or not
|
||||
if is_admin is None:
|
||||
self.is_admin = policy.enforce(self, 'context_is_admin',
|
||||
target={'project': self.project},
|
||||
do_raise=False)
|
||||
self.is_admin = policy.authorize(
|
||||
base_policy.ADMIN_IN_SYSTEM_PROJECTS, {}, self.to_dict(),
|
||||
do_raise=False)
|
||||
else:
|
||||
self.is_admin = is_admin
|
||||
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
# 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.
|
||||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
"""
|
||||
Policy Engine For DC DBsync Agent
|
||||
"""
|
||||
|
||||
# from oslo_concurrency import lockutils
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
|
||||
from dcdbsync.common import exceptions
|
||||
|
||||
POLICY_ENFORCER = None
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
# @lockutils.synchronized('policy_enforcer', 'dcdbsync-')
|
||||
def _get_enforcer(policy_file=None, rules=None, default_rule=None):
|
||||
|
||||
global POLICY_ENFORCER
|
||||
|
||||
if POLICY_ENFORCER is None:
|
||||
POLICY_ENFORCER = policy.Enforcer(CONF,
|
||||
policy_file=policy_file,
|
||||
rules=rules,
|
||||
default_rule=default_rule)
|
||||
return POLICY_ENFORCER
|
||||
|
||||
|
||||
def enforce(context, rule, target, do_raise=True, *args, **kwargs):
|
||||
|
||||
enforcer = _get_enforcer()
|
||||
credentials = context.to_dict()
|
||||
target = target or {}
|
||||
if do_raise:
|
||||
kwargs.update(exc=exceptions.Forbidden)
|
||||
|
||||
return enforcer.enforce(rule, target, credentials, do_raise,
|
||||
*args, **kwargs)
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright 2015 Huawei Technologies Co., Ltd.
|
||||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -27,9 +27,6 @@ from oslo_config import cfg
|
|||
from oslo_log import log as logging
|
||||
|
||||
from dcmanager.common.i18n import _
|
||||
|
||||
|
||||
# from dcmanager import policy
|
||||
from dcmanager.common import version
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -98,7 +95,10 @@ def reset_service():
|
|||
def test_init():
|
||||
# Register the configuration options
|
||||
cfg.CONF.register_opts(common_opts)
|
||||
logging.register_options(cfg.CONF)
|
||||
try:
|
||||
logging.register_options(cfg.CONF)
|
||||
except cfg.ArgsAlreadyParsedError:
|
||||
pass
|
||||
setup_logging()
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2015 Huawei Tech. Co., Ltd.
|
||||
# Copyright (c) 2017, 2019, 2021, 2022 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -41,3 +41,13 @@ def extract_context_from_environ():
|
|||
|
||||
context_paras['is_admin'] = 'admin' in role.split(',')
|
||||
return k_context.RequestContext(**context_paras)
|
||||
|
||||
|
||||
def extract_credentials_for_policy():
|
||||
context_paras = {'project_name': 'HTTP_X_PROJECT_NAME',
|
||||
'roles': 'HTTP_X_ROLE'}
|
||||
environ = request.environ
|
||||
for key, val in context_paras.items():
|
||||
context_paras[key] = environ.get(val)
|
||||
context_paras['roles'] = context_paras['roles'].split(',')
|
||||
return context_paras
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Ericsson AB.
|
||||
# Copyright (c) 2017-2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -16,6 +16,8 @@
|
|||
#
|
||||
|
||||
from dcmanager.api.controllers import restcomm
|
||||
from dcmanager.api.policies import alarm_manager as alarm_manager_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.common import consts
|
||||
from dcmanager.db import api as db_api
|
||||
|
||||
|
@ -63,6 +65,8 @@ class SubcloudAlarmController(object):
|
|||
"""Get List of alarm summarys
|
||||
|
||||
"""
|
||||
policy.authorize(alarm_manager_policy.POLICY_ROOT % "get", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
return self._get_alarm_aggregates()
|
||||
|
||||
def _get_alarm_summary(self):
|
||||
|
@ -79,4 +83,6 @@ class SubcloudAlarmController(object):
|
|||
"""Get an agregate of all subcloud status
|
||||
|
||||
"""
|
||||
policy.authorize(alarm_manager_policy.POLICY_ROOT % "get", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
return self._get_alarm_summary()
|
||||
|
|
|
@ -22,6 +22,8 @@ from yaml.scanner import ScannerError
|
|||
from dccommon import consts as dccommon_consts
|
||||
|
||||
from dcmanager.api.controllers import restcomm
|
||||
from dcmanager.api.policies import subcloud_backup as subcloud_backup_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.common import consts
|
||||
from dcmanager.common.i18n import _
|
||||
from dcmanager.common import utils
|
||||
|
@ -213,6 +215,9 @@ class SubcloudBackupController(object):
|
|||
def post(self):
|
||||
"""Create a new subcloud backup."""
|
||||
|
||||
policy.authorize(subcloud_backup_policy.POLICY_ROOT % "create", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
payload = self._get_backup_payload(request)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copyright (c) 2020, 2022 Wind River Systems, Inc.
|
||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
@ -27,6 +27,9 @@ import pecan
|
|||
from pecan import expose
|
||||
from pecan import request
|
||||
|
||||
from dcmanager.api.controllers import restcomm
|
||||
from dcmanager.api.policies import subcloud_deploy as subcloud_deploy_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.common import consts
|
||||
from dcmanager.common.i18n import _
|
||||
from dcmanager.common import utils
|
||||
|
@ -78,6 +81,8 @@ class SubcloudDeployController(object):
|
|||
@utils.synchronized(LOCK_NAME)
|
||||
@index.when(method='POST', template='json')
|
||||
def post(self):
|
||||
policy.authorize(subcloud_deploy_policy.POLICY_ROOT % "upload", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
deploy_dicts = dict()
|
||||
missing_options = set()
|
||||
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||
|
@ -126,6 +131,8 @@ class SubcloudDeployController(object):
|
|||
def get(self):
|
||||
"""Get the subcloud deploy files that has been uploaded and stored"""
|
||||
|
||||
policy.authorize(subcloud_deploy_policy.POLICY_ROOT % "get", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
deploy_dicts = dict()
|
||||
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||
dir_path = tsc.DEPLOY_PATH
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Ericsson AB.
|
||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -26,6 +26,8 @@ from pecan import expose
|
|||
from pecan import request
|
||||
|
||||
from dcmanager.api.controllers import restcomm
|
||||
from dcmanager.api.policies import subcloud_group as subcloud_group_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.common import consts
|
||||
from dcmanager.common.i18n import _
|
||||
from dcmanager.common import utils
|
||||
|
@ -80,6 +82,8 @@ class SubcloudGroupsController(object):
|
|||
|
||||
:param group_ref: ID or name of subcloud group
|
||||
"""
|
||||
policy.authorize(subcloud_group_policy.POLICY_ROOT % "get", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
if group_ref is None:
|
||||
|
@ -144,6 +148,8 @@ class SubcloudGroupsController(object):
|
|||
@index.when(method='POST', template='json')
|
||||
def post(self):
|
||||
"""Create a new subcloud group."""
|
||||
policy.authorize(subcloud_group_policy.POLICY_ROOT % "create", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
payload = eval(request.body)
|
||||
|
@ -192,6 +198,8 @@ class SubcloudGroupsController(object):
|
|||
:param group_ref: ID or name of subcloud group to update
|
||||
"""
|
||||
|
||||
policy.authorize(subcloud_group_policy.POLICY_ROOT % "modify", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
if group_ref is None:
|
||||
pecan.abort(httpclient.BAD_REQUEST,
|
||||
|
@ -256,6 +264,8 @@ class SubcloudGroupsController(object):
|
|||
@index.when(method='delete', template='json')
|
||||
def delete(self, group_ref):
|
||||
"""Delete the subcloud group."""
|
||||
policy.authorize(subcloud_group_policy.POLICY_ROOT % "delete", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
if group_ref is None:
|
||||
|
|
|
@ -49,6 +49,8 @@ from keystoneauth1 import exceptions as keystone_exceptions
|
|||
import tsconfig.tsconfig as tsc
|
||||
|
||||
from dcmanager.api.controllers import restcomm
|
||||
from dcmanager.api.policies import subclouds as subclouds_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.common import consts
|
||||
from dcmanager.common import exceptions
|
||||
from dcmanager.common.i18n import _
|
||||
|
@ -826,6 +828,8 @@ class SubcloudsController(object):
|
|||
|
||||
:param subcloud_ref: ID or name of subcloud
|
||||
"""
|
||||
policy.authorize(subclouds_policy.POLICY_ROOT % "get", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
if subcloud_ref is None:
|
||||
|
@ -947,6 +951,8 @@ class SubcloudsController(object):
|
|||
config)
|
||||
"""
|
||||
|
||||
policy.authorize(subclouds_policy.POLICY_ROOT % "create", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
if subcloud_ref is None:
|
||||
|
@ -1076,6 +1082,8 @@ class SubcloudsController(object):
|
|||
or subcloud update operation
|
||||
"""
|
||||
|
||||
policy.authorize(subclouds_policy.POLICY_ROOT % "modify", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
subcloud = None
|
||||
|
||||
|
@ -1468,6 +1476,8 @@ class SubcloudsController(object):
|
|||
|
||||
:param subcloud_ref: ID or name of subcloud to delete.
|
||||
"""
|
||||
policy.authorize(subclouds_policy.POLICY_ROOT % "delete", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
subcloud = None
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ from pecan import request
|
|||
|
||||
from dccommon import consts as dccommon_consts
|
||||
from dcmanager.api.controllers import restcomm
|
||||
from dcmanager.api.policies import sw_update_options as sw_update_options_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.common import exceptions
|
||||
from dcmanager.common.i18n import _
|
||||
from dcmanager.common import utils
|
||||
|
@ -51,6 +53,8 @@ class SwUpdateOptionsController(object):
|
|||
|
||||
:param subcloud: name or id of subcloud (optional)
|
||||
"""
|
||||
policy.authorize(sw_update_options_policy.POLICY_ROOT % "get", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
if subcloud_ref is None:
|
||||
|
@ -114,6 +118,8 @@ class SwUpdateOptionsController(object):
|
|||
# Note creating or updating subcloud specific options require
|
||||
# setting all options.
|
||||
|
||||
policy.authorize(sw_update_options_policy.POLICY_ROOT % "update", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
payload = eval(request.body)
|
||||
|
@ -204,6 +210,8 @@ class SwUpdateOptionsController(object):
|
|||
def delete(self, subcloud_ref):
|
||||
"""Delete the software update options."""
|
||||
|
||||
policy.authorize(sw_update_options_policy.POLICY_ROOT % "delete", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
if subcloud_ref == dccommon_consts.DEFAULT_REGION_NAME:
|
||||
|
|
|
@ -25,6 +25,8 @@ from pecan import request
|
|||
|
||||
from dccommon import consts as dccommon_consts
|
||||
from dcmanager.api.controllers import restcomm
|
||||
from dcmanager.api.policies import sw_update_strategy as sw_update_strat_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.common import consts
|
||||
from dcmanager.common import exceptions
|
||||
from dcmanager.common.i18n import _
|
||||
|
@ -71,6 +73,8 @@ class SwUpdateStrategyController(object):
|
|||
:param steps: get the steps for this strategy (optional)
|
||||
:param cloud_name: name of cloud (optional)
|
||||
"""
|
||||
policy.authorize(sw_update_strat_policy.POLICY_ROOT % "get", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
# If 'type' is in the request params, filter the update_type
|
||||
|
@ -138,6 +142,9 @@ class SwUpdateStrategyController(object):
|
|||
pecan.abort(400, _('Body required'))
|
||||
|
||||
if actions is None:
|
||||
policy.authorize(sw_update_strat_policy.POLICY_ROOT % "create", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
|
||||
# Validate any options that were supplied
|
||||
strategy_type = payload.get('type')
|
||||
if not strategy_type:
|
||||
|
@ -218,6 +225,8 @@ class SwUpdateStrategyController(object):
|
|||
if not action:
|
||||
pecan.abort(400, _('action required'))
|
||||
if action == consts.SW_UPDATE_ACTION_APPLY:
|
||||
policy.authorize(sw_update_strat_policy.POLICY_ROOT % "apply",
|
||||
{}, restcomm.extract_credentials_for_policy())
|
||||
try:
|
||||
# Ask dcmanager-manager to apply the strategy.
|
||||
# It will do all the real work...
|
||||
|
@ -230,6 +239,8 @@ class SwUpdateStrategyController(object):
|
|||
LOG.exception(e)
|
||||
pecan.abort(500, _('Unable to apply strategy'))
|
||||
elif action == consts.SW_UPDATE_ACTION_ABORT:
|
||||
policy.authorize(sw_update_strat_policy.POLICY_ROOT % "abort",
|
||||
{}, restcomm.extract_credentials_for_policy())
|
||||
try:
|
||||
# Ask dcmanager-manager to abort the strategy.
|
||||
# It will do all the real work...
|
||||
|
@ -245,6 +256,8 @@ class SwUpdateStrategyController(object):
|
|||
@index.when(method='delete', template='json')
|
||||
def delete(self):
|
||||
"""Delete the software update strategy."""
|
||||
policy.authorize(sw_update_strat_policy.POLICY_ROOT % "delete", {},
|
||||
restcomm.extract_credentials_for_policy())
|
||||
context = restcomm.extract_context_from_environ()
|
||||
|
||||
# If 'type' is in the request params, filter the update_type
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
# Copyright 2017 Ericsson AB.
|
||||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Policy enforcer for DC Manager."""
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
|
||||
from dcmanager.common import exceptions as exc
|
||||
|
||||
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def enforce(action, context, target=None, do_raise=True,
|
||||
exc=exc.NotAuthorized):
|
||||
"""Verify that the action is valid on the target in this context.
|
||||
|
||||
:param action: String, representing the action to be checked.
|
||||
This should be colon separated for clarity.
|
||||
i.e. ``sync:list``
|
||||
:param context: DC Manager context.
|
||||
:param target: Dictionary, representing the object of the action.
|
||||
For object creation, this should be a dictionary
|
||||
representing the location of the object.
|
||||
e.g. ``{'project_id': context.project}``
|
||||
:param do_raise: if True (the default), raises specified exception.
|
||||
:param exc: Exception to be raised if not authorized. Default is
|
||||
dcmanager.common.exceptions.NotAuthorized.
|
||||
|
||||
:return: returns True if authorized and False if not authorized and
|
||||
do_raise is False.
|
||||
"""
|
||||
if cfg.CONF.auth_strategy != 'keystone':
|
||||
# Policy enforcement is supported now only with Keystone
|
||||
# authentication.
|
||||
return
|
||||
|
||||
target_obj = {
|
||||
'project_id': context.project,
|
||||
'user_id': context.user,
|
||||
}
|
||||
|
||||
target_obj.update(target or {})
|
||||
_ensure_enforcer_initialization()
|
||||
|
||||
try:
|
||||
_ENFORCER.enforce(action, target_obj, context.to_dict(),
|
||||
do_raise=do_raise, exc=exc)
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _ensure_enforcer_initialization():
|
||||
global _ENFORCER
|
||||
if not _ENFORCER:
|
||||
_ENFORCER = policy.Enforcer(cfg.CONF)
|
||||
_ENFORCER.load_rules()
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import itertools
|
||||
|
||||
from dcmanager.api.policies import alarm_manager
|
||||
from dcmanager.api.policies import base
|
||||
from dcmanager.api.policies import subcloud_backup
|
||||
from dcmanager.api.policies import subcloud_deploy
|
||||
from dcmanager.api.policies import subcloud_group
|
||||
from dcmanager.api.policies import subclouds
|
||||
from dcmanager.api.policies import sw_update_options
|
||||
from dcmanager.api.policies import sw_update_strategy
|
||||
|
||||
|
||||
def list_rules():
|
||||
return itertools.chain(
|
||||
base.list_rules(),
|
||||
subclouds.list_rules(),
|
||||
subcloud_deploy.list_rules(),
|
||||
alarm_manager.list_rules(),
|
||||
sw_update_strategy.list_rules(),
|
||||
sw_update_options.list_rules(),
|
||||
subcloud_group.list_rules(),
|
||||
subcloud_backup.list_rules()
|
||||
)
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from dcmanager.api.policies import base
|
||||
from oslo_policy import policy
|
||||
|
||||
POLICY_ROOT = 'dc_api:alarm_manager:%s'
|
||||
|
||||
|
||||
alarm_manager_rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'get',
|
||||
check_str='rule:' + base.READER_IN_SYSTEM_PROJECTS,
|
||||
description="Get alarms from subclouds.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/alarms'
|
||||
}
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return alarm_manager_rules
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from oslo_policy import policy
|
||||
|
||||
ADMIN_IN_SYSTEM_PROJECTS = 'admin_in_system_projects'
|
||||
READER_IN_SYSTEM_PROJECTS = 'reader_in_system_projects'
|
||||
|
||||
|
||||
base_rules = [
|
||||
policy.RuleDefault(
|
||||
name=ADMIN_IN_SYSTEM_PROJECTS,
|
||||
check_str='role:admin and (project_name:admin or ' +
|
||||
'project_name:services)',
|
||||
description="Base rule.",
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name=READER_IN_SYSTEM_PROJECTS,
|
||||
check_str='role:reader and (project_name:admin or ' +
|
||||
'project_name:services)',
|
||||
description="Base rule."
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return base_rules
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from dcmanager.api.policies import base
|
||||
from oslo_policy import policy
|
||||
|
||||
POLICY_ROOT = 'dc_api:subcloud_backup:%s'
|
||||
|
||||
|
||||
subcloud_backup_rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'create',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Create new subcloud backup.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/subcloud-backup'
|
||||
}
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return subcloud_backup_rules
|
|
@ -0,0 +1,40 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from dcmanager.api.policies import base
|
||||
from oslo_policy import policy
|
||||
|
||||
POLICY_ROOT = 'dc_api:subcloud_deploy:%s'
|
||||
|
||||
|
||||
subcloud_deploy_rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'upload',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Upload subcloud deploy files.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/subcloud-deploy'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'get',
|
||||
check_str='rule:' + base.READER_IN_SYSTEM_PROJECTS,
|
||||
description="Show subcloud deploy files.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/subcloud-deploy'
|
||||
}
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return subcloud_deploy_rules
|
|
@ -0,0 +1,70 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from dcmanager.api.policies import base
|
||||
from oslo_policy import policy
|
||||
|
||||
POLICY_ROOT = 'dc_api:subcloud_groups:%s'
|
||||
|
||||
|
||||
subcloud_groups_rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'create',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Create subcloud group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/subcloud-groups'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'delete',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Delete subcloud group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/v1.0/subcloud-groups/{subcloud_group}'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'get',
|
||||
check_str='rule:' + base.READER_IN_SYSTEM_PROJECTS,
|
||||
description="Get subcloud groups.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/subcloud-groups'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/subcloud-groups/{subcloud_group}'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/subcloud-groups/{subcloud_group}/subclouds'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'modify',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Modify subcloud group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'PATCH',
|
||||
'path': '/v1.0/subcloud-groups/{subcloud_group}'
|
||||
}
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return subcloud_groups_rules
|
|
@ -0,0 +1,90 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from dcmanager.api.policies import base
|
||||
from oslo_policy import policy
|
||||
|
||||
POLICY_ROOT = 'dc_api:subclouds:%s'
|
||||
|
||||
|
||||
subclouds_rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'create',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Create a subcloud.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/subclouds'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'delete',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Delete a subcloud.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/v1.0/subclouds/{alarm_uuid}'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'get',
|
||||
check_str='rule:' + base.READER_IN_SYSTEM_PROJECTS,
|
||||
description="Get subclouds data.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/subclouds'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/subclouds/{subcloud}'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/subclouds/{subcloud}/detail'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'modify',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Modify a subcloud.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'PATCH',
|
||||
'path': '/v1.0/subclouds/{subcloud}'
|
||||
},
|
||||
{
|
||||
'method': 'PATCH',
|
||||
'path': '/v1.0/subclouds/{subcloud}/prestage'
|
||||
},
|
||||
{
|
||||
'method': 'PATCH',
|
||||
'path': '/v1.0/subclouds/{subcloud}/reconfigure'
|
||||
},
|
||||
{
|
||||
'method': 'PATCH',
|
||||
'path': '/v1.0/subclouds/{subcloud}/reinstall'
|
||||
},
|
||||
{
|
||||
'method': 'PATCH',
|
||||
'path': '/v1.0/subclouds/{subcloud}/restore'
|
||||
},
|
||||
{
|
||||
'method': 'PATCH',
|
||||
'path': '/v1.0/subclouds/{subcloud}/update_status'
|
||||
}
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return subclouds_rules
|
|
@ -0,0 +1,55 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from dcmanager.api.policies import base
|
||||
from oslo_policy import policy
|
||||
|
||||
POLICY_ROOT = 'dc_api:sw_update_options:%s'
|
||||
|
||||
|
||||
sw_update_options_rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'delete',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Delete per subcloud sw-update options.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/v1.0/sw-update-options/{subcloud}'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'get',
|
||||
check_str='rule:' + base.READER_IN_SYSTEM_PROJECTS,
|
||||
description="Get sw-update options.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/sw-update-options'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/sw-update-options/{subcloud}'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'update',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Update sw-update options (defaults or per subcloud).",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/sw-update-options/{subcloud}'
|
||||
}
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return sw_update_options_rules
|
|
@ -0,0 +1,81 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from dcmanager.api.policies import base
|
||||
from oslo_policy import policy
|
||||
|
||||
POLICY_ROOT = 'dc_api:sw_update_strategy:%s'
|
||||
|
||||
|
||||
sw_update_strategy_rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'abort',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Abort update strategy execution.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/sw-update-strategy/actions'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'apply',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Apply update strategy.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/sw-update-strategy/actions'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'create',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Create update strategy.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/v1.0/sw-update-strategy'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'delete',
|
||||
check_str='rule:' + base.ADMIN_IN_SYSTEM_PROJECTS,
|
||||
description="Delete update strategy.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/v1.0/sw-update-strategy'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_ROOT % 'get',
|
||||
check_str='rule:' + base.READER_IN_SYSTEM_PROJECTS,
|
||||
description="Get update strategy.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/sw-update-strategy'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/sw-update-strategy/steps'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/v1.0/sw-update-strategy/steps/{cloud_name}'
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return sw_update_strategy_rules
|
|
@ -0,0 +1,62 @@
|
|||
# Copyright (c) 2011 OpenStack Foundation
|
||||
# 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.
|
||||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
"""Policy Engine For DC."""
|
||||
|
||||
from dcmanager.api import policies as controller_policies
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
from webob import exc
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def reset():
|
||||
"""Discard current Enforcer object."""
|
||||
global _ENFORCER
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def init(policy_file='policy.yaml'):
|
||||
"""Init an Enforcer class.
|
||||
|
||||
:param policy_file: Custom policy file to be used.
|
||||
|
||||
:return: Returns a Enforcer instance.
|
||||
"""
|
||||
global _ENFORCER
|
||||
if not _ENFORCER:
|
||||
|
||||
# https://docs.openstack.org/oslo.policy/latest/user/usage.html
|
||||
_ENFORCER = policy.Enforcer(CONF,
|
||||
policy_file=policy_file,
|
||||
default_rule='default',
|
||||
use_conf=True,
|
||||
overwrite=True)
|
||||
_ENFORCER.register_defaults(controller_policies.list_rules())
|
||||
return _ENFORCER
|
||||
|
||||
|
||||
def authorize(rule, target, creds, do_raise=True):
|
||||
"""A wrapper around 'authorize' from 'oslo_policy.policy'."""
|
||||
init()
|
||||
return _ENFORCER.authorize(rule, target, creds, do_raise=do_raise,
|
||||
exc=exc.HTTPForbidden)
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2017, 2019, 2021, 2022 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
||||
# 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
|
||||
|
@ -23,7 +23,8 @@ from oslo_log import log
|
|||
from oslo_utils import encodeutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from dcmanager.common import policy
|
||||
from dcmanager.api.policies import base as base_policy
|
||||
from dcmanager.api import policy
|
||||
from dcmanager.db import api as db_api
|
||||
|
||||
ALLOWED_WITHOUT_AUTH = '/'
|
||||
|
@ -87,9 +88,9 @@ class RequestContext(base_context.RequestContext):
|
|||
|
||||
# Check user is admin or not
|
||||
if is_admin is None:
|
||||
self.is_admin = policy.enforce(self, 'context_is_admin',
|
||||
target={'project': self.project},
|
||||
do_raise=False)
|
||||
self.is_admin = policy.authorize(
|
||||
base_policy.ADMIN_IN_SYSTEM_PROJECTS, {}, self.to_dict(),
|
||||
do_raise=False)
|
||||
else:
|
||||
self.is_admin = is_admin
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
# Copyright (c) 2017, 2019, 2021 Wind River Systems, Inc.
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""
|
||||
Policy Engine For DC Manager
|
||||
"""
|
||||
|
||||
# from oslo_concurrency import lockutils
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
|
||||
from dcmanager.common import exceptions
|
||||
|
||||
POLICY_ENFORCER = None
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
# @lockutils.synchronized('policy_enforcer', 'dcmanager-')
|
||||
def _get_enforcer(policy_file=None, rules=None, default_rule=None):
|
||||
|
||||
global POLICY_ENFORCER
|
||||
|
||||
if POLICY_ENFORCER is None:
|
||||
POLICY_ENFORCER = policy.Enforcer(CONF,
|
||||
policy_file=policy_file,
|
||||
rules=rules,
|
||||
default_rule=default_rule)
|
||||
return POLICY_ENFORCER
|
||||
|
||||
|
||||
def enforce(context, rule, target, do_raise=True, *args, **kwargs):
|
||||
|
||||
enforcer = _get_enforcer()
|
||||
credentials = context.to_dict()
|
||||
target = target or {}
|
||||
if do_raise:
|
||||
kwargs.update(exc=exceptions.Forbidden)
|
||||
|
||||
return enforcer.enforce(rule, target, credentials, do_raise,
|
||||
*args, **kwargs)
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2015 Huawei Technologies Co., Ltd.
|
||||
# Copyright (c) 2017-2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -47,7 +47,9 @@ class DCManagerApiTest(base.DCManagerTestCase):
|
|||
|
||||
api_config.test_init()
|
||||
|
||||
self.CONF = self.useFixture(fixture_config.Config()).conf
|
||||
config = fixture_config.Config()
|
||||
self.CONF = self.useFixture(config).conf
|
||||
config.set_config_dirs([])
|
||||
|
||||
# self.setup_messaging(self.CONF)
|
||||
self.CONF.set_override('auth_strategy', 'noauth')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Ericsson AB
|
||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -29,8 +29,9 @@ class APIMixin(object):
|
|||
|
||||
api_headers = {
|
||||
'X-Tenant-Id': FAKE_TENANT,
|
||||
'X_ROLE': 'admin',
|
||||
'X-Identity-Status': 'Confirmed'
|
||||
'X_ROLE': 'admin,member,reader',
|
||||
'X-Identity-Status': 'Confirmed',
|
||||
'X-Project-Name': 'admin'
|
||||
}
|
||||
|
||||
# subclasses should provide methods
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
||||
# 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
|
||||
|
@ -22,8 +22,8 @@ from dcmanager.tests import utils
|
|||
FAKE_URL = '/v1.0/alarms'
|
||||
FAKE_TENANT = utils.UUID1
|
||||
FAKE_ID = '1'
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin',
|
||||
'X-Identity-Status': 'Confirmed'}
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin,member,reader',
|
||||
'X-Identity-Status': 'Confirmed', 'X-Project-Name': 'admin'}
|
||||
|
||||
|
||||
class TestSubcloudAlarmController(testroot.DCManagerApiTest):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||
# 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
|
||||
|
@ -22,8 +22,8 @@ from dcmanager.tests import utils
|
|||
|
||||
FAKE_URL = '/v1.0/notifications'
|
||||
FAKE_TENANT = utils.UUID1
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin',
|
||||
'X-Identity-Status': 'Confirmed'}
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin,member,reader',
|
||||
'X-Identity-Status': 'Confirmed', 'X-Project-Name': 'admin'}
|
||||
|
||||
|
||||
class TestNotificationsController(testroot.DCManagerApiTest):
|
||||
|
|
|
@ -25,8 +25,8 @@ from dcmanager.tests import utils
|
|||
FAKE_TENANT = utils.UUID1
|
||||
FAKE_ID = '1'
|
||||
FAKE_URL = '/v1.0/subcloud-deploy'
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin',
|
||||
'X-Identity-Status': 'Confirmed'}
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin,member,reader',
|
||||
'X-Identity-Status': 'Confirmed', 'X-Project-Name': 'admin'}
|
||||
|
||||
|
||||
class TestSubcloudDeploy(testroot.DCManagerApiTest):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Ericsson AB
|
||||
# Copyright (c) 2017-2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -31,8 +31,8 @@ from dcmanager.tests import utils
|
|||
FAKE_TENANT = utils.UUID1
|
||||
FAKE_ID = '1'
|
||||
FAKE_URL = '/v1.0/sw-update-strategy'
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin',
|
||||
'X-Identity-Status': 'Confirmed'}
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin,member,reader',
|
||||
'X-Identity-Status': 'Confirmed', 'X-Project-Name': 'admin'}
|
||||
|
||||
FAKE_SW_UPDATE_DATA = {
|
||||
"type": consts.SW_UPDATE_TYPE_PATCH,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
@ -16,8 +16,8 @@ FAKE_ID = '1'
|
|||
FAKE_URL = '/v1.0/subclouds'
|
||||
WRONG_URL = '/v1.0/wrong'
|
||||
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin',
|
||||
'X-Identity-Status': 'Confirmed'}
|
||||
FAKE_HEADERS = {'X-Tenant-Id': FAKE_TENANT, 'X_ROLE': 'admin,member,reader',
|
||||
'X-Identity-Status': 'Confirmed', 'X-Project-Name': 'admin'}
|
||||
|
||||
FAKE_SUBCLOUD_DATA = {"id": FAKE_ID,
|
||||
"name": "subcloud1",
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
# Copyright 2017 Ericsson AB.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Policy enforcer for DC Orchestrators."""
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
|
||||
from dcorch.common import exceptions as exc
|
||||
|
||||
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def enforce(action, context, target=None, do_raise=True,
|
||||
exc=exc.NotAuthorized):
|
||||
"""Verify that the action is valid on the target in this context.
|
||||
|
||||
:param action: String, representing the action to be checked.
|
||||
This should be colon separated for clarity.
|
||||
i.e. ``sync:list``
|
||||
:param context: dcorch context.
|
||||
:param target: Dictionary, representing the object of the action.
|
||||
For object creation, this should be a dictionary
|
||||
representing the location of the object.
|
||||
e.g. ``{'project_id': context.project}``
|
||||
:param do_raise: if True (the default), raises specified exception.
|
||||
:param exc: Exception to be raised if not authorized. Default is
|
||||
dcorch.common.exceptions.NotAuthorized.
|
||||
|
||||
:return: returns True if authorized and False if not authorized and
|
||||
do_raise is False.
|
||||
"""
|
||||
if cfg.CONF.auth_strategy != 'keystone':
|
||||
# Policy enforcement is supported now only with Keystone
|
||||
# authentication.
|
||||
return
|
||||
|
||||
target_obj = {
|
||||
'project_id': context.project,
|
||||
'user_id': context.user,
|
||||
}
|
||||
|
||||
target_obj.update(target or {})
|
||||
_ensure_enforcer_initialization()
|
||||
|
||||
try:
|
||||
_ENFORCER.enforce(action, target_obj, context.to_dict(),
|
||||
do_raise=do_raise, exc=exc)
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _ensure_enforcer_initialization():
|
||||
global _ENFORCER
|
||||
if not _ENFORCER:
|
||||
_ENFORCER = policy.Enforcer(cfg.CONF)
|
||||
_ENFORCER.load_rules()
|
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import itertools
|
||||
|
||||
from dcorch.api.policies import base
|
||||
|
||||
|
||||
def list_rules():
|
||||
return itertools.chain(
|
||||
base.list_rules()
|
||||
)
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from oslo_policy import policy
|
||||
|
||||
ADMIN_IN_SYSTEM_PROJECTS = 'admin_in_system_projects'
|
||||
READER_IN_SYSTEM_PROJECTS = 'reader_in_system_projects'
|
||||
|
||||
|
||||
base_rules = [
|
||||
policy.RuleDefault(
|
||||
name=ADMIN_IN_SYSTEM_PROJECTS,
|
||||
check_str='role:admin and (project_name:admin or ' +
|
||||
'project_name:services)',
|
||||
description="Base rule.",
|
||||
),
|
||||
policy.RuleDefault(
|
||||
name=READER_IN_SYSTEM_PROJECTS,
|
||||
check_str='role:reader and (project_name:admin or ' +
|
||||
'project_name:services)',
|
||||
description="Base rule."
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return base_rules
|
|
@ -0,0 +1,62 @@
|
|||
# Copyright (c) 2011 OpenStack Foundation
|
||||
# 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.
|
||||
#
|
||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
"""Policy Engine For DC."""
|
||||
|
||||
from dcorch.api import policies as controller_policies
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
from webob import exc
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def reset():
|
||||
"""Discard current Enforcer object."""
|
||||
global _ENFORCER
|
||||
_ENFORCER = None
|
||||
|
||||
|
||||
def init(policy_file='policy.yaml'):
|
||||
"""Init an Enforcer class.
|
||||
|
||||
:param policy_file: Custom policy file to be used.
|
||||
|
||||
:return: Returns a Enforcer instance.
|
||||
"""
|
||||
global _ENFORCER
|
||||
if not _ENFORCER:
|
||||
|
||||
# https://docs.openstack.org/oslo.policy/latest/user/usage.html
|
||||
_ENFORCER = policy.Enforcer(CONF,
|
||||
policy_file=policy_file,
|
||||
default_rule='default',
|
||||
use_conf=True,
|
||||
overwrite=True)
|
||||
_ENFORCER.register_defaults(controller_policies.list_rules())
|
||||
return _ENFORCER
|
||||
|
||||
|
||||
def authorize(rule, target, creds, do_raise=True):
|
||||
"""A wrapper around 'authorize' from 'oslo_policy.policy'."""
|
||||
init()
|
||||
return _ENFORCER.authorize(rule, target, creds, do_raise=do_raise,
|
||||
exc=exc.HTTPForbidden)
|
|
@ -17,7 +17,8 @@ from pecan import hooks
|
|||
from oslo_context import context as base_context
|
||||
from oslo_utils import encodeutils
|
||||
|
||||
from dcorch.common import policy
|
||||
from dcorch.api.policies import base as base_policy
|
||||
from dcorch.api import policy
|
||||
from dcorch.db import api as db_api
|
||||
|
||||
ALLOWED_WITHOUT_AUTH = '/'
|
||||
|
@ -74,9 +75,9 @@ class RequestContext(base_context.RequestContext):
|
|||
|
||||
# Check user is admin or not
|
||||
if is_admin is None:
|
||||
self.is_admin = policy.enforce(self, 'context_is_admin',
|
||||
target={'project': self.project},
|
||||
do_raise=False)
|
||||
self.is_admin = policy.authorize(
|
||||
base_policy.ADMIN_IN_SYSTEM_PROJECTS, {}, self.to_dict(),
|
||||
do_raise=False)
|
||||
else:
|
||||
self.is_admin = is_admin
|
||||
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
Policy Engine For DC Orchestrators
|
||||
"""
|
||||
|
||||
# from oslo_concurrency import lockutils
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy
|
||||
|
||||
from dcorch.common import exceptions
|
||||
|
||||
POLICY_ENFORCER = None
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
# @lockutils.synchronized('policy_enforcer', 'dcorch-')
|
||||
def _get_enforcer(policy_file=None, rules=None, default_rule=None):
|
||||
|
||||
global POLICY_ENFORCER
|
||||
|
||||
if POLICY_ENFORCER is None:
|
||||
POLICY_ENFORCER = policy.Enforcer(CONF,
|
||||
policy_file=policy_file,
|
||||
rules=rules,
|
||||
default_rule=default_rule)
|
||||
return POLICY_ENFORCER
|
||||
|
||||
|
||||
def enforce(context, rule, target, do_raise=True, *args, **kwargs):
|
||||
|
||||
enforcer = _get_enforcer()
|
||||
credentials = context.to_dict()
|
||||
target = target or {}
|
||||
if do_raise:
|
||||
kwargs.update(exc=exceptions.Forbidden)
|
||||
|
||||
return enforcer.enforce(rule, target, credentials, do_raise,
|
||||
*args, **kwargs)
|
Loading…
Reference in New Issue