diff --git a/etc/policy.json b/etc/policy.json index 6c1c05fa..5efa7a47 100644 --- a/etc/policy.json +++ b/etc/policy.json @@ -1,9 +1,4 @@ { - "scheduled_operation:create": "", - "scheduled_operation:delete": "rule:admin_or_owner", - "scheduled_operation:get": "rule:admin_or_owner", - "scheduled_operation:list": "", - "operation_log:get": "rule:admin_or_owner", "operation_log:get_all": "rule:admin_or_owner" } diff --git a/karbor/api/v1/scheduled_operations.py b/karbor/api/v1/scheduled_operations.py index 315e3f41..57232130 100644 --- a/karbor/api/v1/scheduled_operations.py +++ b/karbor/api/v1/scheduled_operations.py @@ -21,18 +21,13 @@ from karbor.api.openstack import wsgi from karbor import exception from karbor.i18n import _ from karbor import objects -from karbor import policy +from karbor.policies import scheduled_operations as scheduled_operation_policy from karbor.services.operationengine import api as operationengine_api from karbor import utils LOG = logging.getLogger(__name__) -def check_policy(context, action, target_obj=None): - _action = 'scheduled_operation:%s' % action - policy.enforce(context, _action, target_obj) - - class ScheduledOperationViewBuilder(common.ViewBuilder): """Model a server API response as a python dictionary.""" @@ -92,7 +87,7 @@ class ScheduledOperationController(wsgi.Controller): LOG.debug('Create a scheduled operation, request body: %s', body) context = req.environ['karbor.context'] - check_policy(context, 'create') + context.can(scheduled_operation_policy.CREATE_POLICY) operation_info = body['scheduled_operation'] name = operation_info.get("name", None) @@ -148,7 +143,7 @@ class ScheduledOperationController(wsgi.Controller): operation = self._get_operation_by_id(context, id, ['trigger']) trigger = operation.trigger - check_policy(context, 'delete', operation) + context.can(scheduled_operation_policy.DELETE_POLICY, operation) try: self.operationengine_api.delete_scheduled_operation( @@ -168,7 +163,7 @@ class ScheduledOperationController(wsgi.Controller): context = req.environ['karbor.context'] operation = self._get_operation_by_id(context, id) - check_policy(context, 'get', operation) + context.can(scheduled_operation_policy.GET_POLICY, operation) return self._view_builder.detail(req, operation) @@ -176,7 +171,7 @@ class ScheduledOperationController(wsgi.Controller): """Returns a list of operations, transformed through view builder.""" context = req.environ['karbor.context'] - check_policy(context, 'list') + context.can(scheduled_operation_policy.GET_ALL_POLICY) params = req.params.copy() LOG.debug('List scheduled operation start, params=%s', params) diff --git a/karbor/policies/__init__.py b/karbor/policies/__init__.py index fa477d55..7674782a 100644 --- a/karbor/policies/__init__.py +++ b/karbor/policies/__init__.py @@ -19,6 +19,7 @@ from karbor.policies import plans from karbor.policies import protectables from karbor.policies import providers from karbor.policies import restores +from karbor.policies import scheduled_operations from karbor.policies import triggers @@ -30,4 +31,5 @@ def list_rules(): protectables.list_rules(), providers.list_rules(), triggers.list_rules(), + scheduled_operations.list_rules(), ) diff --git a/karbor/policies/scheduled_operations.py b/karbor/policies/scheduled_operations.py new file mode 100644 index 00000000..5984d164 --- /dev/null +++ b/karbor/policies/scheduled_operations.py @@ -0,0 +1,71 @@ +# Copyright (c) 2017 Huawei Technologies Co., Ltd. +# 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_policy import policy + +from karbor.policies import base + + +CREATE_POLICY = 'scheduled_operation:create' +DELETE_POLICY = 'scheduled_operation:delete' +GET_POLICY = 'scheduled_operation:get' +GET_ALL_POLICY = 'scheduled_operation:list' + +scheduled_operations_policies = [ + policy.DocumentedRuleDefault( + name=CREATE_POLICY, + check_str=base.RULE_ADMIN_OR_OWNER, + description="""Create a scheduled_operation.""", + operations=[ + { + 'method': 'POST', + 'path': '/scheduled_operations' + } + ]), + policy.DocumentedRuleDefault( + name=DELETE_POLICY, + check_str=base.RULE_ADMIN_OR_OWNER, + description="""Delete a scheduled_operation.""", + operations=[ + { + 'method': 'DELETE', + 'path': '/scheduled_operations/{scheduled_operation_id}' + } + ]), + policy.DocumentedRuleDefault( + name=GET_POLICY, + check_str=base.RULE_ADMIN_OR_OWNER, + description="""Get a scheduled_operation.""", + operations=[ + { + 'method': 'GET', + 'path': '/scheduled_operations/{scheduled_operation_id}' + } + ]), + policy.DocumentedRuleDefault( + name=GET_ALL_POLICY, + check_str=base.RULE_ADMIN_OR_OWNER, + description="""Get scheduled_operations.""", + operations=[ + { + 'method': 'GET', + 'path': '/scheduled_operations' + } + ]), +] + + +def list_rules(): + return scheduled_operations_policies diff --git a/karbor/policy.py b/karbor/policy.py index 7fbdfe77..504dbde2 100644 --- a/karbor/policy.py +++ b/karbor/policy.py @@ -183,7 +183,7 @@ def authorize(context, action, target, do_raise=True, exc=None): LOG.exception('Policy not registered') except Exception: with excutils.save_and_reraise_exception(): - LOG.debug('Policy check for %(action)s failed with credentials ' + LOG.error('Policy check for %(action)s failed with credentials ' '%(credentials)s', {'action': action, 'credentials': credentials}) return result diff --git a/karbor/tests/unit/api/v1/test_scheduled_operation.py b/karbor/tests/unit/api/v1/test_scheduled_operation.py index 70744c6e..66eb66b2 100644 --- a/karbor/tests/unit/api/v1/test_scheduled_operation.py +++ b/karbor/tests/unit/api/v1/test_scheduled_operation.py @@ -63,6 +63,8 @@ class ScheduledOperationApiTest(base.TestCase): "provider_id": self._plan['provider_id'] }, } + self.mock_policy_check = self.mock_object( + context.RequestContext, 'can') def test_create_operation_InvalidBody(self): self.assertRaises(exc.HTTPUnprocessableEntity,