FWaaSOpts = [
cfg.StrOpt(
'driver',
- default=('neutron.services.firewall.agents.firewall_agent_api.'
+ default=('neutron.services.firewall.drivers.fwaas_base.'
'NoopFwaasDriver'),
help=_("Name of the FWaaS Driver")),
cfg.BoolOpt(
def delete_firewall(self, context, firewall, host):
"""Handle RPC cast from plugin to delete a firewall."""
pass
-
-
-class NoopFwaasDriver(object):
- """Noop Fwaas Driver.
-
- Firewall driver which does nothing.
- This driver is for disabling the firewall functionality.
- Put in temporarily until Driver changes are integrated when
- this will come in from there.
- """
-
- def create_firewall(self, apply_list, firewall):
- pass
-
- def delete_firewall(self, apply_list, firewall):
- pass
-
- def update_firewall(self, apply_list, firewall):
- pass
-
- def apply_default_policy(self, apply_list):
- pass
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation.
+# 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.
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 Dell Inc.
+# 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: Rajesh Mohan, Rajesh_Mohan3@Dell.com, DELL Inc.
+
+import abc
+
+
+class FwaasDriverBase(object):
+ """Firewall as a Service Driver base class.
+
+ Using FwaasDriver Class, an instance of L3 perimeter Firewall
+ can be created. The firewall co-exists with the L3 agent.
+
+ One instance is created for each tenant. One firewall policy
+ is associated with each tenant (in the Havana release).
+
+ The Firewall can be visualized as having two zones (in Havana
+ release), trusted and untrusted.
+
+ All the 'internal' interfaces of Neutron Router is treated as trusted. The
+ interface connected to 'external network' is treated as untrusted.
+
+ The policy is applied on traffic ingressing/egressing interfaces on
+ the trusted zone. This implies that policy will be applied for traffic
+ passing from
+ - trusted to untrusted zones
+ - untrusted to trusted zones
+ - trusted to trusted zones
+
+ Policy WILL NOT be applied for traffic from untrusted to untrusted zones.
+ This is not a problem in Havana release as there is only one interface
+ connected to external network.
+
+ Since the policy is applied on the internal interfaces, the traffic
+ will be not be NATed to floating IP. For incoming traffic, the
+ traffic will get NATed to internal IP address before it hits
+ the firewall rules. So, while writing the rules, care should be
+ taken if using rules based on floating IP.
+
+ The firewall rule addition/deletion/insertion/update are done by the
+ management console. When the policy is sent to the driver, the complete
+ policy is sent and the whole policy has to be applied atomically. The
+ firewall rules will not get updated individually. This is to avoid problems
+ related to out-of-order notifications or inconsistent behaviour by partial
+ application of rules.
+ """
+
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def create_firewall(self, apply_list, firewall):
+ """Create the Firewall with default (drop all) policy.
+
+ The default policy will be applied on all the interfaces of
+ trusted zone.
+ """
+ pass
+
+ @abc.abstractmethod
+ def delete_firewall(self, apply_list, firewall):
+ """Delete firewall.
+
+ Removes all policies created by this instance and frees up
+ all the resources.
+ """
+ pass
+
+ @abc.abstractmethod
+ def update_firewall(self, apply_list, firewall):
+ """Apply the policy on all trusted interfaces.
+
+ Remove previous policy and apply the new policy on all trusted
+ interfaces.
+ """
+ pass
+
+ @abc.abstractmethod
+ def apply_default_policy(self, apply_list, firewall):
+ """Apply the default policy on all trusted interfaces.
+
+ Remove current policy and apply the default policy on all trusted
+ interfaces.
+ """
+ pass
+
+
+class NoopFwaasDriver(FwaasDriverBase):
+ """Noop Fwaas Driver.
+
+ Firewall driver which does nothing.
+ This driver is for disabling Fwaas functionality.
+ """
+
+ def create_firewall(self, apply_list, firewall):
+ pass
+
+ def delete_firewall(self, apply_list, firewall):
+ pass
+
+ def update_firewall(self, apply_list, firewall):
+ pass
+
+ def apply_default_policy(self, apply_list, firewall):
+ pass
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation.
+# 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.
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 Dell Inc.
+# 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: Rajesh Mohan, Rajesh_Mohan3@Dell.com, DELL Inc.
+
+from neutron.agent.linux import iptables_manager
+from neutron.extensions import firewall as fw_ext
+from neutron.openstack.common import log as logging
+from neutron.services.firewall.drivers import fwaas_base
+
+LOG = logging.getLogger(__name__)
+FWAAS_DRIVER_NAME = 'Fwaas iptables driver'
+FWAAS_CHAIN = 'fwaas'
+FWAAS_DEFAULT_CHAIN = 'fwaas-default-policy'
+INGRESS_DIRECTION = 'ingress'
+EGRESS_DIRECTION = 'egress'
+CHAIN_NAME_PREFIX = {INGRESS_DIRECTION: 'i',
+ EGRESS_DIRECTION: 'o'}
+
+""" Firewall rules are applied on internal-interfaces of Neutron router.
+ The packets ingressing tenant's network will be on the output
+ direction on internal-interfaces.
+"""
+IPTABLES_DIR = {INGRESS_DIRECTION: '-o',
+ EGRESS_DIRECTION: '-i'}
+IPV4 = 'ipv4'
+IPV6 = 'ipv6'
+IP_VER_TAG = {IPV4: 'v4',
+ IPV6: 'v6'}
+
+
+class IptablesFwaasDriver(fwaas_base.FwaasDriverBase):
+ """IPTables driver for Firewall As A Service."""
+
+ def __init__(self):
+ LOG.debug(_("Initializing fwaas iptables driver"))
+
+ def create_firewall(self, apply_list, firewall):
+ LOG.debug(_('Creating firewall %(fw_id)s for tenant %(tid)s)'),
+ {'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
+ try:
+ if firewall['admin_state_up']:
+ self._setup_firewall(apply_list, firewall)
+ else:
+ self.apply_default_policy(apply_list, firewall)
+ except (LookupError, RuntimeError):
+ # catch known library exceptions and raise Fwaas generic exception
+ LOG.exception(_("Failed to create firewall: %s"), firewall['id'])
+ raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
+
+ def delete_firewall(self, apply_list, firewall):
+ LOG.debug(_('Deleting firewall %(fw_id)s for tenant %(tid)s)'),
+ {'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
+ fwid = firewall['id']
+ try:
+ for router_info in apply_list:
+ ipt_mgr = router_info.iptables_manager
+ self._remove_chains(fwid, ipt_mgr)
+ self._remove_default_chains(ipt_mgr)
+ ipt_mgr.apply()
+ except (LookupError, RuntimeError):
+ # catch known library exceptions and raise Fwaas generic exception
+ LOG.exception(_("Failed to delete firewall: %s"), fwid)
+ raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
+
+ def update_firewall(self, apply_list, firewall):
+ LOG.debug(_('Updating firewall %(fw_id)s for tenant %(tid)s)'),
+ {'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
+ try:
+ if firewall['admin_state_up']:
+ self._setup_firewall(apply_list, firewall)
+ else:
+ self.apply_default_policy(apply_list, firewall)
+ except (LookupError, RuntimeError):
+ # catch known library exceptions and raise Fwaas generic exception
+ LOG.exception(_("Failed to update firewall: %s"), firewall['id'])
+ raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
+
+ def apply_default_policy(self, apply_list, firewall):
+ LOG.debug(_('Applying firewall %(fw_id)s for tenant %(tid)s)'),
+ {'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
+ fwid = firewall['id']
+ try:
+ for router_info in apply_list:
+ ipt_mgr = router_info.iptables_manager
+
+ # the following only updates local memory; no hole in FW
+ self._remove_chains(fwid, ipt_mgr)
+ self._remove_default_chains(ipt_mgr)
+
+ # create default 'DROP ALL' policy chain
+ self._add_default_policy_chain_v4v6(ipt_mgr)
+ self._enable_policy_chain(fwid, ipt_mgr)
+
+ # apply the changes
+ ipt_mgr.apply()
+ except (LookupError, RuntimeError):
+ # catch known library exceptions and raise Fwaas generic exception
+ LOG.exception(_("Failed to apply default policy on firewall: %s"),
+ fwid)
+ raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
+
+ def _setup_firewall(self, apply_list, firewall):
+ fwid = firewall['id']
+ for router_info in apply_list:
+ ipt_mgr = router_info.iptables_manager
+
+ # the following only updates local memory; no hole in FW
+ self._remove_chains(fwid, ipt_mgr)
+ self._remove_default_chains(ipt_mgr)
+
+ # create default 'DROP ALL' policy chain
+ self._add_default_policy_chain_v4v6(ipt_mgr)
+ #create chain based on configured policy
+ self._setup_chains(firewall, ipt_mgr)
+
+ # apply the changes
+ ipt_mgr.apply()
+
+ def _get_chain_name(self, fwid, ver, direction):
+ return '%s%s%s' % (CHAIN_NAME_PREFIX[direction],
+ IP_VER_TAG[ver],
+ fwid)
+
+ def _setup_chains(self, firewall, ipt_mgr):
+ """Create Fwaas chain using the rules in the policy
+ """
+ fw_rules_list = firewall['firewall_rule_list']
+ fwid = firewall['id']
+
+ #default rules for invalid packets and established sessions
+ invalid_rule = self._drop_invalid_packets_rule()
+ est_rule = self._allow_established_rule()
+
+ for ver in [IPV4, IPV6]:
+ if ver == IPV4:
+ table = ipt_mgr.ipv4['filter']
+ else:
+ table = ipt_mgr.ipv6['filter']
+ ichain_name = self._get_chain_name(fwid, ver, INGRESS_DIRECTION)
+ ochain_name = self._get_chain_name(fwid, ver, EGRESS_DIRECTION)
+ for name in [ichain_name, ochain_name]:
+ table.add_chain(name)
+ table.add_rule(name, invalid_rule)
+ table.add_rule(name, est_rule)
+
+ for rule in fw_rules_list:
+ if not rule['enabled']:
+ continue
+ iptbl_rule = self._convert_fwaas_to_iptables_rule(rule)
+ if rule['ip_version'] == 4:
+ ver = IPV4
+ table = ipt_mgr.ipv4['filter']
+ else:
+ ver = IPV6
+ table = ipt_mgr.ipv6['filter']
+ ichain_name = self._get_chain_name(fwid, ver, INGRESS_DIRECTION)
+ ochain_name = self._get_chain_name(fwid, ver, EGRESS_DIRECTION)
+ table.add_rule(ichain_name, iptbl_rule)
+ table.add_rule(ochain_name, iptbl_rule)
+ self._enable_policy_chain(fwid, ipt_mgr)
+
+ def _remove_default_chains(self, nsid):
+ """Remove fwaas default policy chain."""
+ self._remove_chain_by_name(IPV4, FWAAS_DEFAULT_CHAIN, nsid)
+ self._remove_chain_by_name(IPV6, FWAAS_DEFAULT_CHAIN, nsid)
+
+ def _remove_chains(self, fwid, ipt_mgr):
+ """Remove fwaas policy chain."""
+ for ver in [IPV4, IPV6]:
+ for direction in [INGRESS_DIRECTION, EGRESS_DIRECTION]:
+ chain_name = self._get_chain_name(fwid, ver, direction)
+ self._remove_chain_by_name(ver, chain_name, ipt_mgr)
+
+ def _add_default_policy_chain_v4v6(self, ipt_mgr):
+ ipt_mgr.ipv4['filter'].add_chain(FWAAS_DEFAULT_CHAIN)
+ ipt_mgr.ipv4['filter'].add_rule(FWAAS_DEFAULT_CHAIN, '-j DROP')
+ ipt_mgr.ipv6['filter'].add_chain(FWAAS_DEFAULT_CHAIN)
+ ipt_mgr.ipv6['filter'].add_rule(FWAAS_DEFAULT_CHAIN, '-j DROP')
+
+ def _remove_chain_by_name(self, ver, chain_name, ipt_mgr):
+ if ver == IPV4:
+ ipt_mgr.ipv4['filter'].ensure_remove_chain(chain_name)
+ else:
+ ipt_mgr.ipv6['filter'].ensure_remove_chain(chain_name)
+
+ def _add_rules_to_chain(self, ipt_mgr, ver, chain_name, rules):
+ if ver == IPV4:
+ table = ipt_mgr.ipv4['filter']
+ else:
+ table = ipt_mgr.ipv6['filter']
+ for rule in rules:
+ table.add_rule(chain_name, rule)
+
+ def _enable_policy_chain(self, fwid, ipt_mgr):
+ bname = iptables_manager.binary_name
+
+ for (ver, tbl) in [(IPV4, ipt_mgr.ipv4['filter']),
+ (IPV6, ipt_mgr.ipv4['filter'])]:
+ for direction in [INGRESS_DIRECTION, EGRESS_DIRECTION]:
+ chain_name = self._get_chain_name(fwid, ver, direction)
+ chain_name = iptables_manager.get_chain_name(chain_name)
+ if chain_name in tbl.chains:
+ jump_rule = ['%s qr-+ -j %s-%s' % (IPTABLES_DIR[direction],
+ bname, chain_name)]
+ self._add_rules_to_chain(ipt_mgr, ver, 'FORWARD',
+ jump_rule)
+
+ #jump to DROP_ALL policy
+ chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN)
+ jump_rule = ['-o qr-+ -j %s-%s' % (bname, chain_name)]
+ self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule)
+ self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule)
+
+ #jump to DROP_ALL policy
+ chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN)
+ jump_rule = ['-i qr-+ -j %s-%s' % (bname, chain_name)]
+ self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule)
+ self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule)
+
+ def _convert_fwaas_to_iptables_rule(self, rule):
+ if rule.get('action') == 'allow':
+ rule['action'] = 'ACCEPT'
+ else:
+ rule['action'] = 'DROP'
+
+ args = [self._protocol_arg(rule.get('protocol')),
+ self._port_arg('dport',
+ rule.get('protocol'),
+ rule.get('destination_port')),
+ self._port_arg('sport',
+ rule.get('protocol'),
+ rule.get('source_port')),
+ self._ip_prefix_arg('s', rule.get('source_ip_address')),
+ self._ip_prefix_arg('d', rule.get('destination_ip_address')),
+ self._action_arg(rule.get('action'))]
+
+ iptables_rule = ' '.join(args)
+ return iptables_rule
+
+ def _drop_invalid_packets_rule(self):
+ return '-m state --state INVALID -j DROP'
+
+ def _allow_established_rule(self):
+ return '-m state --state ESTABLISHED,RELATED -j ACCEPT'
+
+ def _action_arg(self, action):
+ if action:
+ return '-j %s' % action
+ return ''
+
+ def _protocol_arg(self, protocol):
+ if protocol:
+ return '-p %s' % protocol
+ return ''
+
+ def _port_arg(self, direction, protocol, port):
+ if not (protocol in ['udp', 'tcp'] and port):
+ return ''
+ return '--%s %s' % (direction, port)
+
+ def _ip_prefix_arg(self, direction, ip_prefix):
+ if ip_prefix:
+ return '-%s %s' % (direction, ip_prefix)
+ return ''
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+#
+# 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.
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+#
+# 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.
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 Dell Inc.
+# 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: Rajesh Mohan, Rajesh_Mohan3@Dell.com, DELL Inc.
+
+import mock
+from mock import call
+from oslo.config import cfg
+
+from neutron.agent.common import config as a_cfg
+import neutron.services.firewall.drivers.linux.iptables_fwaas as fwaas
+from neutron.tests import base
+from neutron.tests.unit import test_api_v2
+
+
+_uuid = test_api_v2._uuid
+FAKE_SRC_PREFIX = '10.0.0.0/24'
+FAKE_DST_PREFIX = '20.0.0.0/24'
+FAKE_PROTOCOL = 'tcp'
+FAKE_SRC_PORT = 5000
+FAKE_DST_PORT = 22
+FAKE_FW_ID = 'fake-fw-uuid'
+
+
+class IptablesFwaasTestCase(base.BaseTestCase):
+ def setUp(self):
+ super(IptablesFwaasTestCase, self).setUp()
+ cfg.CONF.register_opts(a_cfg.ROOT_HELPER_OPTS, 'AGENT')
+ self.utils_exec_p = mock.patch(
+ 'neutron.agent.linux.utils.execute')
+ self.utils_exec = self.utils_exec_p.start()
+ self.addCleanup(self.utils_exec_p.stop)
+ self.iptables_cls_p = mock.patch(
+ 'neutron.agent.linux.iptables_manager.IptablesManager')
+ iptables_cls = self.iptables_cls_p.start()
+ self.addCleanup(self.iptables_cls_p.stop)
+ self.iptables_inst = mock.Mock()
+ self.v4filter_inst = mock.Mock()
+ self.v6filter_inst = mock.Mock()
+ self.v4filter_inst.chains = []
+ self.v6filter_inst.chains = []
+ self.iptables_inst.ipv4 = {'filter': self.v4filter_inst}
+ self.iptables_inst.ipv6 = {'filter': self.v6filter_inst}
+ iptables_cls.return_value = self.iptables_inst
+
+ self.router_info_inst = mock.Mock()
+ self.router_info_inst.iptables_manager = self.iptables_inst
+
+ self.firewall = fwaas.IptablesFwaasDriver()
+
+ def _fake_rules_v4(self, fwid):
+ rule_list = []
+ rule1 = {'enabled': True,
+ 'action': 'allow',
+ 'ip_version': 4,
+ 'protocol': 'tcp',
+ 'destination_port': '80',
+ 'source_ip_address': '10.24.4.2'}
+ rule2 = {'enabled': True,
+ 'action': 'deny',
+ 'ip_version': 4,
+ 'protocol': 'tcp',
+ 'destination_port': '22'}
+ ingress_chain = ('iv4%s' % fwid)[:11]
+ self.v4filter_inst.chains.append(ingress_chain)
+ egress_chain = ('ov4%s' % fwid)[:11]
+ self.v4filter_inst.chains.append(egress_chain)
+ rule_list.append(rule1)
+ rule_list.append(rule2)
+ return rule_list
+
+ def _fake_firewall_no_rule(self):
+ rule_list = []
+ fw_inst = {'id': FAKE_FW_ID,
+ 'admin_state_up': True,
+ 'tenant_id': 'tenant-uuid',
+ 'firewall_rule_list': rule_list}
+ return fw_inst
+
+ def _fake_firewall(self, rule_list):
+ fw_inst = {'id': FAKE_FW_ID,
+ 'admin_state_up': True,
+ 'tenant_id': 'tenant-uuid',
+ 'firewall_rule_list': rule_list}
+ return fw_inst
+
+ def _fake_firewall_with_admin_down(self, rule_list):
+ fw_inst = {'id': FAKE_FW_ID,
+ 'admin_state_up': False,
+ 'tenant_id': 'tenant-uuid',
+ 'firewall_rule_list': rule_list}
+ return fw_inst
+
+ def _fake_apply_list(self):
+ apply_list = []
+ apply_list.append(self.router_info_inst)
+ return apply_list
+
+ def _setup_firewall_with_rules(self, func):
+ apply_list = self._fake_apply_list()
+ rule_list = self._fake_rules_v4(FAKE_FW_ID)
+ firewall = self._fake_firewall(rule_list)
+ func(apply_list, firewall)
+ invalid_rule = '-m state --state INVALID -j DROP'
+ est_rule = '-m state --state ESTABLISHED,RELATED -j ACCEPT'
+ rule1 = '-p tcp --dport 80 -s 10.24.4.2 -j ACCEPT'
+ rule2 = '-p tcp --dport 22 -j DROP'
+ ingress_chain = 'iv4%s' % firewall['id']
+ egress_chain = 'ov4%s' % firewall['id']
+ bname = fwaas.iptables_manager.binary_name
+ ipt_mgr_ichain = '%s-%s' % (bname, ingress_chain[:11])
+ ipt_mgr_echain = '%s-%s' % (bname, egress_chain[:11])
+ calls = [call.ensure_remove_chain('iv4fake-fw-uuid'),
+ call.ensure_remove_chain('ov4fake-fw-uuid'),
+ call.ensure_remove_chain('fwaas-default-policy'),
+ call.add_chain('fwaas-default-policy'),
+ call.add_rule('fwaas-default-policy', '-j DROP'),
+ call.add_chain(ingress_chain),
+ call.add_rule(ingress_chain, invalid_rule),
+ call.add_rule(ingress_chain, est_rule),
+ call.add_chain(egress_chain),
+ call.add_rule(egress_chain, invalid_rule),
+ call.add_rule(egress_chain, est_rule),
+ call.add_rule(ingress_chain, rule1),
+ call.add_rule(egress_chain, rule1),
+ call.add_rule(ingress_chain, rule2),
+ call.add_rule(egress_chain, rule2),
+ call.add_rule('FORWARD', '-o qr-+ -j %s' % ipt_mgr_ichain),
+ call.add_rule('FORWARD', '-i qr-+ -j %s' % ipt_mgr_echain),
+ call.add_rule('FORWARD', '-o qr-+ -j %s-fwaas-defau' % bname),
+ call.add_rule('FORWARD', '-i qr-+ -j %s-fwaas-defau' % bname)]
+ self.v4filter_inst.assert_has_calls(calls)
+
+ def test_create_firewall_no_rules(self):
+ apply_list = self._fake_apply_list()
+ firewall = self._fake_firewall_no_rule()
+ self.firewall.create_firewall(apply_list, firewall)
+ invalid_rule = '-m state --state INVALID -j DROP'
+ est_rule = '-m state --state ESTABLISHED,RELATED -j ACCEPT'
+ ingress_chain = ('iv4%s' % firewall['id'])
+ egress_chain = ('ov4%s' % firewall['id'])
+ bname = fwaas.iptables_manager.binary_name
+ calls = [call.ensure_remove_chain('iv4fake-fw-uuid'),
+ call.ensure_remove_chain('ov4fake-fw-uuid'),
+ call.ensure_remove_chain('fwaas-default-policy'),
+ call.add_chain('fwaas-default-policy'),
+ call.add_rule('fwaas-default-policy', '-j DROP'),
+ call.add_chain(ingress_chain),
+ call.add_rule(ingress_chain, invalid_rule),
+ call.add_rule(ingress_chain, est_rule),
+ call.add_chain(egress_chain),
+ call.add_rule(egress_chain, invalid_rule),
+ call.add_rule(egress_chain, est_rule),
+ call.add_rule('FORWARD', '-o qr-+ -j %s-fwaas-defau' % bname),
+ call.add_rule('FORWARD', '-i qr-+ -j %s-fwaas-defau' % bname)]
+ self.v4filter_inst.assert_has_calls(calls)
+
+ def test_create_firewall_with_rules(self):
+ self._setup_firewall_with_rules(self.firewall.create_firewall)
+
+ def test_update_firewall_with_rules(self):
+ self._setup_firewall_with_rules(self.firewall.update_firewall)
+
+ def test_delete_firewall(self):
+ apply_list = self._fake_apply_list()
+ firewall = self._fake_firewall_no_rule()
+ self.firewall.delete_firewall(apply_list, firewall)
+ ingress_chain = 'iv4%s' % firewall['id']
+ egress_chain = 'ov4%s' % firewall['id']
+ calls = [call.ensure_remove_chain(ingress_chain),
+ call.ensure_remove_chain(egress_chain),
+ call.ensure_remove_chain('fwaas-default-policy')]
+ self.v4filter_inst.assert_has_calls(calls)
+
+ def test_create_firewall_with_admin_down(self):
+ rule_list = self._fake_rules_v4(FAKE_FW_ID)
+ apply_list = self._fake_apply_list()
+ firewall = self._fake_firewall_with_admin_down(rule_list)
+ self.firewall.create_firewall(apply_list, firewall)
+ calls = [call.ensure_remove_chain('iv4fake-fw-uuid'),
+ call.ensure_remove_chain('ov4fake-fw-uuid'),
+ call.ensure_remove_chain('fwaas-default-policy'),
+ call.add_chain('fwaas-default-policy'),
+ call.add_rule('fwaas-default-policy', '-j DROP')]
+ self.v4filter_inst.assert_has_calls(calls)