[policy in code] Add support for message, worker, cluster resources
This patch adds policy in code support for message, worker and cluster resources and depends on the basic patch [1]. [1]: https://review.openstack.org/#/c/506976/ Change-Id: I04c0b79175c69d25ca6fcb50ec604123f3f09933 Partial-Implements: blueprint policy-in-code
This commit is contained in:
parent
43a3152581
commit
c52b7ef584
@ -19,6 +19,7 @@ from cinder.api.v3.views import clusters as clusters_view
|
|||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
|
from cinder.policies import clusters as policy
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
|
|
||||||
@ -28,13 +29,12 @@ class ClusterController(wsgi.Controller):
|
|||||||
'frozen', 'active_backend_id'}
|
'frozen', 'active_backend_id'}
|
||||||
replication_fields = {'replication_status', 'frozen', 'active_backend_id'}
|
replication_fields = {'replication_status', 'frozen', 'active_backend_id'}
|
||||||
|
|
||||||
policy_checker = wsgi.Controller.get_policy_checker('clusters')
|
|
||||||
|
|
||||||
@wsgi.Controller.api_version(mv.CLUSTER_SUPPORT)
|
@wsgi.Controller.api_version(mv.CLUSTER_SUPPORT)
|
||||||
def show(self, req, id, binary='cinder-volume'):
|
def show(self, req, id, binary='cinder-volume'):
|
||||||
"""Return data for a given cluster name with optional binary."""
|
"""Return data for a given cluster name with optional binary."""
|
||||||
# Let the wsgi middleware convert NotAuthorized exceptions
|
# Let the wsgi middleware convert NotAuthorized exceptions
|
||||||
context = self.policy_checker(req, 'get')
|
context = req.environ['cinder.context']
|
||||||
|
context.authorize(policy.GET_POLICY)
|
||||||
# Let the wsgi middleware convert NotFound exceptions
|
# Let the wsgi middleware convert NotFound exceptions
|
||||||
cluster = objects.Cluster.get_by_id(context, None, binary=binary,
|
cluster = objects.Cluster.get_by_id(context, None, binary=binary,
|
||||||
name=id, services_summary=True)
|
name=id, services_summary=True)
|
||||||
@ -60,7 +60,8 @@ class ClusterController(wsgi.Controller):
|
|||||||
|
|
||||||
def _get_clusters(self, req, detail):
|
def _get_clusters(self, req, detail):
|
||||||
# Let the wsgi middleware convert NotAuthorized exceptions
|
# Let the wsgi middleware convert NotAuthorized exceptions
|
||||||
context = self.policy_checker(req, 'get_all')
|
context = req.environ['cinder.context']
|
||||||
|
context.authorize(policy.GET_ALL_POLICY)
|
||||||
replication_data = req.api_version_request.matches(
|
replication_data = req.api_version_request.matches(
|
||||||
mv.REPLICATION_CLUSTER)
|
mv.REPLICATION_CLUSTER)
|
||||||
filters = dict(req.GET)
|
filters = dict(req.GET)
|
||||||
@ -93,7 +94,8 @@ class ClusterController(wsgi.Controller):
|
|||||||
# update endpoint API.
|
# update endpoint API.
|
||||||
|
|
||||||
# Let the wsgi middleware convert NotAuthorized exceptions
|
# Let the wsgi middleware convert NotAuthorized exceptions
|
||||||
context = self.policy_checker(req, 'update')
|
context = req.environ['cinder.context']
|
||||||
|
context.authorize(policy.UPDATE_POLICY)
|
||||||
|
|
||||||
if id not in ('enable', 'disable'):
|
if id not in ('enable', 'disable'):
|
||||||
raise exception.NotFound(message=_("Unknown action"))
|
raise exception.NotFound(message=_("Unknown action"))
|
||||||
|
@ -23,18 +23,7 @@ from cinder.api.v3.views import messages as messages_view
|
|||||||
from cinder.message import api as message_api
|
from cinder.message import api as message_api
|
||||||
from cinder.message import defined_messages
|
from cinder.message import defined_messages
|
||||||
from cinder.message import message_field
|
from cinder.message import message_field
|
||||||
import cinder.policy
|
from cinder.policies import messages as policy
|
||||||
|
|
||||||
|
|
||||||
def check_policy(context, action, target_obj=None):
|
|
||||||
target = {
|
|
||||||
'project_id': context.project_id,
|
|
||||||
'user_id': context.user_id,
|
|
||||||
}
|
|
||||||
target.update(target_obj or {})
|
|
||||||
|
|
||||||
_action = 'message:%s' % action
|
|
||||||
cinder.policy.enforce(context, _action, target)
|
|
||||||
|
|
||||||
|
|
||||||
class MessagesController(wsgi.Controller):
|
class MessagesController(wsgi.Controller):
|
||||||
@ -68,7 +57,7 @@ class MessagesController(wsgi.Controller):
|
|||||||
# Not found exception will be handled at the wsgi level
|
# Not found exception will be handled at the wsgi level
|
||||||
message = self.message_api.get(context, id)
|
message = self.message_api.get(context, id)
|
||||||
|
|
||||||
check_policy(context, 'get', message)
|
context.authorize(policy.GET_POLICY)
|
||||||
|
|
||||||
self._build_user_message(message)
|
self._build_user_message(message)
|
||||||
return self._view_builder.detail(req, message)
|
return self._view_builder.detail(req, message)
|
||||||
@ -80,7 +69,7 @@ class MessagesController(wsgi.Controller):
|
|||||||
|
|
||||||
# Not found exception will be handled at the wsgi level
|
# Not found exception will be handled at the wsgi level
|
||||||
message = self.message_api.get(context, id)
|
message = self.message_api.get(context, id)
|
||||||
check_policy(context, 'delete', message)
|
context.authorize(policy.DELETE_POLICY, target_obj=message)
|
||||||
self.message_api.delete(context, message)
|
self.message_api.delete(context, message)
|
||||||
|
|
||||||
return webob.Response(status_int=http_client.NO_CONTENT)
|
return webob.Response(status_int=http_client.NO_CONTENT)
|
||||||
@ -90,7 +79,7 @@ class MessagesController(wsgi.Controller):
|
|||||||
"""Returns a list of messages, transformed through view builder."""
|
"""Returns a list of messages, transformed through view builder."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
api_version = req.api_version_request
|
api_version = req.api_version_request
|
||||||
check_policy(context, 'get_all')
|
context.authorize(policy.GET_ALL_POLICY)
|
||||||
filters = None
|
filters = None
|
||||||
marker = None
|
marker = None
|
||||||
limit = None
|
limit = None
|
||||||
|
@ -24,6 +24,7 @@ from cinder import exception
|
|||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
from cinder.objects import cleanable
|
from cinder.objects import cleanable
|
||||||
|
from cinder.policies import workers as policy
|
||||||
from cinder.scheduler import rpcapi as sch_rpc
|
from cinder.scheduler import rpcapi as sch_rpc
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
@ -33,8 +34,6 @@ class WorkerController(wsgi.Controller):
|
|||||||
'is_up', 'disabled', 'resource_id', 'resource_type',
|
'is_up', 'disabled', 'resource_id', 'resource_type',
|
||||||
'until'}
|
'until'}
|
||||||
|
|
||||||
policy_checker = wsgi.Controller.get_policy_checker('workers')
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.sch_api = sch_rpc.SchedulerAPI()
|
self.sch_api = sch_rpc.SchedulerAPI()
|
||||||
|
|
||||||
@ -104,7 +103,8 @@ class WorkerController(wsgi.Controller):
|
|||||||
def cleanup(self, req, body=None):
|
def cleanup(self, req, body=None):
|
||||||
"""Do the cleanup on resources from a specific service/host/node."""
|
"""Do the cleanup on resources from a specific service/host/node."""
|
||||||
# Let the wsgi middleware convert NotAuthorized exceptions
|
# Let the wsgi middleware convert NotAuthorized exceptions
|
||||||
ctxt = self.policy_checker(req, 'cleanup')
|
ctxt = req.environ['cinder.context']
|
||||||
|
ctxt.authorize(policy.CLEAN_POLICY)
|
||||||
body = body or {}
|
body = body or {}
|
||||||
|
|
||||||
params = self._prepare_params(ctxt, body, self.allowed_clean_keys)
|
params = self._prepare_params(ctxt, body, self.allowed_clean_keys)
|
||||||
|
@ -17,10 +17,16 @@ import itertools
|
|||||||
|
|
||||||
from cinder.policies import attachments
|
from cinder.policies import attachments
|
||||||
from cinder.policies import base
|
from cinder.policies import base
|
||||||
|
from cinder.policies import clusters
|
||||||
|
from cinder.policies import messages
|
||||||
|
from cinder.policies import workers
|
||||||
|
|
||||||
|
|
||||||
def list_rules():
|
def list_rules():
|
||||||
return itertools.chain(
|
return itertools.chain(
|
||||||
base.list_rules(),
|
base.list_rules(),
|
||||||
attachments.list_rules()
|
attachments.list_rules(),
|
||||||
|
messages.list_rules(),
|
||||||
|
clusters.list_rules(),
|
||||||
|
workers.list_rules()
|
||||||
)
|
)
|
||||||
|
65
cinder/policies/clusters.py
Normal file
65
cinder/policies/clusters.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# 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 cinder.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
GET_POLICY = 'clusters:get'
|
||||||
|
GET_ALL_POLICY = 'clusters:get_all'
|
||||||
|
UPDATE_POLICY = 'clusters:update'
|
||||||
|
|
||||||
|
|
||||||
|
clusters_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=GET_ALL_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="""List clusters.""",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/clusters'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/clusters/detail'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=GET_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="""Show cluster.""",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/clusters/{cluster_id}'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=UPDATE_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="""Update cluster.""",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'PUT',
|
||||||
|
'path': '/clusters/{cluster_id}'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return clusters_policies
|
61
cinder/policies/messages.py
Normal file
61
cinder/policies/messages.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# 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 cinder.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
DELETE_POLICY = 'message:delete'
|
||||||
|
GET_POLICY = 'message:get'
|
||||||
|
GET_ALL_POLICY = 'message:get_all'
|
||||||
|
|
||||||
|
|
||||||
|
messages_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=GET_ALL_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="""List messages.""",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/messages'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=GET_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="""Show message.""",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/messages/{message_id}'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=DELETE_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="""Delete message.""",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'DELETE',
|
||||||
|
'path': '/messages/{message_id}'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return messages_policies
|
39
cinder/policies/workers.py
Normal file
39
cinder/policies/workers.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# 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 cinder.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
CLEAN_POLICY = 'workers:cleanup'
|
||||||
|
|
||||||
|
|
||||||
|
workers_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=CLEAN_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="""Clean up workers.""",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'POST',
|
||||||
|
'path': '/workers/cleanup'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return workers_policies
|
@ -149,13 +149,4 @@
|
|||||||
|
|
||||||
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
||||||
|
|
||||||
"message:delete": "rule:admin_or_owner",
|
|
||||||
"message:get": "rule:admin_or_owner",
|
|
||||||
"message:get_all": "rule:admin_or_owner",
|
|
||||||
|
|
||||||
"clusters:get": "rule:admin_api",
|
|
||||||
"clusters:get_all": "rule:admin_api",
|
|
||||||
"clusters:update": "rule:admin_api",
|
|
||||||
|
|
||||||
"workers:cleanup": "rule:admin_api"
|
|
||||||
}
|
}
|
||||||
|
@ -141,13 +141,5 @@
|
|||||||
"group:list_replication_targets": "rule:admin_or_owner",
|
"group:list_replication_targets": "rule:admin_or_owner",
|
||||||
|
|
||||||
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
||||||
"message:delete": "rule:admin_or_owner",
|
|
||||||
"message:get": "rule:admin_or_owner",
|
|
||||||
"message:get_all": "rule:admin_or_owner",
|
|
||||||
|
|
||||||
"clusters:get": "rule:admin_api",
|
|
||||||
"clusters:get_all": "rule:admin_api",
|
|
||||||
"clusters:update": "rule:admin_api",
|
|
||||||
|
|
||||||
"workers:cleanup": "rule:admin_api"
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user