Merge "Remove calls to policy.enforce from plugin and db logic"
This commit is contained in:
commit
1957375800
@ -12,7 +12,6 @@
|
||||
"extension:provider_network:set": "rule:admin_only",
|
||||
|
||||
"extension:router:view": "rule:regular_user",
|
||||
"extension:router:set": "rule:admin_only",
|
||||
|
||||
"extension:port_binding:view": "rule:admin_only",
|
||||
"extension:port_binding:set": "rule:admin_only",
|
||||
@ -31,7 +30,13 @@
|
||||
"get_network": "rule:admin_or_owner or rule:shared or rule:external",
|
||||
"create_network:shared": "rule:admin_only",
|
||||
"create_network:router:external": "rule:admin_only",
|
||||
"create_network:provider:network_type": "rule:admin_only",
|
||||
"create_network:provider:physical_network": "rule:admin_only",
|
||||
"create_network:provider:segmentation_id": "rule:admin_only",
|
||||
"update_network": "rule:admin_or_owner",
|
||||
"update_network:provider:network_type": "rule:admin_only",
|
||||
"update_network:provider:physical_network": "rule:admin_only",
|
||||
"update_network:provider:segmentation_id": "rule:admin_only",
|
||||
"delete_network": "rule:admin_or_owner",
|
||||
|
||||
"create_port": "",
|
||||
|
@ -36,7 +36,6 @@ from quantum.openstack.common.notifier import api as notifier_api
|
||||
from quantum.openstack.common import uuidutils
|
||||
from quantum import policy
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -770,11 +769,6 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
|
||||
"extension:router:view",
|
||||
network)
|
||||
|
||||
def _enforce_l3_set_auth(self, context, network):
|
||||
return policy.enforce(context,
|
||||
"extension:router:set",
|
||||
network)
|
||||
|
||||
def _network_is_external(self, context, net_id):
|
||||
try:
|
||||
context.session.query(ExternalNetwork).filter_by(
|
||||
@ -795,8 +789,6 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
|
||||
if not external_set:
|
||||
return
|
||||
|
||||
self._enforce_l3_set_auth(context, net_data)
|
||||
|
||||
if external:
|
||||
# expects to be called within a plugin's session
|
||||
context.session.add(ExternalNetwork(network_id=net_id))
|
||||
@ -807,7 +799,6 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
|
||||
if not attributes.is_attr_set(new_value):
|
||||
return
|
||||
|
||||
self._enforce_l3_set_auth(context, net_data)
|
||||
existing_value = self._network_is_external(context, net_id)
|
||||
|
||||
if existing_value == new_value:
|
||||
|
@ -27,12 +27,15 @@ EXTENDED_ATTRIBUTES_2_0 = {
|
||||
NETWORK_TYPE: {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string': None},
|
||||
'default': attributes.ATTR_NOT_SPECIFIED,
|
||||
'enforce_policy': True,
|
||||
'is_visible': True},
|
||||
PHYSICAL_NETWORK: {'allow_post': True, 'allow_put': True,
|
||||
'default': attributes.ATTR_NOT_SPECIFIED,
|
||||
'enforce_policy': True,
|
||||
'is_visible': True},
|
||||
SEGMENTATION_ID: {'allow_post': True, 'allow_put': True,
|
||||
'convert_to': int,
|
||||
'enforce_policy': True,
|
||||
'default': attributes.ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True},
|
||||
}
|
||||
|
@ -204,3 +204,9 @@ class Servicetype(extensions.ExtensionDescriptor):
|
||||
return [extensions.ResourceExtension(COLLECTION_NAME,
|
||||
controller,
|
||||
attr_map=attr_map)]
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return dict(RESOURCE_ATTRIBUTE_MAP.items())
|
||||
else:
|
||||
return {}
|
||||
|
@ -738,7 +738,6 @@ class RuleCheck(Check):
|
||||
class RoleCheck(Check):
|
||||
def __call__(self, target, creds):
|
||||
"""Check that there is a matching role in the cred dict."""
|
||||
|
||||
return self.match.lower() in [x.lower() for x in creds['roles']]
|
||||
|
||||
|
||||
|
@ -1234,9 +1234,6 @@ class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
def _check_view_auth(self, context, resource, action):
|
||||
return policy.check(context, action, resource)
|
||||
|
||||
def _enforce_set_auth(self, context, resource, action):
|
||||
policy.enforce(context, action, resource)
|
||||
|
||||
def _extend_port_dict_binding(self, context, port):
|
||||
if self._check_view_auth(context, port, self.binding_view):
|
||||
port[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_OVS
|
||||
|
@ -195,9 +195,6 @@ class HyperVQuantumPlugin(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
def _check_view_auth(self, context, resource, action):
|
||||
return policy.check(context, action, resource)
|
||||
|
||||
def _enforce_set_auth(self, context, resource, action):
|
||||
policy.enforce(context, action, resource)
|
||||
|
||||
def _parse_network_vlan_ranges(self):
|
||||
self._network_vlan_ranges = {}
|
||||
for entry in cfg.CONF.HYPERV.network_vlan_ranges:
|
||||
@ -256,9 +253,6 @@ class HyperVQuantumPlugin(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
# Provider specific network creation
|
||||
p.create_network(session, attrs)
|
||||
|
||||
if network_type_set:
|
||||
self._enforce_set_auth(context, attrs, self.network_set)
|
||||
|
||||
def create_network(self, context, network):
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
@ -310,8 +304,6 @@ class HyperVQuantumPlugin(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
def update_network(self, context, id, network):
|
||||
network_attrs = network['network']
|
||||
self._check_provider_update(context, network_attrs)
|
||||
# Authorize before exposing plugin details to client
|
||||
self._enforce_set_auth(context, network_attrs, self.network_set)
|
||||
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
|
@ -271,9 +271,6 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
def _check_view_auth(self, context, resource, action):
|
||||
return policy.check(context, action, resource)
|
||||
|
||||
def _enforce_set_auth(self, context, resource, action):
|
||||
policy.enforce(context, action, resource)
|
||||
|
||||
def _add_network_vlan_range(self, physical_network, vlan_min, vlan_max):
|
||||
self._add_network(physical_network)
|
||||
self.network_vlan_ranges[physical_network].append((vlan_min, vlan_max))
|
||||
@ -314,9 +311,6 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
segmentation_id_set):
|
||||
return (None, None, None)
|
||||
|
||||
# Authorize before exposing plugin details to client
|
||||
self._enforce_set_auth(context, attrs, self.network_set)
|
||||
|
||||
if not network_type_set:
|
||||
msg = _("provider:network_type required")
|
||||
raise q_exc.InvalidInput(error_message=msg)
|
||||
@ -378,9 +372,6 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
segmentation_id_set):
|
||||
return
|
||||
|
||||
# Authorize before exposing plugin details to client
|
||||
self._enforce_set_auth(context, attrs, self.network_set)
|
||||
|
||||
msg = _("Plugin does not support updating provider attributes")
|
||||
raise q_exc.InvalidInput(error_message=msg)
|
||||
|
||||
|
@ -133,9 +133,6 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
|
||||
def _check_view_auth(self, context, resource, action):
|
||||
return policy.check(context, action, resource)
|
||||
|
||||
def _enforce_set_auth(self, context, resource, action):
|
||||
policy.enforce(context, action, resource)
|
||||
|
||||
def _update_resource_status(self, context, resource, id, status):
|
||||
"""Update status of specified resource."""
|
||||
request = {}
|
||||
|
@ -142,8 +142,6 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
novazone_cluster_map = {}
|
||||
|
||||
provider_network_view = "extension:provider_network:view"
|
||||
provider_network_set = "extension:provider_network:set"
|
||||
port_security_enabled_create = "create_port:port_security_enabled"
|
||||
port_security_enabled_update = "update_port:port_security_enabled"
|
||||
|
||||
def __init__(self, loglevel=None):
|
||||
@ -664,9 +662,6 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
def _check_view_auth(self, context, resource, action):
|
||||
return policy.check(context, action, resource)
|
||||
|
||||
def _enforce_set_auth(self, context, resource, action):
|
||||
return policy.enforce(context, action, resource)
|
||||
|
||||
def _handle_provider_create(self, context, attrs):
|
||||
# NOTE(salvatore-orlando): This method has been borrowed from
|
||||
# the OpenvSwtich plugin, altough changed to match NVP specifics.
|
||||
@ -680,8 +675,6 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
segmentation_id_set):
|
||||
return
|
||||
|
||||
# Authorize before exposing plugin details to client
|
||||
self._enforce_set_auth(context, attrs, self.provider_network_set)
|
||||
err_msg = None
|
||||
if not network_type_set:
|
||||
err_msg = _("%s required") % pnet.NETWORK_TYPE
|
||||
@ -1146,10 +1139,6 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
# pass the value to the policy engine when the port is
|
||||
# ATTR_NOT_SPECIFIED is for the case where a port is created on a
|
||||
# shared network that is not owned by the tenant.
|
||||
# TODO(arosen) fix policy engine to do this for us automatically.
|
||||
if attr.is_attr_set(port['port'].get(psec.PORTSECURITY)):
|
||||
self._enforce_set_auth(context, port,
|
||||
self.port_security_enabled_create)
|
||||
port_data = port['port']
|
||||
notify_dhcp_agent = False
|
||||
with context.session.begin(subtransactions=True):
|
||||
@ -1215,9 +1204,6 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
return port_data
|
||||
|
||||
def update_port(self, context, id, port):
|
||||
if attr.is_attr_set(port['port'].get(psec.PORTSECURITY)):
|
||||
self._enforce_set_auth(context, port,
|
||||
self.port_security_enabled_update)
|
||||
delete_security_groups = self._check_update_deletes_security_groups(
|
||||
port)
|
||||
has_security_groups = self._check_update_has_security_groups(port)
|
||||
@ -2035,8 +2021,6 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
|
||||
def create_qos_queue(self, context, qos_queue, check_policy=True):
|
||||
q = qos_queue.get('qos_queue')
|
||||
if check_policy:
|
||||
self._enforce_set_auth(context, q, ext_qos.qos_queue_create)
|
||||
self._validate_qos_queue(context, q)
|
||||
q['id'] = nvplib.create_lqueue(self.cluster,
|
||||
self._nvp_lqueue(q))
|
||||
|
@ -179,7 +179,8 @@ class Nvp_qos(object):
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return EXTENDED_ATTRIBUTES_2_0
|
||||
return dict(EXTENDED_ATTRIBUTES_2_0.items() +
|
||||
RESOURCE_ATTRIBUTE_MAP.items())
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
@ -344,9 +344,6 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
def _check_view_auth(self, context, resource, action):
|
||||
return policy.check(context, action, resource)
|
||||
|
||||
def _enforce_set_auth(self, context, resource, action):
|
||||
policy.enforce(context, action, resource)
|
||||
|
||||
def _extend_network_dict_provider(self, context, network):
|
||||
if self._check_view_auth(context, network, self.network_view):
|
||||
binding = ovs_db_v2.get_network_binding(context.session,
|
||||
@ -378,9 +375,6 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
segmentation_id_set):
|
||||
return (None, None, None)
|
||||
|
||||
# Authorize before exposing plugin details to client
|
||||
self._enforce_set_auth(context, attrs, self.network_set)
|
||||
|
||||
if not network_type_set:
|
||||
msg = _("provider:network_type required")
|
||||
raise q_exc.InvalidInput(error_message=msg)
|
||||
@ -455,9 +449,6 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
segmentation_id_set):
|
||||
return
|
||||
|
||||
# Authorize before exposing plugin details to client
|
||||
self._enforce_set_auth(context, attrs, self.network_set)
|
||||
|
||||
msg = _("Plugin does not support updating provider attributes")
|
||||
raise q_exc.InvalidInput(error_message=msg)
|
||||
|
||||
|
157
quantum/tests/unit/test_extension_pnet.py
Normal file
157
quantum/tests/unit/test_extension_pnet.py
Normal file
@ -0,0 +1,157 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2013 VMware
|
||||
# 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.
|
||||
#
|
||||
# @author: Salvatore Orlando, VMware
|
||||
#
|
||||
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
from webob import exc as web_exc
|
||||
import webtest
|
||||
|
||||
from quantum.api import extensions
|
||||
from quantum.api.v2 import attributes
|
||||
from quantum.api.v2 import router
|
||||
from quantum import context
|
||||
from quantum.extensions import providernet as pnet
|
||||
from quantum.manager import QuantumManager
|
||||
from quantum.openstack.common import uuidutils
|
||||
from quantum.tests.unit import test_api_v2
|
||||
from quantum.tests.unit import test_extensions
|
||||
from quantum.tests.unit import testlib_api
|
||||
|
||||
|
||||
class ProviderExtensionManager(object):
|
||||
|
||||
def get_resources(self):
|
||||
return []
|
||||
|
||||
def get_actions(self):
|
||||
return []
|
||||
|
||||
def get_request_extensions(self):
|
||||
return []
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
return pnet.get_extended_resources(version)
|
||||
|
||||
|
||||
class ProvidernetExtensionTestCase(testlib_api.WebTestCase):
|
||||
fmt = 'json'
|
||||
|
||||
def setUp(self):
|
||||
super(ProvidernetExtensionTestCase, self).setUp()
|
||||
|
||||
plugin = 'quantum.quantum_plugin_base_v2.QuantumPluginBaseV2'
|
||||
# Ensure 'stale' patched copies of the plugin are never returned
|
||||
QuantumManager._instance = None
|
||||
|
||||
# Ensure existing ExtensionManager is not used
|
||||
extensions.PluginAwareExtensionManager._instance = None
|
||||
|
||||
# Save the global RESOURCE_ATTRIBUTE_MAP
|
||||
self.saved_attr_map = {}
|
||||
for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.iteritems():
|
||||
self.saved_attr_map[resource] = attrs.copy()
|
||||
|
||||
# Update the plugin and extensions path
|
||||
cfg.CONF.set_override('core_plugin', plugin)
|
||||
cfg.CONF.set_override('allow_pagination', True)
|
||||
cfg.CONF.set_override('allow_sorting', True)
|
||||
cfg.CONF.set_override('quota_network', -1, group='QUOTAS')
|
||||
self._plugin_patcher = mock.patch(plugin, autospec=True)
|
||||
self.plugin = self._plugin_patcher.start()
|
||||
# Instantiate mock plugin and enable the 'provider' extension
|
||||
QuantumManager.get_plugin().supported_extension_aliases = (
|
||||
["provider"])
|
||||
ext_mgr = ProviderExtensionManager()
|
||||
self.ext_mdw = test_extensions.setup_extensions_middleware(ext_mgr)
|
||||
self.addCleanup(self._plugin_patcher.stop)
|
||||
self.addCleanup(cfg.CONF.reset)
|
||||
self.addCleanup(self._restore_attribute_map)
|
||||
self.api = webtest.TestApp(router.APIRouter())
|
||||
|
||||
def _restore_attribute_map(self):
|
||||
# Restore the global RESOURCE_ATTRIBUTE_MAP
|
||||
attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
|
||||
|
||||
def _prepare_net_data(self):
|
||||
return {'name': 'net1',
|
||||
pnet.NETWORK_TYPE: 'sometype',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet',
|
||||
pnet.SEGMENTATION_ID: 666}
|
||||
|
||||
def _put_network_with_provider_attrs(self, ctx, expect_errors=False):
|
||||
data = self._prepare_net_data()
|
||||
env = {'quantum.context': ctx}
|
||||
instance = self.plugin.return_value
|
||||
instance.get_network.return_value = {'tenant_id': ctx.tenant_id,
|
||||
'shared': False}
|
||||
net_id = uuidutils.generate_uuid()
|
||||
res = self.api.put(test_api_v2._get_path('networks',
|
||||
id=net_id,
|
||||
fmt=self.fmt),
|
||||
self.serialize({'network': data}),
|
||||
extra_environ=env,
|
||||
expect_errors=expect_errors)
|
||||
return res, data, net_id
|
||||
|
||||
def _post_network_with_provider_attrs(self, ctx, expect_errors=False):
|
||||
data = self._prepare_net_data()
|
||||
env = {'quantum.context': ctx}
|
||||
res = self.api.post(test_api_v2._get_path('networks', fmt=self.fmt),
|
||||
self.serialize({'network': data}),
|
||||
content_type='application/' + self.fmt,
|
||||
extra_environ=env,
|
||||
expect_errors=expect_errors)
|
||||
return res, data
|
||||
|
||||
def test_network_create_with_provider_attrs(self):
|
||||
ctx = context.get_admin_context()
|
||||
ctx.tenant_id = 'an_admin'
|
||||
res, data = self._post_network_with_provider_attrs(ctx)
|
||||
instance = self.plugin.return_value
|
||||
exp_input = {'network': data}
|
||||
exp_input['network'].update({'admin_state_up': True,
|
||||
'tenant_id': 'an_admin',
|
||||
'shared': False})
|
||||
instance.create_network.assert_called_with(mock.ANY,
|
||||
network=exp_input)
|
||||
self.assertEqual(res.status_int, web_exc.HTTPCreated.code)
|
||||
|
||||
def test_network_update_with_provider_attrs(self):
|
||||
ctx = context.get_admin_context()
|
||||
ctx.tenant_id = 'an_admin'
|
||||
res, data, net_id = self._put_network_with_provider_attrs(ctx)
|
||||
instance = self.plugin.return_value
|
||||
exp_input = {'network': data}
|
||||
instance.update_network.assert_called_with(mock.ANY,
|
||||
net_id,
|
||||
network=exp_input)
|
||||
self.assertEqual(res.status_int, web_exc.HTTPOk.code)
|
||||
|
||||
def test_network_create_with_provider_attrs_noadmin_returns_403(self):
|
||||
tenant_id = 'no_admin'
|
||||
ctx = context.Context('', tenant_id, is_admin=False)
|
||||
res, _1 = self._post_network_with_provider_attrs(ctx, True)
|
||||
self.assertEqual(res.status_int, web_exc.HTTPForbidden.code)
|
||||
|
||||
def test_network_update_with_provider_attrs_noadmin_returns_404(self):
|
||||
tenant_id = 'no_admin'
|
||||
ctx = context.Context('', tenant_id, is_admin=False)
|
||||
res, _1, _2 = self._put_network_with_provider_attrs(ctx, True)
|
||||
self.assertEqual(res.status_int, web_exc.HTTPNotFound.code)
|
Loading…
Reference in New Issue
Block a user