summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-01-17 17:13:51 +0000
committerGerrit Code Review <review@openstack.org>2012-01-17 17:13:51 +0000
commit820c46021d62a922da753a1bdee2df8b25ed23bc (patch)
tree61121080026955ba477eeb72c820bb15e3f6b018
parent70bf86e13fbdaf5a2deec24993744f8c0e41b4e3 (diff)
parent480875d49c722a2310b52c3bd4b2241598df86c8 (diff)
downloadnova-820c46021d62a922da753a1bdee2df8b25ed23bc.tar.gz
nova-820c46021d62a922da753a1bdee2df8b25ed23bc.tar.xz
nova-820c46021d62a922da753a1bdee2df8b25ed23bc.zip
Merge "Add policy checking to nova.network.api.API"
-rw-r--r--etc/nova/policy.json37
-rw-r--r--nova/exception.py2
-rw-r--r--nova/network/manager.py59
-rw-r--r--nova/tests/fake_network.py9
-rw-r--r--nova/tests/policy.json36
-rw-r--r--nova/tests/test_network.py45
6 files changed, 173 insertions, 15 deletions
diff --git a/etc/nova/policy.json b/etc/nova/policy.json
index 78003d2e3..44bbee65d 100644
--- a/etc/nova/policy.json
+++ b/etc/nova/policy.json
@@ -13,5 +13,40 @@
"volume:get_all": [],
"volume:get_volume_metadata": [],
"volume:get_snapshot": [],
- "volume:get_all_snapshots": []
+ "volume:get_all_snapshots": [],
+
+
+ "network:get_all_networks": [],
+ "network:get_network": [],
+ "network:delete_network": [],
+ "network:disassociate_network": [],
+ "network:get_vifs_by_instance": [],
+ "network:allocate_for_instance": [],
+ "network:deallocate_for_instance": [],
+ "network:validate_networks": [],
+ "network:get_instance_uuids_by_ip_filter": [],
+
+ "network:get_floating_ip": [],
+ "network:get_floating_ip_pools": [],
+ "network:get_floating_ip_by_address": [],
+ "network:get_floating_ips_by_project": [],
+ "network:get_floating_ips_by_fixed_address": [],
+ "network:allocate_floating_ip": [],
+ "network:deallocate_floating_ip": [],
+ "network:associate_floating_ip": [],
+ "network:disassociate_floating_ip": [],
+
+ "network:get_fixed_ip": [],
+ "network:add_fixed_ip_to_instance": [],
+ "network:remove_fixed_ip_from_instance": [],
+ "network:add_network_to_project": [],
+ "network:get_instance_nw_info": [],
+
+ "network:get_dns_zones": [],
+ "network:add_dns_entry": [],
+ "network:modify_dns_entry": [],
+ "network:delete_dns_entry": [],
+ "network:get_dns_entries_by_address": [],
+ "network:get_dns_entries_by_name": []
}
+
diff --git a/nova/exception.py b/nova/exception.py
index 716f86dc1..6e60642f6 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -204,7 +204,7 @@ class AdminRequired(NotAuthorized):
class PolicyNotAuthorized(NotAuthorized):
- message = _("Policy Doesn't allow %(action)s to be performed.")
+ message = _("Policy doesn't allow %(action)s to be performed.")
class Invalid(NovaException):
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 6e4a57a15..4117903ef 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -46,13 +46,15 @@ topologies. All of the network commands are issued to a subclass of
"""
import datetime
+import functools
import itertools
import math
-import netaddr
import random
import re
import socket
+
from eventlet import greenpool
+import netaddr
from nova.compute import api as compute_api
from nova.compute import instance_types
@@ -65,6 +67,7 @@ from nova import log as logging
from nova import manager
from nova.network import api as network_api
from nova.network import model as network_model
+import nova.policy
from nova import quota
from nova import utils
from nova import rpc
@@ -187,6 +190,27 @@ class RPCAllocateFixedIP(object):
return self.allocate_fixed_ip(context, instance_id, network, **kwargs)
+def wrap_check_policy(func):
+ """Check policy corresponding to the wrapped methods prior to execution"""
+
+ @functools.wraps(func)
+ def wrapped(self, context, *args, **kwargs):
+ action = func.__name__
+ check_policy(context, action)
+ return func(self, context, *args, **kwargs)
+
+ return wrapped
+
+
+def check_policy(context, action):
+ target = {
+ 'project_id': context.project_id,
+ 'user_id': context.user_id,
+ }
+ _action = 'network:%s' % action
+ nova.policy.enforce(context, _action, target)
+
+
class FloatingIP(object):
"""Mixin class for adding floating IP functionality to a manager."""
def init_host_floating_ips(self):
@@ -209,6 +233,7 @@ class FloatingIP(object):
self.driver.ensure_floating_forward(floating_ip['address'],
fixed_address)
+ @wrap_check_policy
def allocate_for_instance(self, context, **kwargs):
"""Handles allocating the floating IP resources for an instance.
@@ -245,6 +270,7 @@ class FloatingIP(object):
affect_auto_assigned=True)
return nw_info
+ @wrap_check_policy
def deallocate_for_instance(self, context, **kwargs):
"""Handles deallocating floating IP resources for an instance.
@@ -293,6 +319,7 @@ class FloatingIP(object):
'project': context.project_id})
raise exception.NotAuthorized()
+ @wrap_check_policy
def allocate_floating_ip(self, context, project_id, pool=None):
"""Gets a floating ip from the pool."""
# NOTE(tr3buchet): all network hosts in zone now use the same pool
@@ -308,6 +335,7 @@ class FloatingIP(object):
project_id,
pool)
+ @wrap_check_policy
def deallocate_floating_ip(self, context, address,
affect_auto_assigned=False):
"""Returns an floating ip to the pool."""
@@ -327,8 +355,9 @@ class FloatingIP(object):
self.db.floating_ip_deallocate(context, address)
+ @wrap_check_policy
def associate_floating_ip(self, context, floating_address, fixed_address,
- affect_auto_assigned=False):
+ affect_auto_assigned=False):
"""Associates a floating ip with a fixed ip.
Makes sure everything makes sense then calls _associate_floating_ip,
@@ -384,6 +413,7 @@ class FloatingIP(object):
self.driver.bind_floating_ip(floating_address, interface)
self.driver.ensure_floating_forward(floating_address, fixed_address)
+ @wrap_check_policy
def disassociate_floating_ip(self, context, address,
affect_auto_assigned=False):
"""Disassociates a floating ip from its fixed ip.
@@ -436,50 +466,61 @@ class FloatingIP(object):
self.driver.unbind_floating_ip(address, interface)
self.driver.remove_floating_forward(address, fixed_address)
+ @wrap_check_policy
def get_floating_ip(self, context, id):
"""Returns a floating IP as a dict"""
return dict(self.db.floating_ip_get(context, id).iteritems())
+ @wrap_check_policy
def get_floating_pools(self, context):
"""Returns list of floating pools"""
pools = self.db.floating_ip_get_pools(context)
return [dict(pool.iteritems()) for pool in pools]
+ @wrap_check_policy
def get_floating_ip_by_address(self, context, address):
"""Returns a floating IP as a dict"""
return dict(self.db.floating_ip_get_by_address(context,
address).iteritems())
+ @wrap_check_policy
def get_floating_ips_by_project(self, context):
"""Returns the floating IPs allocated to a project"""
ips = self.db.floating_ip_get_all_by_project(context,
context.project_id)
return [dict(ip.iteritems()) for ip in ips]
+ @wrap_check_policy
def get_floating_ips_by_fixed_address(self, context, fixed_address):
"""Returns the floating IPs associated with a fixed_address"""
floating_ips = self.db.floating_ip_get_by_fixed_address(context,
fixed_address)
return [floating_ip['address'] for floating_ip in floating_ips]
+ @wrap_check_policy
def get_dns_zones(self, context):
return self.floating_dns_manager.get_zones()
+ @wrap_check_policy
def add_dns_entry(self, context, address, dns_name, dns_type, dns_zone):
self.floating_dns_manager.create_entry(dns_name, address,
dns_type, dns_zone)
+ @wrap_check_policy
def modify_dns_entry(self, context, address, dns_name, dns_zone):
self.floating_dns_manager.modify_address(dns_name, address,
dns_zone)
+ @wrap_check_policy
def delete_dns_entry(self, context, dns_name, dns_zone):
self.floating_dns_manager.delete_entry(dns_name, dns_zone)
+ @wrap_check_policy
def get_dns_entries_by_address(self, context, address, dns_zone):
return self.floating_dns_manager.get_entries_by_address(address,
dns_zone)
+ @wrap_check_policy
def get_dns_entries_by_name(self, context, name, dns_zone):
return self.floating_dns_manager.get_entries_by_name(name,
dns_zone)
@@ -588,6 +629,7 @@ class NetworkManager(manager.SchedulerDependentManager):
# floating ips MUST override this or use the Mixin
return []
+ @wrap_check_policy
def get_instance_uuids_by_ip_filter(self, context, filters):
fixed_ip_filter = filters.get('fixed_ip')
ip_filter = re.compile(str(filters.get('ip')))
@@ -663,6 +705,7 @@ class NetworkManager(manager.SchedulerDependentManager):
return [network for network in networks if
not network['vlan']]
+ @wrap_check_policy
def allocate_for_instance(self, context, **kwargs):
"""Handles allocating the various network resources for an instance.
@@ -688,6 +731,7 @@ class NetworkManager(manager.SchedulerDependentManager):
return self.get_instance_nw_info(context, instance_id, instance_uuid,
type_id, host)
+ @wrap_check_policy
def deallocate_for_instance(self, context, **kwargs):
"""Handles deallocating various network resources for an instance.
@@ -709,6 +753,7 @@ class NetworkManager(manager.SchedulerDependentManager):
# deallocate vifs (mac addresses)
self.db.virtual_interface_delete_by_instance(context, instance_id)
+ @wrap_check_policy
def get_instance_nw_info(self, context, instance_id, instance_uuid,
instance_type_id, host):
"""Creates network info list for instance.
@@ -976,11 +1021,13 @@ class NetworkManager(manager.SchedulerDependentManager):
random.randint(0x00, 0xff)]
return ':'.join(map(lambda x: "%02x" % x, mac))
+ @wrap_check_policy
def add_fixed_ip_to_instance(self, context, instance_id, host, network_id):
"""Adds a fixed ip to an instance from specified network."""
networks = [self._get_network_by_id(context, network_id)]
self._allocate_fixed_ips(context, instance_id, host, networks)
+ @wrap_check_policy
def remove_fixed_ip_from_instance(self, context, instance_id, address):
"""Removes a fixed ip from an instance from specified network."""
fixed_ips = self.db.fixed_ip_get_by_instance(context, instance_id)
@@ -1215,6 +1262,7 @@ class NetworkManager(manager.SchedulerDependentManager):
self._create_fixed_ips(context, network['id'])
return networks
+ @wrap_check_policy
def delete_network(self, context, fixed_range, uuid,
require_disassociated=True):
@@ -1270,6 +1318,7 @@ class NetworkManager(manager.SchedulerDependentManager):
"""Sets up network on this host."""
raise NotImplementedError()
+ @wrap_check_policy
def validate_networks(self, context, networks):
"""check if the networks exists and host
is set to each network.
@@ -1304,11 +1353,13 @@ class NetworkManager(manager.SchedulerDependentManager):
def _get_networks_by_uuids(self, context, network_uuids):
return self.db.network_get_all_by_uuids(context, network_uuids)
+ @wrap_check_policy
def get_vifs_by_instance(self, context, instance_id):
"""Returns the vifs associated with an instance"""
vifs = self.db.virtual_interface_get_by_instance(context, instance_id)
return [dict(vif.iteritems()) for vif in vifs]
+ @wrap_check_policy
def get_network(self, context, network_uuid):
networks = self._get_networks_by_uuids(context, [network_uuid])
try:
@@ -1318,14 +1369,17 @@ class NetworkManager(manager.SchedulerDependentManager):
return dict(network.iteritems())
+ @wrap_check_policy
def get_all_networks(self, context):
networks = self.db.network_get_all(context)
return [dict(network.iteritems()) for network in networks]
+ @wrap_check_policy
def disassociate_network(self, context, network_uuid):
network = self.get_network(context, network_uuid)
self.db.network_disassociate(context, network['id'])
+ @wrap_check_policy
def get_fixed_ip(self, context, id):
"""Return a fixed ip"""
fixed = self.db.fixed_ip_get(context, id)
@@ -1494,6 +1548,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
self._setup_network(context, network)
return address
+ @wrap_check_policy
def add_network_to_project(self, context, project_id):
"""Force adds another network to a project."""
self.db.network_associate(context, project_id, force=True)
diff --git a/nova/tests/fake_network.py b/nova/tests/fake_network.py
index 071990bd6..29bb793ce 100644
--- a/nova/tests/fake_network.py
+++ b/nova/tests/fake_network.py
@@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import nova.context
from nova import db
from nova import exception
from nova import flags
@@ -295,11 +296,9 @@ def fake_get_instance_nw_info(stubs, num_networks=1, ips_per_vif=2,
stubs.Set(db, 'network_get', network_get_fake)
stubs.Set(db, 'instance_info_cache_update', update_cache_fake)
- class FakeContext(object):
- def __init__(self):
- self.project_id = 1
-
- return network.get_instance_nw_info(FakeContext(), 0, 0, 0, None)
+ context = nova.context.RequestContext('testuser', 'testproject',
+ is_admin=False)
+ return network.get_instance_nw_info(context, 0, 0, 0, None)
def stub_out_nw_api_get_instance_nw_info(stubs, func=None):
diff --git a/nova/tests/policy.json b/nova/tests/policy.json
index c96908fff..a12a84ab1 100644
--- a/nova/tests/policy.json
+++ b/nova/tests/policy.json
@@ -88,5 +88,39 @@
"volume:create_snapshot": [],
"volume:delete_snapshot": [],
"volume:get_snapshot": [],
- "volume:get_all_snapshots": []
+ "volume:get_all_snapshots": [],
+
+
+ "network:get_all_networks": [],
+ "network:get_network": [],
+ "network:delete_network": [],
+ "network:disassociate_network": [],
+ "network:get_vifs_by_instance": [],
+ "network:allocate_for_instance": [],
+ "network:deallocate_for_instance": [],
+ "network:validate_networks": [],
+ "network:get_instance_uuids_by_ip_filter": [],
+
+ "network:get_floating_ip": [],
+ "network:get_floating_ip_pools": [],
+ "network:get_floating_ip_by_address": [],
+ "network:get_floating_ips_by_project": [],
+ "network:get_floating_ips_by_fixed_address": [],
+ "network:allocate_floating_ip": [],
+ "network:deallocate_floating_ip": [],
+ "network:associate_floating_ip": [],
+ "network:disassociate_floating_ip": [],
+
+ "network:get_fixed_ip": [],
+ "network:add_fixed_ip_to_instance": [],
+ "network:remove_fixed_ip_from_instance": [],
+ "network:add_network_to_project": [],
+ "network:get_instance_nw_info": [],
+
+ "network:get_dns_zones": [],
+ "network:add_dns_entry": [],
+ "network:modify_dns_entry": [],
+ "network:delete_dns_entry": [],
+ "network:get_dns_entries_by_address": [],
+ "network:get_dns_entries_by_name": []
}
diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py
index 8f8efc991..8b230376b 100644
--- a/nova/tests/test_network.py
+++ b/nova/tests/test_network.py
@@ -22,6 +22,7 @@ from nova import db
from nova import exception
from nova import flags
from nova import log as logging
+import nova.policy
from nova import rpc
from nova import test
from nova import utils
@@ -230,7 +231,7 @@ class FlatNetworkTestCase(test.TestCase):
self.mox.ReplayAll()
self.assertRaises(exception.FixedIpInvalid,
- self.network.validate_networks, None,
+ self.network.validate_networks, self.context,
requested_networks)
def test_validate_networks_empty_fixed_ip(self):
@@ -243,7 +244,7 @@ class FlatNetworkTestCase(test.TestCase):
self.assertRaises(exception.FixedIpInvalid,
self.network.validate_networks,
- None, requested_networks)
+ self.context, requested_networks)
def test_validate_networks_none_fixed_ip(self):
self.mox.StubOutWithMock(db, 'network_get_all_by_uuids')
@@ -253,7 +254,7 @@ class FlatNetworkTestCase(test.TestCase):
mox.IgnoreArg()).AndReturn(networks)
self.mox.ReplayAll()
- self.network.validate_networks(None, requested_networks)
+ self.network.validate_networks(self.context, requested_networks)
def test_add_fixed_ip_instance_without_vpn_requested_networks(self):
self.mox.StubOutWithMock(db, 'network_get')
@@ -813,12 +814,17 @@ class VlanNetworkTestCase(test.TestCase):
class CommonNetworkTestCase(test.TestCase):
+
+ def setUp(self):
+ super(CommonNetworkTestCase, self).setUp()
+ self.context = context.RequestContext('fake', 'fake')
+
def fake_create_fixed_ips(self, context, network_id):
return None
def test_remove_fixed_ip_from_instance(self):
manager = fake_network.FakeNetworkManager()
- manager.remove_fixed_ip_from_instance(None, 99, '10.0.0.1')
+ manager.remove_fixed_ip_from_instance(self.context, 99, '10.0.0.1')
self.assertEquals(manager.deallocate_called, '10.0.0.1')
@@ -826,7 +832,7 @@ class CommonNetworkTestCase(test.TestCase):
manager = fake_network.FakeNetworkManager()
self.assertRaises(exception.FixedIpNotFoundForSpecificInstance,
manager.remove_fixed_ip_from_instance,
- None, 99, 'bad input')
+ self.context, 99, 'bad input')
def test_validate_cidrs(self):
manager = fake_network.FakeNetworkManager()
@@ -1320,3 +1326,32 @@ class FloatingIPTestCase(test.TestCase):
self.assertRaises(exception.NotFound,
self.network.delete_dns_entry, self.context,
name1, zone)
+
+
+class NetworkPolicyTestCase(test.TestCase):
+ def setUp(self):
+ super(NetworkPolicyTestCase, self).setUp()
+
+ nova.policy.reset()
+ nova.policy.init()
+
+ self.context = context.get_admin_context()
+
+ def tearDown(self):
+ super(NetworkPolicyTestCase, self).tearDown()
+ nova.policy.reset()
+
+ def _set_rules(self, rules):
+ nova.common.policy.set_brain(nova.common.policy.HttpBrain(rules))
+
+ def test_check_policy(self):
+ self.mox.StubOutWithMock(nova.policy, 'enforce')
+ target = {
+ 'project_id': self.context.project_id,
+ 'user_id': self.context.user_id,
+ }
+ nova.policy.enforce(self.context, 'network:get_all', target)
+ self.mox.ReplayAll()
+ network_manager.check_policy(self.context, 'get_all')
+ self.mox.UnsetStubs()
+ self.mox.VerifyAll()