remove unused nwfilter methods and tests.
remove unused methods and classes in nova/virt/libvirt/firewall.py and releative function tests. now,nova use nwfilter offered by libvirt only for anti ARP and IP spoofing.other security policy use iptables. Change-Id: Ib9866802ef64668e2feba09124bdf7c7fee92f92
This commit is contained in:
@@ -168,6 +168,7 @@ Vladimir Popovski <vladimir@zadarastorage.com>
|
||||
William Henry <whenry@redhat.com>
|
||||
William Kelly <william.kelly@rackspace.com>
|
||||
William Wolf <throughnothing@gmail.com>
|
||||
Yaguang Tang <heut2008@gmail.com>
|
||||
Yoshiaki Tamura <yoshi@midokura.jp>
|
||||
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
||||
Yun Mao <yunmao@gmail.com>
|
||||
|
||||
@@ -1631,28 +1631,6 @@ class NWFilterTestCase(test.TestCase):
|
||||
security_group = db.security_group_get_by_name(self.context,
|
||||
'fake',
|
||||
'testgroup')
|
||||
|
||||
xml = self.fw.security_group_to_nwfilter_xml(security_group.id)
|
||||
|
||||
dom = xml_to_dom(xml)
|
||||
self.assertEqual(dom.firstChild.tagName, 'filter')
|
||||
|
||||
rules = dom.getElementsByTagName('rule')
|
||||
self.assertEqual(len(rules), 1)
|
||||
|
||||
# It's supposed to allow inbound traffic.
|
||||
self.assertEqual(rules[0].getAttribute('action'), 'accept')
|
||||
self.assertEqual(rules[0].getAttribute('direction'), 'in')
|
||||
|
||||
# Must be lower priority than the base filter (which blocks everything)
|
||||
self.assertTrue(int(rules[0].getAttribute('priority')) < 1000)
|
||||
|
||||
ip_conditions = rules[0].getElementsByTagName('tcp')
|
||||
self.assertEqual(len(ip_conditions), 1)
|
||||
self.assertEqual(ip_conditions[0].getAttribute('srcipaddr'), '0.0.0.0')
|
||||
self.assertEqual(ip_conditions[0].getAttribute('srcipmask'), '0.0.0.0')
|
||||
self.assertEqual(ip_conditions[0].getAttribute('dstportstart'), '80')
|
||||
self.assertEqual(ip_conditions[0].getAttribute('dstportend'), '81')
|
||||
self.teardown_security_group()
|
||||
|
||||
def teardown_security_group(self):
|
||||
@@ -1732,8 +1710,7 @@ class NWFilterTestCase(test.TestCase):
|
||||
def _ensure_all_called(mac):
|
||||
instance_filter = 'nova-instance-%s-%s' % (instance_ref['name'],
|
||||
mac.translate(None, ':'))
|
||||
secgroup_filter = 'nova-secgroup-%s' % self.security_group['id']
|
||||
for required in [secgroup_filter, 'allow-dhcp-server',
|
||||
for required in ['allow-dhcp-server',
|
||||
'no-arp-spoofing', 'no-ip-spoofing',
|
||||
'no-mac-spoofing']:
|
||||
self.assertTrue(required in
|
||||
@@ -1754,20 +1731,10 @@ class NWFilterTestCase(test.TestCase):
|
||||
mac = network_info[0][1]['mac']
|
||||
|
||||
self.fw.setup_basic_filtering(instance, network_info)
|
||||
self.fw.prepare_instance_filter(instance, network_info)
|
||||
self.fw.apply_instance_filter(instance, network_info)
|
||||
_ensure_all_called(mac)
|
||||
self.teardown_security_group()
|
||||
db.instance_destroy(context.get_admin_context(), instance_ref['id'])
|
||||
|
||||
def test_create_network_filters(self):
|
||||
instance_ref = self._create_instance()
|
||||
network_info = _fake_network_info(self.stubs, 3)
|
||||
result = self.fw._create_network_filters(instance_ref,
|
||||
network_info,
|
||||
"fake")
|
||||
self.assertEquals(len(result), 3)
|
||||
|
||||
def test_unfilter_instance_undefines_nwfilters(self):
|
||||
admin_ctxt = context.get_admin_context()
|
||||
|
||||
@@ -1788,13 +1755,9 @@ class NWFilterTestCase(test.TestCase):
|
||||
|
||||
network_info = _fake_network_info(self.stubs, 1)
|
||||
self.fw.setup_basic_filtering(instance, network_info)
|
||||
self.fw.prepare_instance_filter(instance, network_info)
|
||||
self.fw.apply_instance_filter(instance, network_info)
|
||||
original_filter_count = len(fakefilter.filters)
|
||||
self.fw.unfilter_instance(instance, network_info)
|
||||
|
||||
# should undefine 2 filters: instance and instance-secgroup
|
||||
self.assertEqual(original_filter_count - len(fakefilter.filters), 2)
|
||||
self.assertEqual(original_filter_count - len(fakefilter.filters), 1)
|
||||
|
||||
db.instance_destroy(admin_ctxt, instance_ref['id'])
|
||||
|
||||
|
||||
@@ -45,48 +45,11 @@ except ImportError:
|
||||
|
||||
class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
"""
|
||||
This class implements a network filtering mechanism versatile
|
||||
enough for EC2 style Security Group filtering by leveraging
|
||||
This class implements a network filtering mechanism by using
|
||||
libvirt's nwfilter.
|
||||
|
||||
First, all instances get a filter ("nova-base-filter") applied.
|
||||
This filter provides some basic security such as protection against
|
||||
MAC spoofing, IP spoofing, and ARP spoofing.
|
||||
|
||||
This filter drops all incoming ipv4 and ipv6 connections.
|
||||
Outgoing connections are never blocked.
|
||||
|
||||
Second, every security group maps to a nwfilter filter(*).
|
||||
NWFilters can be updated at runtime and changes are applied
|
||||
immediately, so changes to security groups can be applied at
|
||||
runtime (as mandated by the spec).
|
||||
|
||||
Security group rules are named "nova-secgroup-<id>" where <id>
|
||||
is the internal id of the security group. They're applied only on
|
||||
hosts that have instances in the security group in question.
|
||||
|
||||
Updates to security groups are done by updating the data model
|
||||
(in response to API calls) followed by a request sent to all
|
||||
the nodes with instances in the security group to refresh the
|
||||
security group.
|
||||
|
||||
Each instance has its own NWFilter, which references the above
|
||||
mentioned security group NWFilters. This was done because
|
||||
interfaces can only reference one filter while filters can
|
||||
reference multiple other filters. This has the added benefit of
|
||||
actually being able to add and remove security groups from an
|
||||
instance at run time. This functionality is not exposed anywhere,
|
||||
though.
|
||||
|
||||
Outstanding questions:
|
||||
|
||||
The name is unique, so would there be any good reason to sync
|
||||
the uuid across the nodes (by assigning it from the datamodel)?
|
||||
|
||||
|
||||
(*) This sentence brought to you by the redundancy department of
|
||||
redundancy.
|
||||
|
||||
all instances get a filter ("nova-base") applied. This filter
|
||||
provides some basic security such as protection against MAC
|
||||
spoofing, IP spoofing, and ARP spoofing.
|
||||
"""
|
||||
|
||||
def __init__(self, get_connection, **kwargs):
|
||||
@@ -125,16 +88,6 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
</rule>
|
||||
</filter>'''
|
||||
|
||||
@staticmethod
|
||||
def nova_ra_filter():
|
||||
return '''<filter name='nova-allow-ra-server' chain='root'>
|
||||
<uuid>d707fa71-4fb5-4b27-9ab7-ba5ca19c8804</uuid>
|
||||
<rule action='accept' direction='inout'
|
||||
priority='100'>
|
||||
<icmpv6 srcipaddr='$RASERVER'/>
|
||||
</rule>
|
||||
</filter>'''
|
||||
|
||||
def setup_basic_filtering(self, instance, network_info):
|
||||
"""Set up basic filtering (MAC, IP, and ARP spoofing protection)"""
|
||||
LOG.info(_('Called setup_basic_filtering in nwfilter'),
|
||||
@@ -177,14 +130,7 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
'allow-dhcp-server']))
|
||||
self._define_filter(self._filter_container('nova-vpn',
|
||||
['allow-dhcp-server']))
|
||||
self._define_filter(self.nova_base_ipv4_filter)
|
||||
self._define_filter(self.nova_base_ipv6_filter)
|
||||
self._define_filter(self.nova_dhcp_filter)
|
||||
self._define_filter(self.nova_ra_filter)
|
||||
if FLAGS.allow_same_net_traffic:
|
||||
self._define_filter(self.nova_project_filter)
|
||||
if FLAGS.use_ipv6:
|
||||
self._define_filter(self.nova_project_filter_v6)
|
||||
|
||||
self.static_filters_configured = True
|
||||
|
||||
@@ -194,54 +140,6 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
''.join(["<filterref filter='%s'/>" % (f,) for f in filters]))
|
||||
return xml
|
||||
|
||||
@staticmethod
|
||||
def nova_base_ipv4_filter():
|
||||
retval = "<filter name='nova-base-ipv4' chain='ipv4'>"
|
||||
for protocol in ['tcp', 'udp', 'icmp']:
|
||||
for direction, action, priority in [('out', 'accept', 399),
|
||||
('in', 'drop', 400)]:
|
||||
retval += """<rule action='%s' direction='%s' priority='%d'>
|
||||
<%s />
|
||||
</rule>""" % (action, direction,
|
||||
priority, protocol)
|
||||
retval += '</filter>'
|
||||
return retval
|
||||
|
||||
@staticmethod
|
||||
def nova_base_ipv6_filter():
|
||||
retval = "<filter name='nova-base-ipv6' chain='ipv6'>"
|
||||
for protocol in ['tcp-ipv6', 'udp-ipv6', 'icmpv6']:
|
||||
for direction, action, priority in [('out', 'accept', 399),
|
||||
('in', 'drop', 400)]:
|
||||
retval += """<rule action='%s' direction='%s' priority='%d'>
|
||||
<%s />
|
||||
</rule>""" % (action, direction,
|
||||
priority, protocol)
|
||||
retval += '</filter>'
|
||||
return retval
|
||||
|
||||
@staticmethod
|
||||
def nova_project_filter():
|
||||
retval = "<filter name='nova-project' chain='ipv4'>"
|
||||
for protocol in ['tcp', 'udp', 'icmp']:
|
||||
retval += """<rule action='accept' direction='in' priority='200'>
|
||||
<%s srcipaddr='$PROJNET' srcipmask='$PROJMASK' />
|
||||
</rule>""" % protocol
|
||||
retval += '</filter>'
|
||||
return retval
|
||||
|
||||
@staticmethod
|
||||
def nova_project_filter_v6():
|
||||
retval = "<filter name='nova-project-v6' chain='ipv6'>"
|
||||
for protocol in ['tcp-ipv6', 'udp-ipv6', 'icmpv6']:
|
||||
retval += """<rule action='accept' direction='inout'
|
||||
priority='200'>
|
||||
<%s srcipaddr='$PROJNETV6'
|
||||
srcipmask='$PROJMASKV6' />
|
||||
</rule>""" % (protocol)
|
||||
retval += '</filter>'
|
||||
return retval
|
||||
|
||||
def _define_filter(self, xml):
|
||||
if callable(xml):
|
||||
xml = xml()
|
||||
@@ -263,61 +161,6 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
'is not found.') % locals(),
|
||||
instance=instance)
|
||||
|
||||
instance_secgroup_filter_name = ('%s-secgroup' %
|
||||
self._instance_filter_name(instance))
|
||||
|
||||
try:
|
||||
_nw = self._conn.nwfilterLookupByName(
|
||||
instance_secgroup_filter_name)
|
||||
_nw.undefine()
|
||||
except libvirt.libvirtError:
|
||||
LOG.debug(_('The nwfilter(%(instance_secgroup_filter_name)s) '
|
||||
'is not found.') % locals(), instance=instance)
|
||||
|
||||
def prepare_instance_filter(self, instance, network_info):
|
||||
"""Creates an NWFilter for the given instance.
|
||||
|
||||
In the process, it makes sure the filters for the provider blocks,
|
||||
security groups, and base filter are all in place.
|
||||
|
||||
"""
|
||||
self.refresh_provider_fw_rules()
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
|
||||
instance_secgroup_filter_name = ('%s-secgroup' %
|
||||
self._instance_filter_name(instance))
|
||||
|
||||
instance_secgroup_filter_children = ['nova-base-ipv4',
|
||||
'nova-base-ipv6',
|
||||
'nova-allow-dhcp-server']
|
||||
|
||||
if FLAGS.use_ipv6:
|
||||
networks = [network for (network, info) in network_info if
|
||||
info['gateway_v6']]
|
||||
|
||||
if networks:
|
||||
instance_secgroup_filter_children.append(
|
||||
'nova-allow-ra-server')
|
||||
|
||||
for security_group in db.security_group_get_by_instance(ctxt,
|
||||
instance['id']):
|
||||
|
||||
self.refresh_security_group_rules(security_group['id'])
|
||||
|
||||
instance_secgroup_filter_children.append('nova-secgroup-%s' %
|
||||
security_group['id'])
|
||||
|
||||
self._define_filter(
|
||||
self._filter_container(instance_secgroup_filter_name,
|
||||
instance_secgroup_filter_children))
|
||||
|
||||
network_filters = self._create_network_filters(instance, network_info,
|
||||
instance_secgroup_filter_name)
|
||||
|
||||
for (name, children) in network_filters:
|
||||
self._define_filters(name, children)
|
||||
|
||||
def _create_network_filters(self, instance, network_info,
|
||||
instance_secgroup_filter_name):
|
||||
if instance['image_ref'] == str(FLAGS.vpn_image_id):
|
||||
@@ -345,100 +188,6 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
self._define_filter(self._filter_container(filter_name,
|
||||
filter_children))
|
||||
|
||||
def refresh_security_group_rules(self, security_group_id):
|
||||
return self._define_filter(
|
||||
self.security_group_to_nwfilter_xml(security_group_id))
|
||||
|
||||
def refresh_provider_fw_rules(self):
|
||||
"""Update rules for all instances.
|
||||
|
||||
This is part of the FirewallDriver API and is called when the
|
||||
provider firewall rules change in the database. In the
|
||||
`prepare_instance_filter` we add a reference to the
|
||||
'nova-provider-rules' filter for each instance's firewall, and
|
||||
by changing that filter we update them all.
|
||||
|
||||
"""
|
||||
xml = self.provider_fw_to_nwfilter_xml()
|
||||
return self._define_filter(xml)
|
||||
|
||||
@staticmethod
|
||||
def security_group_to_nwfilter_xml(security_group_id):
|
||||
security_group = db.security_group_get(context.get_admin_context(),
|
||||
security_group_id)
|
||||
rule_xml = ""
|
||||
v6protocol = {'tcp': 'tcp-ipv6', 'udp': 'udp-ipv6', 'icmp': 'icmpv6'}
|
||||
for rule in security_group.rules:
|
||||
rule_xml += "<rule action='accept' direction='in' priority='300'>"
|
||||
if rule.cidr:
|
||||
version = netutils.get_ip_version(rule.cidr)
|
||||
if(FLAGS.use_ipv6 and version == 6):
|
||||
net, prefixlen = netutils.get_net_and_prefixlen(rule.cidr)
|
||||
rule_xml += ("<%s srcipaddr='%s' srcipmask='%s' " %
|
||||
(v6protocol[rule.protocol], net, prefixlen))
|
||||
else:
|
||||
net, mask = netutils.get_net_and_mask(rule.cidr)
|
||||
rule_xml += ("<%s srcipaddr='%s' srcipmask='%s' " %
|
||||
(rule.protocol, net, mask))
|
||||
if rule.protocol in ['tcp', 'udp']:
|
||||
rule_xml += ("dstportstart='%s' dstportend='%s' " %
|
||||
(rule.from_port, rule.to_port))
|
||||
elif rule.protocol == 'icmp':
|
||||
LOG.info('rule.protocol: %r, rule.from_port: %r, '
|
||||
'rule.to_port: %r', rule.protocol,
|
||||
rule.from_port, rule.to_port)
|
||||
if rule.from_port != -1:
|
||||
rule_xml += "type='%s' " % rule.from_port
|
||||
if rule.to_port != -1:
|
||||
rule_xml += "code='%s' " % rule.to_port
|
||||
|
||||
rule_xml += '/>\n'
|
||||
rule_xml += "</rule>\n"
|
||||
xml = "<filter name='nova-secgroup-%s' " % security_group_id
|
||||
if(FLAGS.use_ipv6):
|
||||
xml += "chain='root'>%s</filter>" % rule_xml
|
||||
else:
|
||||
xml += "chain='ipv4'>%s</filter>" % rule_xml
|
||||
return xml
|
||||
|
||||
@staticmethod
|
||||
def provider_fw_to_nwfilter_xml():
|
||||
"""Compose a filter of drop rules from specified cidrs."""
|
||||
rule_xml = ""
|
||||
v6protocol = {'tcp': 'tcp-ipv6', 'udp': 'udp-ipv6', 'icmp': 'icmpv6'}
|
||||
rules = db.provider_fw_rule_get_all(context.get_admin_context())
|
||||
for rule in rules:
|
||||
rule_xml += "<rule action='block' direction='in' priority='150'>"
|
||||
version = netutils.get_ip_version(rule.cidr)
|
||||
if(FLAGS.use_ipv6 and version == 6):
|
||||
net, prefixlen = netutils.get_net_and_prefixlen(rule.cidr)
|
||||
rule_xml += ("<%s srcipaddr='%s' srcipmask='%s' " %
|
||||
(v6protocol[rule.protocol], net, prefixlen))
|
||||
else:
|
||||
net, mask = netutils.get_net_and_mask(rule.cidr)
|
||||
rule_xml += ("<%s srcipaddr='%s' srcipmask='%s' " %
|
||||
(rule.protocol, net, mask))
|
||||
if rule.protocol in ['tcp', 'udp']:
|
||||
rule_xml += ("dstportstart='%s' dstportend='%s' " %
|
||||
(rule.from_port, rule.to_port))
|
||||
elif rule.protocol == 'icmp':
|
||||
LOG.info('rule.protocol: %r, rule.from_port: %r, '
|
||||
'rule.to_port: %r', rule.protocol,
|
||||
rule.from_port, rule.to_port)
|
||||
if rule.from_port != -1:
|
||||
rule_xml += "type='%s' " % rule.from_port
|
||||
if rule.to_port != -1:
|
||||
rule_xml += "code='%s' " % rule.to_port
|
||||
|
||||
rule_xml += '/>\n'
|
||||
rule_xml += "</rule>\n"
|
||||
xml = "<filter name='nova-provider-rules' "
|
||||
if(FLAGS.use_ipv6):
|
||||
xml += "chain='root'>%s</filter>" % rule_xml
|
||||
else:
|
||||
xml += "chain='ipv4'>%s</filter>" % rule_xml
|
||||
return xml
|
||||
|
||||
@staticmethod
|
||||
def _instance_filter_name(instance, nic_id=None):
|
||||
if not nic_id:
|
||||
|
||||
Reference in New Issue
Block a user