Removing FWaaS v1 source code

As German Eichberger's email at
https://markmail.org/message/2kva4b3lwgddyeau. So This patch intend to
removes source code related FWaaS V1.

Change-Id: I4e440c854e5aa11193d38946e659481f4fefded2
This commit is contained in:
Nguyen Phuong An 2018-11-08 10:56:39 +07:00 committed by Akihiro Motoki
parent d2adcdec83
commit 0e968fa0c7
24 changed files with 28 additions and 6228 deletions

View File

@ -14,21 +14,17 @@
- neutron-fwaas-networking-midonet-cross-py35:
voting: false
- legacy-neutron-fwaas-v2-dsvm-tempest
- legacy-neutron-fwaas-v1-dsvm-tempest
- legacy-neutron-fwaas-dsvm-functional
- legacy-grenade-dsvm-neutron-fwaas-multinode:
voting: false
irrelevant-files:
- ^(test-|)requirements.txt$
- ^setup.cfg$
- legacy-neutron-fwaas-v1-dsvm-tempest-multinode:
voting: false
- legacy-neutron-fwaas-v2-dsvm-tempest-multinode:
voting: false
gate:
jobs:
- legacy-neutron-fwaas-v2-dsvm-tempest
- legacy-neutron-fwaas-v1-dsvm-tempest
- legacy-neutron-fwaas-dsvm-functional
experimental:
jobs:

View File

@ -6,10 +6,8 @@ This is setup as a DevStack plugin. For more information on DevStack plugins,
see the `DevStack Plugins documentation
<https://docs.openstack.org/devstack/latest/plugins.html>`_.
Please note that the old 'q-fwaas' keyword still exists, and will run FWaaS V1.
This default will be changed during the Ocata cycle. The introduction of two
new keywords, 'q-fwaas-v1' and 'q-fwaas-v2' allow you to explicitly select the
version you with to run.
Please note that the old 'q-fwaas' keyword still exists, You can specify
enable_service q-fwaas or enable_service q-fwaas-v2 in local.conf
How to run FWaaS V2 in DevStack
===============================
@ -32,25 +30,3 @@ testing.
[[local|localrc]]
enable_plugin neutron-fwaas https://review.openstack.org/p/openstack/neutron-fwaas refs/changes/50/214350/14
enable_service q-fwaas-v2
How to run FWaaS V1 in DevStack
===============================
Add the following to the localrc section of your local.conf to configure
FWaaS v1.
.. code-block:: ini
[[local|localrc]]
enable_plugin neutron-fwaas https://git.openstack.org/openstack/neutron-fwaas
enable_service q-fwaas-v1
To check a specific patchset that is currently under development, use a form
like the below example, which is checking out change 214350 patch set 14 for
testing.
.. code-block:: ini
[[local|localrc]]
enable_plugin neutron-fwaas https://review.openstack.org/p/openstack/neutron-fwaas refs/changes/50/214350/14
enable_service q-fwaas-v1

View File

@ -38,14 +38,6 @@ function install_fwaas() {
fi
}
function configure_fwaas_v1() {
cp $NEUTRON_FWAAS_DIR/etc/neutron_fwaas.conf.sample $NEUTRON_FWAAS_CONF
neutron_fwaas_configure_driver fwaas
iniset_multiline $Q_L3_CONF_FILE fwaas agent_version v1
iniset_multiline $Q_L3_CONF_FILE fwaas conntrack_driver conntrack
iniset_multiline $Q_L3_CONF_FILE fwaas driver $FWAAS_DRIVER_V1
}
function configure_fwaas_v2() {
# Add conf file
cp $NEUTRON_FWAAS_DIR/etc/neutron_fwaas.conf.sample $NEUTRON_FWAAS_CONF
@ -93,13 +85,7 @@ function cleanup_fwaas() {
}
function neutron_fwaas_configure_common {
if is_service_enabled q-fwaas-v1 neutron-fwaas-v1; then
neutron_service_plugin_class_add $FWAAS_PLUGIN_V1
elif is_service_enabled q-fwaas-v2 neutron-fwaas-v2; then
neutron_service_plugin_class_add $FWAAS_PLUGIN_V2
else
neutron_service_plugin_class_add $FWAAS_PLUGIN_V1
fi
neutron_service_plugin_class_add $FWAAS_PLUGIN_V2
}
function neutron_fwaas_configure_driver {
@ -109,7 +95,7 @@ function neutron_fwaas_configure_driver {
}
# check for service enabled
if is_service_enabled q-svc neutron-api && is_service_enabled q-fwaas q-fwaas-v1 q-fwaas-v2 neutron-fwaas-v1 neutron-fwaas-v2; then
if is_service_enabled q-svc neutron-api && is_service_enabled q-fwaas q-fwaas-v2 neutron-fwaas-v2; then
if [[ "$1" == "stack" && "$2" == "install" ]]; then
# Perform installation of service source
@ -120,19 +106,11 @@ if is_service_enabled q-svc neutron-api && is_service_enabled q-fwaas q-fwaas-v1
# Configure after the other layer 1 and 2 services have been configured
neutron_fwaas_configure_common
neutron_fwaas_generate_config_files
if is_service_enabled q-fwaas-v1 neutron-fwaas-v1; then
echo_summary "Configuring neutron-fwaas for FWaaS v1"
configure_fwaas_v1
elif is_service_enabled q-fwaas-v2 neutron-fwaas-v2; then
echo_summary "Configuring neutron-fwaas for FWaaS v2"
configure_fwaas_v2
if is_service_enabled q-log neutron-log; then
echo_summary "Configuring FwaaS V2 packet log for l3 extension"
configure_l3_log_fwaas_v2
fi
else
echo_summary "Configuring neutron-fwaas for FWaaS v1"
configure_fwaas_v1
echo_summary "Configuring neutron-fwaas for FWaaS v2"
configure_fwaas_v2
if is_service_enabled q-log neutron-log; then
echo_summary "Configuring FwaaS V2 packet log for l3 extension"
configure_l3_log_fwaas_v2
fi
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then

View File

@ -1,7 +1,5 @@
FWAAS_DRIVER_V1=${FWAAS_DRIVER_V1:-iptables}
FWAAS_DRIVER_V2=${FWAAS_DRIVER_V2:-iptables_v2}
FW_L2_DRIVER=${FW_L2_DRIVER:-noop}
FWAAS_PLUGIN_V1=${FWAAS_PLUGIN:-firewall}
FWAAS_PLUGIN_V2=${FWAAS_PLUGIN:-firewall_v2}
NEUTRON_FWAAS_DIR=$DEST/neutron-fwaas

View File

@ -13,38 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import operator
from neutron.db import common_db_mixin as base_db
from neutron.db.models import agent as agent_model
from neutron.db.models import l3agent as l3agent_model
from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
from neutron_lib import constants as nl_constants
from neutron_lib.db import model_base
from neutron_lib.exceptions import firewall_v1 as f_exc
from neutron_lib.exceptions import l3
from neutron_lib.plugins import directory
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import uuidutils
import sqlalchemy as sa
from sqlalchemy.ext.orderinglist import ordering_list
from sqlalchemy import orm
from sqlalchemy.orm import exc
import netaddr
from neutron_fwaas.common import fwaas_constants
from neutron_fwaas.db.firewall import firewall_router_insertion_db \
as fw_r_ins_db
from neutron_fwaas.extensions import firewall as fw_ext
LOG = logging.getLogger(__name__)
# Note(annp): Keep firewall db v1 structure for migration
class FirewallRule(model_base.BASEV2, model_base.HasId, model_base.HasProject):
"""Represents a Firewall rule."""
__tablename__ = 'firewall_rules'
@ -100,558 +75,15 @@ class FirewallPolicy(model_base.BASEV2, model_base.HasId,
firewalls = orm.relationship(Firewall, backref='firewall_policies')
class Firewall_db_mixin(fw_ext.FirewallPluginBase, base_db.CommonDbMixin):
"""Mixin class for Firewall DB implementation."""
class FirewallRouterAssociation(model_base.BASEV2):
@property
def _core_plugin(self):
return directory.get_plugin()
"""Tracks FW Router Association"""
def _get_firewall(self, context, id):
try:
return self._get_by_id(context, Firewall, id)
except exc.NoResultFound:
raise f_exc.FirewallNotFound(firewall_id=id)
__tablename__ = 'firewall_router_associations'
def _get_firewall_policy(self, context, id):
try:
return self._get_by_id(context, FirewallPolicy, id)
except exc.NoResultFound:
raise f_exc.FirewallPolicyNotFound(firewall_policy_id=id)
def _get_firewall_rule(self, context, id):
try:
return self._get_by_id(context, FirewallRule, id)
except exc.NoResultFound:
raise f_exc.FirewallRuleNotFound(firewall_rule_id=id)
def _make_firewall_dict(self, fw, fields=None):
res = {'id': fw['id'],
'tenant_id': fw['tenant_id'],
'name': fw['name'],
'description': fw['description'],
'shared': fw['shared'],
'admin_state_up': fw['admin_state_up'],
'status': fw['status'],
'firewall_policy_id': fw['firewall_policy_id']}
return self._fields(res, fields)
def _make_firewall_policy_dict(self, firewall_policy, fields=None):
fw_rules = [rule['id'] for rule in firewall_policy['firewall_rules']]
firewalls = [fw['id'] for fw in firewall_policy['firewalls']]
res = {'id': firewall_policy['id'],
'tenant_id': firewall_policy['tenant_id'],
'name': firewall_policy['name'],
'description': firewall_policy['description'],
'shared': firewall_policy['shared'],
'audited': firewall_policy['audited'],
'firewall_rules': fw_rules,
'firewall_list': firewalls}
return self._fields(res, fields)
def _make_firewall_rule_dict(self, firewall_rule, fields=None):
position = None
# We return the position only if the firewall_rule is bound to a
# firewall_policy.
if firewall_rule['firewall_policy_id']:
position = firewall_rule['position']
src_port_range = self._get_port_range_from_min_max_ports(
firewall_rule['source_port_range_min'],
firewall_rule['source_port_range_max'])
dst_port_range = self._get_port_range_from_min_max_ports(
firewall_rule['destination_port_range_min'],
firewall_rule['destination_port_range_max'])
res = {'id': firewall_rule['id'],
'tenant_id': firewall_rule['tenant_id'],
'name': firewall_rule['name'],
'description': firewall_rule['description'],
'firewall_policy_id': firewall_rule['firewall_policy_id'],
'shared': firewall_rule['shared'],
'protocol': firewall_rule['protocol'],
'ip_version': firewall_rule['ip_version'],
'source_ip_address': firewall_rule['source_ip_address'],
'destination_ip_address':
firewall_rule['destination_ip_address'],
'source_port': src_port_range,
'destination_port': dst_port_range,
'action': firewall_rule['action'],
'position': position,
'enabled': firewall_rule['enabled']}
return self._fields(res, fields)
def _make_firewall_dict_with_rules(self, context, firewall_id):
firewall = self.get_firewall(context, firewall_id)
fw_policy_id = firewall['firewall_policy_id']
if fw_policy_id:
fw_rules_list = self.get_firewall_rules(
context, filters={'firewall_policy_id': [fw_policy_id]})
fw_rules_list = sorted(
fw_rules_list, key=operator.itemgetter('position'))
firewall['firewall_rule_list'] = fw_rules_list
else:
firewall['firewall_rule_list'] = []
# FIXME(Sumit): If the size of the firewall object we are creating
# here exceeds the largest message size supported by rabbit/qpid
# then we will have a problem.
return firewall
def _check_firewall_rule_conflict(self, fwr_db, fwp_db):
if not fwr_db['shared']:
if fwr_db['tenant_id'] != fwp_db['tenant_id']:
raise f_exc.FirewallRuleConflict(
firewall_rule_id=fwr_db['id'],
project_id=fwr_db['tenant_id'])
def _set_rules_for_policy(self, context, firewall_policy_db, fwp):
rule_id_list = fwp['firewall_rules']
fwp_db = firewall_policy_db
with context.session.begin(subtransactions=True):
if not rule_id_list:
fwp_db.firewall_rules = []
fwp_db.audited = False
return
# We will first check if the new list of rules is valid
filters = {'id': [r_id for r_id in rule_id_list]}
rules_in_db = self._get_collection_query(context, FirewallRule,
filters=filters)
rules_dict = dict((fwr_db['id'], fwr_db) for fwr_db in rules_in_db)
for fwrule_id in rule_id_list:
if fwrule_id not in rules_dict:
# If we find an invalid rule in the list we
# do not perform the update since this breaks
# the integrity of this list.
raise f_exc.FirewallRuleNotFound(
firewall_rule_id=fwrule_id)
elif rules_dict[fwrule_id]['firewall_policy_id']:
if (rules_dict[fwrule_id]['firewall_policy_id'] !=
fwp_db['id']):
raise f_exc.FirewallRuleInUse(
firewall_rule_id=fwrule_id)
if 'shared' in fwp:
if fwp['shared'] and not rules_dict[fwrule_id]['shared']:
raise f_exc.FirewallRuleSharingConflict(
firewall_rule_id=fwrule_id,
firewall_policy_id=fwp_db['id'])
elif fwp_db['shared'] and not rules_dict[fwrule_id]['shared']:
raise f_exc.FirewallRuleSharingConflict(
firewall_rule_id=fwrule_id,
firewall_policy_id=fwp_db['id'])
for fwr_db in rules_in_db:
self._check_firewall_rule_conflict(fwr_db, fwp_db)
# New list of rules is valid so we will first reset the existing
# list and then add each rule in order.
# Note that the list could be empty in which case we interpret
# it as clearing existing rules.
fwp_db.firewall_rules = []
for fwrule_id in rule_id_list:
fwp_db.firewall_rules.append(rules_dict[fwrule_id])
fwp_db.firewall_rules.reorder()
fwp_db.audited = False
def _check_unshared_rules_for_policy(self, fwp_db, fwp):
if fwp['shared']:
rules_in_db = fwp_db['firewall_rules']
for fwr_db in rules_in_db:
if not fwr_db['shared']:
raise f_exc.FirewallPolicySharingConflict(
firewall_rule_id=fwr_db['id'],
firewall_policy_id=fwp_db['id'])
def _process_rule_for_policy(self, context, firewall_policy_id,
firewall_rule_db, position):
with context.session.begin(subtransactions=True):
fwp_query = context.session.query(
FirewallPolicy).with_lockmode('update')
fwp_db = fwp_query.filter_by(id=firewall_policy_id).one()
if position:
# Note that although position numbering starts at 1,
# internal ordering of the list starts at 0, so we compensate.
fwp_db.firewall_rules.insert(position - 1, firewall_rule_db)
else:
fwp_db.firewall_rules.remove(firewall_rule_db)
fwp_db.firewall_rules.reorder()
fwp_db.audited = False
return self._make_firewall_policy_dict(fwp_db)
def _get_min_max_ports_from_range(self, port_range):
if not port_range:
return [None, None]
min_port, sep, max_port = port_range.partition(":")
if not max_port:
max_port = min_port
self._validate_fwr_port_range(min_port, max_port)
return [int(min_port), int(max_port)]
def _get_port_range_from_min_max_ports(self, min_port, max_port):
if not min_port:
return None
if min_port == max_port:
return str(min_port)
self._validate_fwr_port_range(min_port, max_port)
return '%s:%s' % (min_port, max_port)
def _validate_fw_parameters(self, context, fw, fw_tenant_id):
if 'firewall_policy_id' not in fw:
return
fwp_id = fw['firewall_policy_id']
fwp = self._get_firewall_policy(context, fwp_id)
if fw_tenant_id != fwp['tenant_id'] and not fwp['shared']:
raise f_exc.FirewallPolicyConflict(firewall_policy_id=fwp_id)
def _validate_fwr_src_dst_ip_version(self, fwr):
src_version = dst_version = None
if fwr.get('source_ip_address', None):
src_version = netaddr.IPNetwork(fwr['source_ip_address']).version
if fwr.get('destination_ip_address', None):
dst_version = netaddr.IPNetwork(
fwr['destination_ip_address']).version
rule_ip_version = fwr.get('ip_version', None)
if ((src_version and src_version != rule_ip_version) or
(dst_version and dst_version != rule_ip_version)):
raise f_exc.FirewallIpAddressConflict()
def _validate_fwr_port_range(self, min_port, max_port):
if int(min_port) > int(max_port):
port_range = '%s:%s' % (min_port, max_port)
raise f_exc.FirewallRuleInvalidPortValue(port=port_range)
def _validate_fwr_protocol_parameters(self, fwr):
protocol = fwr.get('protocol', None)
if protocol not in (nl_constants.PROTO_NAME_TCP,
nl_constants.PROTO_NAME_UDP):
if (fwr.get('source_port', None) or
fwr.get('destination_port', None)):
raise f_exc.FirewallRuleInvalidICMPParameter(
param="Source, destination port")
def create_firewall(self, context, firewall, status=None):
LOG.debug("create_firewall() called")
fw = firewall['firewall']
tenant_id = fw['tenant_id']
# distributed routers may required a more complex state machine;
# the introduction of a new 'CREATED' state allows this, whilst
# keeping a backward compatible behavior of the logical resource.
if not status:
status = (nl_constants.CREATED if cfg.CONF.router_distributed
else nl_constants.PENDING_CREATE)
with context.session.begin(subtransactions=True):
self._validate_fw_parameters(context, fw, tenant_id)
firewall_db = Firewall(
id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
name=fw['name'],
description=fw['description'],
firewall_policy_id=fw['firewall_policy_id'],
admin_state_up=fw['admin_state_up'],
status=status)
context.session.add(firewall_db)
return self._make_firewall_dict(firewall_db)
def update_firewall(self, context, id, firewall):
LOG.debug("update_firewall() called")
fw = firewall['firewall']
with context.session.begin(subtransactions=True):
fw_db = self.get_firewall(context, id)
self._validate_fw_parameters(context, fw, fw_db['tenant_id'])
count = context.session.query(Firewall).filter_by(id=id).update(fw)
if not count:
raise f_exc.FirewallNotFound(firewall_id=id)
return self.get_firewall(context, id)
def update_firewall_status(self, context, id, status, not_in=None):
"""Conditionally update firewall status.
Status transition is performed only if firewall is not in the specified
states as defined by 'not_in' list.
"""
# filter in_ wants iterable objects, None isn't.
not_in = not_in or []
with context.session.begin(subtransactions=True):
return (context.session.query(Firewall).
filter(Firewall.id == id).
filter(~Firewall.status.in_(not_in)).
update({'status': status}, synchronize_session=False))
def delete_firewall(self, context, id):
LOG.debug("delete_firewall() called")
with context.session.begin(subtransactions=True):
# Note: Plugin should ensure that it's okay to delete if the
# firewall is active
count = context.session.query(Firewall).filter_by(id=id).delete()
if not count:
raise f_exc.FirewallNotFound(firewall_id=id)
def get_firewall(self, context, id, fields=None):
LOG.debug("get_firewall() called")
fw = self._get_firewall(context, id)
return self._make_firewall_dict(fw, fields)
def get_firewalls(self, context, filters=None, fields=None):
LOG.debug("get_firewalls() called")
return self._get_collection(context, Firewall,
self._make_firewall_dict,
filters=filters, fields=fields)
def get_firewalls_count(self, context, filters=None):
LOG.debug("get_firewalls_count() called")
return self._get_collection_count(context, Firewall,
filters=filters)
def create_firewall_policy(self, context, firewall_policy):
LOG.debug("create_firewall_policy() called")
fwp = firewall_policy['firewall_policy']
with context.session.begin(subtransactions=True):
fwp_db = FirewallPolicy(id=uuidutils.generate_uuid(),
tenant_id=fwp['tenant_id'],
name=fwp['name'],
description=fwp['description'],
shared=fwp['shared'])
context.session.add(fwp_db)
self._set_rules_for_policy(context, fwp_db, fwp)
fwp_db.audited = fwp['audited']
return self._make_firewall_policy_dict(fwp_db)
def update_firewall_policy(self, context, id, firewall_policy):
LOG.debug("update_firewall_policy() called")
fwp = firewall_policy['firewall_policy']
with context.session.begin(subtransactions=True):
fwp_db = self._get_firewall_policy(context, id)
# check tenant ids are same for fw and fwp or not
if not fwp.get('shared', True) and fwp_db.firewalls:
for fw in fwp_db['firewalls']:
if fwp_db['tenant_id'] != fw['tenant_id']:
raise f_exc.FirewallPolicyInUse(
firewall_policy_id=id)
# check any existing rules are not shared
if 'shared' in fwp and 'firewall_rules' not in fwp:
self._check_unshared_rules_for_policy(fwp_db, fwp)
elif 'firewall_rules' in fwp:
self._set_rules_for_policy(context, fwp_db, fwp)
del fwp['firewall_rules']
if 'audited' not in fwp:
fwp['audited'] = False
fwp_db.update(fwp)
return self._make_firewall_policy_dict(fwp_db)
def delete_firewall_policy(self, context, id):
LOG.debug("delete_firewall_policy() called")
with context.session.begin(subtransactions=True):
fwp = self._get_firewall_policy(context, id)
# Ensure that the firewall_policy is not
# being used
qry = context.session.query(Firewall)
if qry.filter_by(firewall_policy_id=id).first():
raise f_exc.FirewallPolicyInUse(firewall_policy_id=id)
else:
context.session.delete(fwp)
def get_firewall_policy(self, context, id, fields=None):
LOG.debug("get_firewall_policy() called")
fwp = self._get_firewall_policy(context, id)
return self._make_firewall_policy_dict(fwp, fields)
def get_firewall_policies(self, context, filters=None, fields=None):
LOG.debug("get_firewall_policies() called")
return self._get_collection(context, FirewallPolicy,
self._make_firewall_policy_dict,
filters=filters, fields=fields)
def get_firewalls_policies_count(self, context, filters=None):
LOG.debug("get_firewall_policies_count() called")
return self._get_collection_count(context, FirewallPolicy,
filters=filters)
def create_firewall_rule(self, context, firewall_rule):
LOG.debug("create_firewall_rule() called")
fwr = firewall_rule['firewall_rule']
self._validate_fwr_protocol_parameters(fwr)
self._validate_fwr_src_dst_ip_version(fwr)
if not fwr['protocol'] and (fwr['source_port'] or
fwr['destination_port']):
raise f_exc.FirewallRuleWithPortWithoutProtocolInvalid()
src_port_min, src_port_max = self._get_min_max_ports_from_range(
fwr['source_port'])
dst_port_min, dst_port_max = self._get_min_max_ports_from_range(
fwr['destination_port'])
with context.session.begin(subtransactions=True):
fwr_db = FirewallRule(
id=uuidutils.generate_uuid(),
tenant_id=fwr['tenant_id'],
name=fwr['name'],
description=fwr['description'],
shared=fwr['shared'],
protocol=fwr['protocol'],
ip_version=fwr['ip_version'],
source_ip_address=fwr['source_ip_address'],
destination_ip_address=fwr['destination_ip_address'],
source_port_range_min=src_port_min,
source_port_range_max=src_port_max,
destination_port_range_min=dst_port_min,
destination_port_range_max=dst_port_max,
action=fwr['action'],
enabled=fwr['enabled'])
context.session.add(fwr_db)
return self._make_firewall_rule_dict(fwr_db)
def update_firewall_rule(self, context, id, firewall_rule):
LOG.debug("update_firewall_rule() called")
fwr = firewall_rule['firewall_rule']
self._validate_fwr_protocol_parameters(fwr)
self._validate_fwr_src_dst_ip_version(fwr)
fwr_db = self._get_firewall_rule(context, id)
if fwr_db.firewall_policy_id:
fwp_db = self._get_firewall_policy(context,
fwr_db.firewall_policy_id)
if 'shared' in fwr and not fwr['shared']:
if fwr_db['tenant_id'] != fwp_db['tenant_id']:
raise f_exc.FirewallRuleInUse(firewall_rule_id=id)
if 'source_port' in fwr:
src_port_min, src_port_max = self._get_min_max_ports_from_range(
fwr['source_port'])
fwr['source_port_range_min'] = src_port_min
fwr['source_port_range_max'] = src_port_max
del fwr['source_port']
if 'destination_port' in fwr:
dst_port_min, dst_port_max = self._get_min_max_ports_from_range(
fwr['destination_port'])
fwr['destination_port_range_min'] = dst_port_min
fwr['destination_port_range_max'] = dst_port_max
del fwr['destination_port']
with context.session.begin(subtransactions=True):
protocol = fwr.get('protocol', fwr_db['protocol'])
if not protocol:
sport = fwr.get('source_port_range_min',
fwr_db['source_port_range_min'])
dport = fwr.get('destination_port_range_min',
fwr_db['destination_port_range_min'])
if sport or dport:
raise f_exc.FirewallRuleWithPortWithoutProtocolInvalid()
fwr_db.update(fwr)
if fwr_db.firewall_policy_id:
fwp_db.audited = False
return self._make_firewall_rule_dict(fwr_db)
def delete_firewall_rule(self, context, id):
LOG.debug("delete_firewall_rule() called")
with context.session.begin(subtransactions=True):
fwr = self._get_firewall_rule(context, id)
if fwr.firewall_policy_id:
raise f_exc.FirewallRuleInUse(firewall_rule_id=id)
context.session.delete(fwr)
def get_firewall_rule(self, context, id, fields=None):
LOG.debug("get_firewall_rule() called")
fwr = self._get_firewall_rule(context, id)
return self._make_firewall_rule_dict(fwr, fields)
def get_firewall_rules(self, context, filters=None, fields=None):
LOG.debug("get_firewall_rules() called")
return self._get_collection(context, FirewallRule,
self._make_firewall_rule_dict,
filters=filters, fields=fields)
def get_firewalls_rules_count(self, context, filters=None):
LOG.debug("get_firewall_rules_count() called")
return self._get_collection_count(context, FirewallRule,
filters=filters)
def _validate_insert_remove_rule_request(self, id, rule_info):
if not rule_info or 'firewall_rule_id' not in rule_info:
raise f_exc.FirewallRuleInfoMissing()
def insert_rule(self, context, id, rule_info):
LOG.debug("insert_rule() called")
self._validate_insert_remove_rule_request(id, rule_info)
firewall_rule_id = rule_info['firewall_rule_id']
insert_before = True
ref_firewall_rule_id = None
if not firewall_rule_id:
raise f_exc.FirewallRuleNotFound(firewall_rule_id=None)
if 'insert_before' in rule_info:
ref_firewall_rule_id = rule_info['insert_before']
if not ref_firewall_rule_id and 'insert_after' in rule_info:
# If insert_before is set, we will ignore insert_after.
ref_firewall_rule_id = rule_info['insert_after']
insert_before = False
with context.session.begin(subtransactions=True):
fwr_db = self._get_firewall_rule(context, firewall_rule_id)
fwp_db = self._get_firewall_policy(context, id)
if fwr_db.firewall_policy_id:
raise f_exc.FirewallRuleInUse(firewall_rule_id=fwr_db['id'])
self._check_firewall_rule_conflict(fwr_db, fwp_db)
if ref_firewall_rule_id:
# If reference_firewall_rule_id is set, the new rule
# is inserted depending on the value of insert_before.
# If insert_before is set, the new rule is inserted before
# reference_firewall_rule_id, and if it is not set the new
# rule is inserted after reference_firewall_rule_id.
ref_fwr_db = self._get_firewall_rule(
context, ref_firewall_rule_id)
if ref_fwr_db.firewall_policy_id != id:
raise f_exc.FirewallRuleNotAssociatedWithPolicy(
firewall_rule_id=ref_fwr_db['id'],
firewall_policy_id=id)
if insert_before:
position = ref_fwr_db.position
else:
position = ref_fwr_db.position + 1
else:
# If reference_firewall_rule_id is not set, it is assumed
# that the new rule needs to be inserted at the top.
# insert_before field is ignored.
# So default insertion is always at the top.
# Also note that position numbering starts at 1.
position = 1
return self._process_rule_for_policy(context, id, fwr_db,
position)
def remove_rule(self, context, id, rule_info):
LOG.debug("remove_rule() called")
self._validate_insert_remove_rule_request(id, rule_info)
firewall_rule_id = rule_info['firewall_rule_id']
if not firewall_rule_id:
raise f_exc.FirewallRuleNotFound(firewall_rule_id=None)
with context.session.begin(subtransactions=True):
fwr_db = self._get_firewall_rule(context, firewall_rule_id)
if fwr_db.firewall_policy_id != id:
raise f_exc.FirewallRuleNotAssociatedWithPolicy(
firewall_rule_id=fwr_db['id'],
firewall_policy_id=id)
return self._process_rule_for_policy(context, id, fwr_db, None)
def get_firewall_tenant_ids_on_host(self, context, host):
query = context.session.query(Firewall.tenant_id)
query = query.join(fw_r_ins_db.FirewallRouterAssociation)
query = query.join(l3agent_model.RouterL3AgentBinding,
l3agent_model.RouterL3AgentBinding.router_id ==
fw_r_ins_db.FirewallRouterAssociation.router_id)
query = query.join(agent_model.Agent)
query = query.filter(agent_model.Agent.host == host)
query = query.distinct()
return [item[0] for item in query]
def migration_callback(resource, event, trigger, **kwargs):
context = kwargs['context']
router = kwargs['router']
fw_plugin = directory.get_plugin(fwaas_constants.FIREWALL)
if fw_plugin:
tenant_firewalls = fw_plugin.get_firewalls(
context, filters={'tenant_id': [router['tenant_id']]})
if tenant_firewalls:
raise l3.RouterInUse(router_id=router['id'])
def subscribe():
registry.subscribe(
migration_callback, resources.ROUTER, events.BEFORE_UPDATE)
# NOTE(armax): multiple FW service plugins (potentially out of tree) may
# inherit from firewall_db and may need the callbacks to be processed. Having
# an implicit subscription (through the module import) preserves the existing
# behavior, and at the same time it avoids fixing it manually in each and
# every fw plugin out there. That said, The subscription is also made
# explicitly in the reference fw plugin. The subscription operation is
# idempotent so there is no harm in registering the same callback multiple
# times.
subscribe()
fw_id = sa.Column(sa.String(36),
sa.ForeignKey('firewalls.id', ondelete="CASCADE"),
primary_key=True)
router_id = sa.Column(sa.String(36),
sa.ForeignKey('routers.id', ondelete="CASCADE"),
primary_key=True)

View File

@ -1,98 +0,0 @@
# Copyright 2015 Cisco Systems 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.
from neutron_lib.db import model_base
from neutron_lib.exceptions import firewall_v1 as fwrtrins
from oslo_log import helpers as log_helpers
from oslo_log import log as logging
import sqlalchemy as sa
LOG = logging.getLogger(__name__)
class FirewallRouterAssociation(model_base.BASEV2):
"""Tracks FW Router Association"""
__tablename__ = 'firewall_router_associations'
fw_id = sa.Column(sa.String(36),
sa.ForeignKey('firewalls.id', ondelete="CASCADE"),
primary_key=True)
router_id = sa.Column(sa.String(36),
sa.ForeignKey('routers.id', ondelete="CASCADE"),
primary_key=True)
class FirewallRouterInsertionDbMixin(object):
"""Access methods for the firewall_router_associations table."""
@log_helpers.log_method_call
def set_routers_for_firewall(self, context, fw):
"""Sets the routers associated with the fw."""
with context.session.begin(subtransactions=True):
for r_id in fw['router_ids']:
fw_rtr_db = FirewallRouterAssociation(fw_id=fw['fw_id'],
router_id=r_id)
context.session.add(fw_rtr_db)
@log_helpers.log_method_call
def get_firewall_routers(self, context, fwid):
"""Gets all routers associated with a firewall."""
with context.session.begin(subtransactions=True):
fw_rtr_qry = context.session.query(
FirewallRouterAssociation.router_id)
fw_rtr_rows = fw_rtr_qry.filter_by(fw_id=fwid)
fw_rtrs = [entry.router_id for entry in fw_rtr_rows]
LOG.debug("get_firewall_routers(): fw_rtrs: %s", fw_rtrs)
return fw_rtrs
@log_helpers.log_method_call
def validate_firewall_routers_not_in_use(
self, context, router_ids, fwid=None):
"""Validate if router-ids not associated with any firewall.
If any of the router-ids in the list is already associated with
a firewall, raise an exception else just return.
"""
fw_rtr_qry = context.session.query(FirewallRouterAssociation.router_id)
fw_rtrs = fw_rtr_qry.filter(
FirewallRouterAssociation.router_id.in_(router_ids),
FirewallRouterAssociation.fw_id != fwid).all()
if fw_rtrs:
router_ids = [entry.router_id for entry in fw_rtrs]
raise fwrtrins.FirewallRouterInUse(router_ids=router_ids)
@log_helpers.log_method_call
def update_firewall_routers(self, context, fw):
"""Update the firewall with new routers.
This involves removing existing router associations and replacing
it with the new router associations provided in the update method.
"""
with context.session.begin(subtransactions=True):
fw_rtr_qry = context.session.query(FirewallRouterAssociation)
fw_rtr_qry.filter_by(fw_id=fw['fw_id']).delete()
if fw['router_ids']:
self.set_routers_for_firewall(context, fw)
# TODO(sridar): Investigate potential corner case if rpc failure
# happens on PENDING_UPDATE and agent did not restart. Evaluate
# complexity vs benefit of holding on to old entries until ack
# from agent.
return fw

View File

@ -12,8 +12,6 @@
from neutron_lib.db import model_base
from neutron_fwaas.db.firewall import firewall_db # noqa
from neutron_fwaas.db.firewall import firewall_router_insertion_db # noqa
from neutron_fwaas.db.firewall.v2 import firewall_db_v2 # noqa

View File

@ -12,7 +12,6 @@
import itertools
from neutron_fwaas.policies import firewall
from neutron_fwaas.policies import firewall_group
from neutron_fwaas.policies import firewall_policy
from neutron_fwaas.policies import firewall_rule
@ -20,7 +19,6 @@ from neutron_fwaas.policies import firewall_rule
def list_rules():
return itertools.chain(
firewall.list_rules(),
firewall_group.list_rules(),
firewall_policy.list_rules(),
firewall_rule.list_rules(),

View File

@ -1,113 +0,0 @@
# 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 neutron_fwaas.policies import base
rules = [
policy.RuleDefault(
'shared_firewalls',
'field:firewalls:shared=True',
'(FWaaS v1) Definition of shared firewalls'
),
policy.DocumentedRuleDefault(
'create_firewall',
base.RULE_ANY,
'(FWaaS v1) Create a firewall',
[
{
'method': 'POST',
'path': '/fw/firewalls',
},
]
),
policy.DocumentedRuleDefault(
'update_firewall',
base.RULE_ADMIN_OR_OWNER,
'(FWaaS v1) Update a firewall',
[
{
'method': 'PUT',
'path': '/fw/firewalls/{id}',
},
]
),
policy.DocumentedRuleDefault(
'delete_firewall',
base.RULE_ADMIN_OR_OWNER,
'(FWaaS v1) Delete a firewall',
[
{
'method': 'DELETE',
'path': '/fw/firewalls/{id}',
},
]
),
policy.DocumentedRuleDefault(
'create_firewall:shared',
base.RULE_ADMIN_ONLY,
'(FWaaS v1) Create a shared firewall',
[
{
'method': 'POST',
'path': '/fw/firewalls',
},
]
),
policy.DocumentedRuleDefault(
'update_firewall:shared',
base.RULE_ADMIN_ONLY,
'(FWaaS v1) Update ``shared`` attribute of a firewall',
[
{
'method': 'PUT',
'path': '/fw/firewalls/{id}',
},
]
),
# TODO(amotoki): Drop this rule as it has no effect.
policy.DocumentedRuleDefault(
'delete_firewall:shared',
base.RULE_ADMIN_ONLY,
'(FWaaS v1) Delete a shared firewall',
[
{
'method': 'DELETE',
'path': '/fw/firewalls/{id}',
},
]
),
policy.DocumentedRuleDefault(
'get_firewall',
'rule:admin_or_owner or rule:shared_firewalls',
'(FWaaS v1) Get firewalls',
[
{
'method': 'GET',
'path': '/fw/firewalls',
},
{
'method': 'GET',
'path': '/fw/firewalls/{id}',
},
]
),
]
def list_rules():
return rules

View File

@ -1,444 +0,0 @@
# Copyright 2013 Big Switch Networks, 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.
from neutron import service
from neutron_lib.api.definitions import firewall as fw_ext
from neutron_lib.api import extensions
from neutron_lib import constants as nl_constants
from neutron_lib import context as neutron_context
from neutron_lib.exceptions import firewall_v1 as f_exc
from neutron_lib.plugins import constants as plugin_constants
from neutron_lib.plugins import directory
from neutron_lib import rpc as n_rpc
from oslo_config import cfg
from oslo_log import log as logging
import oslo_messaging
from neutron_fwaas.common import fwaas_constants as f_const
from neutron_fwaas.db.firewall import firewall_db
from neutron_fwaas.db.firewall import firewall_router_insertion_db
LOG = logging.getLogger(__name__)
class FirewallCallbacks(object):
target = oslo_messaging.Target(version='1.0')
def __init__(self, plugin):
super(FirewallCallbacks, self).__init__()
self.plugin = plugin
def set_firewall_status(self, context, firewall_id, status, **kwargs):
"""Agent uses this to set a firewall's status."""
LOG.debug("Setting firewall %s to status: %s", firewall_id, status)
# Sanitize status first
if status in (nl_constants.ACTIVE, nl_constants.DOWN,
nl_constants.INACTIVE):
to_update = status
else:
to_update = nl_constants.ERROR
# ignore changing status if firewall expects to be deleted
# That case means that while some pending operation has been
# performed on the backend, neutron server received delete request
# and changed firewall status to PENDING_DELETE
updated = self.plugin.update_firewall_status(
context, firewall_id, to_update,
not_in=(nl_constants.PENDING_DELETE,))
if updated:
LOG.debug("firewall %s status set: %s", firewall_id, to_update)
return updated and to_update != nl_constants.ERROR
def firewall_deleted(self, context, firewall_id, **kwargs):
"""Agent uses this to indicate firewall is deleted."""
LOG.debug("firewall_deleted() called")
try:
with context.session.begin(subtransactions=True):
fw_db = self.plugin._get_firewall(context, firewall_id)
# allow to delete firewalls in ERROR state
if fw_db.status in (nl_constants.PENDING_DELETE,
nl_constants.ERROR):
self.plugin.delete_db_firewall_object(context, firewall_id)
return True
else:
LOG.warning('Firewall %(fw)s unexpectedly deleted by '
'agent, status was %(status)s',
{'fw': firewall_id, 'status': fw_db.status})
fw_db.update({"status": nl_constants.ERROR})
return False
except f_exc.FirewallNotFound:
LOG.info('Firewall %s already deleted', firewall_id)
return True
def get_firewalls_for_tenant(self, context, **kwargs):
"""Agent uses this to get all firewalls and rules for a tenant."""
LOG.debug("get_firewalls_for_tenant() called")
fw_list = []
for fw in self.plugin.get_firewalls(context):
fw_with_rules = self.plugin._make_firewall_dict_with_rules(
context, fw['id'])
if fw['status'] == nl_constants.PENDING_DELETE:
fw_with_rules['add-router-ids'] = []
fw_with_rules['del-router-ids'] = fw['router_ids']
else:
fw_with_rules['add-router-ids'] = fw['router_ids']
fw_with_rules['del-router-ids'] = []
fw_list.append(fw_with_rules)
return fw_list
def get_tenants_with_firewalls(self, context, **kwargs):
"""Agent uses this to get all tenants that have firewalls."""
LOG.debug("get_tenants_with_firewalls() called")
host = kwargs['host']
ctx = neutron_context.get_admin_context()
tenant_ids = self.plugin.get_firewall_tenant_ids_on_host(ctx, host)
return tenant_ids
class FirewallAgentApi(object):
"""Plugin side of plugin to agent RPC API."""
def __init__(self, topic, host):
self.host = host
target = oslo_messaging.Target(topic=topic, version='1.0')
self.client = n_rpc.get_client(target)
def _prepare_rpc_client(self, host=None):
if host:
return self.client.prepare(server=host)
else:
# historical behaviour (RPC broadcast)
return self.client.prepare(fanout=True)
def create_firewall(self, context, firewall, host=None):
cctxt = self._prepare_rpc_client(host)
# TODO(blallau) host param is not used on agent side (to be removed)
cctxt.cast(context, 'create_firewall', firewall=firewall,
host=self.host)
def update_firewall(self, context, firewall, host=None):
cctxt = self._prepare_rpc_client(host)
# TODO(blallau) host param is not used on agent side (to be removed)
cctxt.cast(context, 'update_firewall', firewall=firewall,
host=self.host)
def delete_firewall(self, context, firewall, host=None):
cctxt = self._prepare_rpc_client(host)
# TODO(blallau) host param is not used on agent side (to be removed)
cctxt.cast(context, 'delete_firewall', firewall=firewall,
host=self.host)
class FirewallPlugin(
firewall_db.Firewall_db_mixin,
firewall_router_insertion_db.FirewallRouterInsertionDbMixin):
"""Implementation of the Neutron Firewall Service Plugin.
This class manages the workflow of FWaaS request/response.
Most DB related works are implemented in class
firewall_db.Firewall_db_mixin.
"""
supported_extension_aliases = ["fwaas", "fwaasrouterinsertion"]
path_prefix = fw_ext.API_PREFIX
def __init__(self):
"""Do the initialization for the firewall service plugin here."""
self.agent_rpc = FirewallAgentApi(
f_const.FW_AGENT,
cfg.CONF.host
)
firewall_db.subscribe()
rpc_worker = service.RpcWorker([self], worker_process_count=0)
self.add_worker(rpc_worker)
def start_rpc_listeners(self):
self.endpoints = [FirewallCallbacks(self)]
self.conn = n_rpc.Connection()
self.conn.create_consumer(
f_const.FIREWALL_PLUGIN, self.endpoints, fanout=False)
return self.conn.consume_in_threads()
def _get_hosts_to_notify(self, context, router_ids):
"""Returns all hosts to send notification about firewall update"""
l3_plugin = directory.get_plugin(plugin_constants.L3)
no_broadcast = (
extensions.is_extension_supported(
l3_plugin, nl_constants.L3_AGENT_SCHEDULER_EXT_ALIAS) and
getattr(l3_plugin, 'get_l3_agents_hosting_routers', False))
if no_broadcast:
agents = l3_plugin.get_l3_agents_hosting_routers(
context, router_ids, admin_state_up=True, active=True)
return [a.host for a in agents]
# NOTE(blallau): default: FirewallAgentAPI performs RPC broadcast
return [None]
def _rpc_update_firewall(self, context, firewall_id):
status_update = {"firewall": {"status": nl_constants.PENDING_UPDATE}}
super(FirewallPlugin, self).update_firewall(context, firewall_id,
status_update)
fw_with_rules = self._make_firewall_dict_with_rules(context,
firewall_id)
# this is triggered on an update to fw rule or policy, no
# change in associated routers.
fw_update_rtrs = self.get_firewall_routers(context, firewall_id)
fw_with_rules['add-router-ids'] = fw_update_rtrs
fw_with_rules['del-router-ids'] = []
hosts = self._get_hosts_to_notify(context, fw_update_rtrs)
for host in hosts:
self.agent_rpc.update_firewall(context, fw_with_rules,
host=host)
def _rpc_update_firewall_policy(self, context, firewall_policy_id):
firewall_policy = self.get_firewall_policy(context, firewall_policy_id)
if firewall_policy:
for firewall_id in firewall_policy['firewall_list']:
self._rpc_update_firewall(context, firewall_id)
def _ensure_update_firewall(self, context, firewall_id):
fwall = self.get_firewall(context, firewall_id)
if fwall['status'] in [nl_constants.PENDING_CREATE,
nl_constants.PENDING_UPDATE,
nl_constants.PENDING_DELETE]:
raise f_exc.FirewallInPendingState(firewall_id=firewall_id,
pending_state=fwall['status'])
def _ensure_update_firewall_policy(self, context, firewall_policy_id):
firewall_policy = self.get_firewall_policy(context, firewall_policy_id)
if firewall_policy and 'firewall_list' in firewall_policy:
for firewall_id in firewall_policy['firewall_list']:
self._ensure_update_firewall(context, firewall_id)
def _ensure_update_firewall_rule(self, context, firewall_rule_id):
fw_rule = self.get_firewall_rule(context, firewall_rule_id)
if 'firewall_policy_id' in fw_rule and fw_rule['firewall_policy_id']:
self._ensure_update_firewall_policy(context,
fw_rule['firewall_policy_id'])
def _get_routers_for_create_firewall(self, tenant_id, context, firewall):
# pop router_id as this goes in the router association db
# and not firewall db
router_ids = firewall['firewall'].pop('router_ids', None)
if router_ids == nl_constants.ATTR_NOT_SPECIFIED:
# old semantics router-ids keyword not specified pick up
# all routers on tenant.
l3_plugin = directory.get_plugin(plugin_constants.L3)
ctx = neutron_context.get_admin_context()
routers = l3_plugin.get_routers(ctx)
router_ids = [
router['id']
for router in routers
if router['tenant_id'] == tenant_id]
# validation can still fail this if there is another fw
# which is associated with one of these routers.
self.validate_firewall_routers_not_in_use(context, router_ids)
return router_ids
else:
if not router_ids:
# This indicates that user specifies no routers.
return []
else:
# some router(s) provided.
self.validate_firewall_routers_not_in_use(context, router_ids)
return router_ids
def create_firewall(self, context, firewall):
LOG.debug("create_firewall() called")
fw_new_rtrs = self._get_routers_for_create_firewall(
firewall['firewall']['tenant_id'], context, firewall)
if not fw_new_rtrs:
# no messaging to agent needed, and fw needs to go
# to INACTIVE(no associated rtrs) state.
status = nl_constants.INACTIVE
fw = super(FirewallPlugin, self).create_firewall(
context, firewall, status)
fw['router_ids'] = []
return fw
else:
fw = super(FirewallPlugin, self).create_firewall(
context, firewall)
fw['router_ids'] = fw_new_rtrs
fw_with_rules = (
self._make_firewall_dict_with_rules(context, fw['id']))
fw_with_rtrs = {'fw_id': fw['id'],
'router_ids': fw_new_rtrs}
self.set_routers_for_firewall(context, fw_with_rtrs)
fw_with_rules['add-router-ids'] = fw_new_rtrs
fw_with_rules['del-router-ids'] = []
hosts = self._get_hosts_to_notify(context, fw_new_rtrs)
for host in hosts:
self.agent_rpc.create_firewall(context, fw_with_rules,
host=host)
return fw
def update_firewall(self, context, id, firewall):
LOG.debug("update_firewall() called on firewall %s", id)
self._ensure_update_firewall(context, id)
# pop router_id as this goes in the router association db
# and not firewall db
router_ids = firewall['firewall'].pop('router_ids', None)
fw_current_rtrs = fw_new_rtrs = self.get_firewall_routers(
context, id)
if router_ids is not None:
if router_ids == []:
# This indicates that user is indicating no routers.
fw_new_rtrs = []
else:
self.validate_firewall_routers_not_in_use(
context, router_ids, id)
fw_new_rtrs = router_ids
self.update_firewall_routers(context, {'fw_id': id,
'router_ids': fw_new_rtrs})
if not fw_new_rtrs and not fw_current_rtrs:
# no messaging to agent needed, and we need to continue
# in INACTIVE state
firewall['firewall']['status'] = nl_constants.INACTIVE
fw = super(FirewallPlugin, self).update_firewall(
context, id, firewall)
fw['router_ids'] = []
return fw
else:
firewall['firewall']['status'] = nl_constants.PENDING_UPDATE
fw = super(FirewallPlugin, self).update_firewall(
context, id, firewall)
fw['router_ids'] = fw_new_rtrs
fw_with_rules = (
self._make_firewall_dict_with_rules(context, fw['id']))
# determine rtrs to add fw to and del from
fw_with_rules['add-router-ids'] = fw_new_rtrs
fw_with_rules['del-router-ids'] = list(
set(fw_current_rtrs).difference(set(fw_new_rtrs)))
# last-router drives agent to ack with status to set state to INACTIVE
fw_with_rules['last-router'] = not fw_new_rtrs
LOG.debug("update_firewall %s: Add Routers: %s, Del Routers: %s",
fw['id'],
fw_with_rules['add-router-ids'],
fw_with_rules['del-router-ids'])
hosts = self._get_hosts_to_notify(context, list(
set(fw_new_rtrs).union(set(fw_current_rtrs))))
for host in hosts:
self.agent_rpc.update_firewall(context, fw_with_rules,
host=host)
return fw
def delete_db_firewall_object(self, context, id):
super(FirewallPlugin, self).delete_firewall(context, id)
def delete_firewall(self, context, id):
LOG.debug("delete_firewall() called on firewall %s", id)
fw_with_rules = (
self._make_firewall_dict_with_rules(context, id))
fw_delete_rtrs = self.get_firewall_routers(context, id)
fw_with_rules['del-router-ids'] = fw_delete_rtrs
fw_with_rules['add-router-ids'] = []
if not fw_with_rules['del-router-ids']:
# no routers to delete on the agent side
self.delete_db_firewall_object(context, id)
else:
status = {"firewall": {"status": nl_constants.PENDING_DELETE}}
super(FirewallPlugin, self).update_firewall(context, id, status)
# Reflect state change in fw_with_rules
fw_with_rules['status'] = status['firewall']['status']
hosts = self._get_hosts_to_notify(context, fw_delete_rtrs)
if hosts:
for host in hosts:
self.agent_rpc.delete_firewall(context, fw_with_rules,
host=host)
else:
# NOTE(blallau): we directly delete the firewall
# if router is not associated to an agent
self.delete_db_firewall_object(context, id)
def update_firewall_policy(self, context, id, firewall_policy):
LOG.debug("update_firewall_policy() called")
self._ensure_update_firewall_policy(context, id)
fwp = super(FirewallPlugin,
self).update_firewall_policy(context, id, firewall_policy)
self._rpc_update_firewall_policy(context, id)
return fwp
def update_firewall_rule(self, context, id, firewall_rule):
LOG.debug("update_firewall_rule() called")
self._ensure_update_firewall_rule(context, id)
fwr = super(FirewallPlugin,
self).update_firewall_rule(context, id, firewall_rule)
firewall_policy_id = fwr['firewall_policy_id']
if firewall_policy_id:
self._rpc_update_firewall_policy(context, firewall_policy_id)
return fwr
def _notify_firewall_updates(self, context, resource, update_info):
notifier = n_rpc.get_notifier('network')
notifier.info(context, resource, update_info)
def insert_rule(self, context, id, rule_info):
LOG.debug("insert_rule() called")
self._ensure_update_firewall_policy(context, id)
fwp = super(FirewallPlugin,
self).insert_rule(context, id, rule_info)
self._rpc_update_firewall_policy(context, id)
resource = 'firewall_policy.update.insert_rule'
self._notify_firewall_updates(context, resource, rule_info)
return fwp
def remove_rule(self, context, id, rule_info):
LOG.debug("remove_rule() called")
self._ensure_update_firewall_policy(context, id)
fwp = super(FirewallPlugin,
self).remove_rule(context, id, rule_info)
self._rpc_update_firewall_policy(context, id)
resource = 'firewall_policy.update.remove_rule'
self._notify_firewall_updates(context, resource, rule_info)
return fwp
def get_firewalls(self, context, filters=None, fields=None):
LOG.debug("fwaas get_firewalls() called")
has_id_field = not fields or 'id' in fields
if not has_id_field:
fields = fields + ['id']
fw_list = super(FirewallPlugin, self).get_firewalls(
context, filters, fields)
if not fields or 'router_ids' in fields:
for fw in fw_list:
fw['router_ids'] = self.get_firewall_routers(context, fw['id'])
if not has_id_field:
for fw in fw_list:
del fw['id']
return fw_list
def get_firewall(self, context, id, fields=None):
LOG.debug("fwaas get_firewall() called")
res = super(FirewallPlugin, self).get_firewall(
context, id, fields)
fw_current_rtrs = self.get_firewall_routers(context, id)
res['router_ids'] = fw_current_rtrs
return res

View File

@ -1,431 +0,0 @@
# 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.
from neutron.agent.linux import iptables_manager
from neutron.common import utils
from neutron_lib import constants
from neutron_lib.exceptions import firewall_v1 as f_exc
from oslo_log import log as logging
from neutron_fwaas.common import fwaas_constants as f_const
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
conntrack_base
from neutron_fwaas.services.firewall.service_drivers.agents.drivers import\
fwaas_base
LOG = logging.getLogger(__name__)
FWAAS_DRIVER_NAME = 'Fwaas iptables driver'
FWAAS_DEFAULT_CHAIN = 'fwaas-default-policy'
FWAAS_TO_IPTABLE_ACTION_MAP = {'allow': 'ACCEPT',
'deny': 'DROP',
'reject': 'REJECT'}
CHAIN_NAME_PREFIX = {constants.INGRESS_DIRECTION: 'i',
constants.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 = {constants.INGRESS_DIRECTION: '-o',
constants.EGRESS_DIRECTION: '-i'}
IPV4 = 'ipv4'
IPV6 = 'ipv6'
IP_VER_TAG = {IPV4: 'v4',
IPV6: 'v6'}
INTERNAL_DEV_PREFIX = 'qr-'
SNAT_INT_DEV_PREFIX = 'sg-'
ROUTER_2_FIP_DEV_PREFIX = 'rfp-'
class IptablesFwaasDriver(fwaas_base.FwaasDriverBase):
"""IPTables driver for Firewall As A Service."""
def __init__(self):
LOG.debug("Initializing fwaas iptables driver")
self.pre_firewall = None
self.conntrack = conntrack_base.load_and_init_conntrack_driver()
def create_firewall(self, agent_mode, 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(agent_mode, apply_list, firewall)
self._remove_conntrack_new_firewall(agent_mode,
apply_list, firewall)
self.pre_firewall = dict(firewall)
else:
self.apply_default_policy(agent_mode, 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 f_exc.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def _get_ipt_mgrs_with_if_prefix(self, agent_mode, router_info):
"""Gets the iptables manager along with the if prefix to apply rules.
With DVR we can have differing namespaces depending on which agent
(on Network or Compute node). Also, there is an associated i/f for
each namespace. The iptables on the relevant namespace and matching
i/f are provided. On the Network node we could have both the snat
namespace and a fip so this is provided back as a list - so in that
scenario rules can be applied on both.
"""
if not router_info.router.get('distributed'):
return [{'ipt': router_info.iptables_manager,
'if_prefix': INTERNAL_DEV_PREFIX}]
ipt_mgrs = []
# TODO(sridar): refactor to get strings to a common location.
if agent_mode == 'dvr_snat':
if router_info.snat_iptables_manager:
ipt_mgrs.append({'ipt': router_info.snat_iptables_manager,
'if_prefix': SNAT_INT_DEV_PREFIX})
if router_info.rtr_fip_connect:
# handle the fip case on n/w or compute node.
ipt_mgrs.append({'ipt': router_info.iptables_manager,
'if_prefix': ROUTER_2_FIP_DEV_PREFIX})
return ipt_mgrs
def delete_firewall(self, agent_mode, 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_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
agent_mode, router_info)
for ipt_if_prefix in ipt_if_prefix_list:
ipt_mgr = ipt_if_prefix['ipt']
self._remove_chains(fwid, ipt_mgr)
self._remove_default_chains(ipt_mgr)
# apply the changes immediately (no defer in firewall path)
ipt_mgr.defer_apply_off()
self.pre_firewall = None
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception("Failed to delete firewall: %s", fwid)
raise f_exc.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def update_firewall(self, agent_mode, 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(agent_mode, apply_list, firewall)
if self.pre_firewall:
self._remove_conntrack_updated_firewall(agent_mode,
apply_list, self.pre_firewall, firewall)
else:
self._remove_conntrack_new_firewall(agent_mode,
apply_list, firewall)
else:
self.apply_default_policy(agent_mode, apply_list, firewall)
self.pre_firewall = dict(firewall)
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception("Failed to update firewall: %s", firewall['id'])
raise f_exc.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def apply_default_policy(self, agent_mode, 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_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
agent_mode, router_info)
for ipt_if_prefix in ipt_if_prefix_list:
# the following only updates local memory; no hole in FW
ipt_mgr = ipt_if_prefix['ipt']
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_if_prefix)
# apply the changes immediately (no defer in firewall path)
ipt_mgr.defer_apply_off()
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(
"Failed to apply default policy on firewall: %s", fwid)
raise f_exc.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def _setup_firewall(self, agent_mode, apply_list, firewall):
fwid = firewall['id']
for router_info in apply_list:
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
agent_mode, router_info)
for ipt_if_prefix in ipt_if_prefix_list:
ipt_mgr = ipt_if_prefix['ipt']
# 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_if_prefix)
# apply the changes immediately (no defer in firewall path)
ipt_mgr.defer_apply_off()
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_if_prefix):
"""Create Fwaas chain using the rules in the policy
"""
fw_rules_list = firewall['firewall_rule_list']
fwid = firewall['id']
ipt_mgr = ipt_if_prefix['ipt']
#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, constants.INGRESS_DIRECTION)
ochain_name = self._get_chain_name(
fwid, ver, constants.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, constants.INGRESS_DIRECTION)
ochain_name = self._get_chain_name(
fwid, ver, constants.EGRESS_DIRECTION)
table.add_rule(ichain_name, iptbl_rule)
table.add_rule(ochain_name, iptbl_rule)
self._enable_policy_chain(fwid, ipt_if_prefix)
def _find_changed_rules(self, pre_firewall, firewall):
"""Find the rules changed between the current firewall
and the updating rule
"""
changed_rules = []
fw_rules_list = firewall[f_const.FIREWALL_RULE_LIST]
pre_fw_rules_list = pre_firewall[f_const.FIREWALL_RULE_LIST]
for pre_fw_rule in pre_fw_rules_list:
for fw_rule in fw_rules_list:
if (pre_fw_rule.get('id') == fw_rule.get('id') and
pre_fw_rule != fw_rule):
changed_rules.append(pre_fw_rule)
changed_rules.append(fw_rule)
return changed_rules
def _find_removed_rules(self, pre_firewall, firewall):
fw_rules_list = firewall[f_const.FIREWALL_RULE_LIST]
pre_fw_rules_list = pre_firewall[f_const.FIREWALL_RULE_LIST]
fw_rule_ids = [fw_rule.get('id') for fw_rule in fw_rules_list]
removed_rules = [pre_fw_rule for pre_fw_rule in
pre_fw_rules_list if pre_fw_rule.get('id') not in fw_rule_ids]
return removed_rules
def _find_new_rules(self, pre_firewall, firewall):
return self._find_removed_rules(firewall, pre_firewall)
def _remove_conntrack_new_firewall(self, agent_mode, apply_list, firewall):
"""Remove conntrack when create new firewall"""
routers_list = list(set(apply_list))
for router_info in routers_list:
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
agent_mode, router_info)
for ipt_if_prefix in ipt_if_prefix_list:
ipt_mgr = ipt_if_prefix['ipt']
self.conntrack.flush_entries(ipt_mgr.namespace)
def _remove_conntrack_updated_firewall(self, agent_mode,
apply_list, pre_firewall, firewall):
"""Remove conntrack when updated firewall"""
router_list = list(set(apply_list))
for router_info in router_list:
ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
agent_mode, router_info)
for ipt_if_prefix in ipt_if_prefix_list:
ipt_mgr = ipt_if_prefix['ipt']
ch_rules = self._find_changed_rules(pre_firewall,
firewall)
i_rules = self._find_new_rules(pre_firewall, firewall)
r_rules = self._find_removed_rules(pre_firewall, firewall)
removed_conntrack_rules_list = ch_rules + i_rules + r_rules
self.conntrack.delete_entries(removed_conntrack_rules_list,
ipt_mgr.namespace)
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 [constants.INGRESS_DIRECTION,
constants.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'].remove_chain(chain_name)
else:
ipt_mgr.ipv6['filter'].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_if_prefix):
bname = iptables_manager.binary_name
ipt_mgr = ipt_if_prefix['ipt']
if_prefix = ipt_if_prefix['if_prefix']
for (ver, tbl) in [(IPV4, ipt_mgr.ipv4['filter']),
(IPV6, ipt_mgr.ipv6['filter'])]:
for direction in [constants.INGRESS_DIRECTION,
constants.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 %s+ -j %s-%s' % (IPTABLES_DIR[direction],
if_prefix, 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 %s+ -j %s-%s' % (if_prefix, 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 %s+ -j %s-%s' % (if_prefix, 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):
action = FWAAS_TO_IPTABLE_ACTION_MAP[rule.get('action')]
# Output ordering is important here as it must exactly match what
# is returned by iptables-save. If not we risk unnecessarily removing
# and readding rules.
args = []
args += self._protocol_arg(rule.get('protocol'))
args += self._ip_prefix_arg('s', rule.get('source_ip_address'))
args += self._ip_prefix_arg('d', rule.get('destination_ip_address'))
# iptables adds '-m protocol' when any source
# or destination port number is specified
if (rule.get('source_port') is not None or
rule.get('destination_port') is not None):
args += self._match_arg(rule.get('protocol'))
args += self._port_arg('sport',
rule.get('protocol'),
rule.get('source_port'))
args += self._port_arg('dport',
rule.get('protocol'),
rule.get('destination_port'))
args += self._action_arg(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 RELATED,ESTABLISHED -j ACCEPT'
def _action_arg(self, action):
if not action:
return []
args = ['-j', action]
return args
def _protocol_arg(self, protocol):
if not protocol:
return []
args = ['-p', protocol]
return args
def _match_arg(self, protocol):
if not protocol:
return []
protocol_modules = {'udp': 'udp', 'tcp': 'tcp',
'icmp': 'icmp', 'ipv6-icmp': 'icmp6'}
# iptables adds '-m protocol' when the port number is specified
args = ['-m', protocol_modules[protocol]]
return args
def _port_arg(self, direction, protocol, port):
if protocol not in ['udp', 'tcp'] or port is None:
return []
args = ['--%s' % direction, '%s' % port]
return args
def _ip_prefix_arg(self, direction, ip_prefix):
if not(ip_prefix):
return []
args = ['-%s' % direction, '%s' % utils.ip_to_cidr(ip_prefix)]
return args

View File

@ -1,428 +0,0 @@
# Copyright (c) 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.
from neutron_lib.agent import l3_extension
from neutron_lib import constants as nl_constants
from neutron_lib import context
from neutron_lib.exceptions import firewall_v1 as fw_ext
from neutron_lib import rpc as n_rpc
from oslo_config import cfg
from oslo_log import helpers as log_helpers
from oslo_log import log as logging
from neutron_fwaas.common import fwaas_constants
from neutron_fwaas.common import resources as f_resources
from neutron_fwaas.services.firewall.service_drivers.agents \
import firewall_agent_api as api
from neutron_fwaas.services.firewall.service_drivers.agents \
import firewall_service
LOG = logging.getLogger(__name__)
#TODO(njohnston): There needs to be some extrapolation of the common code
# between this module and firewall_l3_agent_v2.py.
class FWaaSL3PluginApi(api.FWaaSPluginApiMixin):
"""Agent side of the FWaaS agent to FWaaS Plugin RPC API."""
def __init__(self, topic, host):
super(FWaaSL3PluginApi, self).__init__(topic, host)
def get_firewalls_for_tenant(self, context, **kwargs):
"""Get the Firewalls with rules from the Plugin to send to driver."""
LOG.debug("Retrieve Firewall with rules from Plugin")
cctxt = self.client.prepare()
return cctxt.call(context, 'get_firewalls_for_tenant', host=self.host)
def get_tenants_with_firewalls(self, context, **kwargs):
"""Get all Tenants that have Firewalls configured from plugin."""
LOG.debug("Retrieve Tenants with Firewalls configured from Plugin")
cctxt = self.client.prepare()
return cctxt.call(context,
'get_tenants_with_firewalls', host=self.host)
class FWaaSL3AgentExtension(l3_extension.L3AgentExtension):
"""FWaaS Agent support to be used by Neutron L3 agent."""
SUPPORTED_RESOURCE_TYPES = [f_resources.FIREWALL_GROUP,
f_resources.FIREWALL_POLICY,
f_resources.FIREWALL_RULE]
def initialize(self, connection, driver_type):
self._register_rpc_consumers(connection)
def consume_api(self, agent_api):
LOG.debug("FWaaS consume_api call occurred with %s", agent_api)
self.agent_api = agent_api
def _register_rpc_consumers(self, connection):
#TODO(njohnston): Add RPC consumer connection loading here.
pass
def start_rpc_listeners(self, conf):
self.endpoints = [self]
self.conn = n_rpc.Connection()
self.conn.create_consumer(
fwaas_constants.FW_AGENT, self.endpoints, fanout=False)
return self.conn.consume_in_threads()
def __init__(self, host, conf):
LOG.debug("Initializing firewall agent")
self.agent_api = None
self.neutron_service_plugins = None
self.conf = conf
self.fwaas_enabled = cfg.CONF.fwaas.enabled
self.start_rpc_listeners(conf)
# None means l3-agent has no information on the server
# configuration due to the lack of RPC support.
if self.neutron_service_plugins is not None:
fwaas_plugin_configured = (fwaas_constants.FIREWALL
in self.neutron_service_plugins)
if fwaas_plugin_configured and not self.fwaas_enabled:
msg = ("FWaaS plugin is configured in the server side, but "
"FWaaS is disabled in L3-agent.")
LOG.error(msg)
raise SystemExit(1)
self.fwaas_enabled = self.fwaas_enabled and fwaas_plugin_configured
if self.fwaas_enabled:
# NOTE: Temp location for creating service and loading driver
self.fw_service = firewall_service.FirewallService()
self.fwaas_driver = self.fw_service.load_device_drivers()
self.services_sync_needed = False
# setup RPC to msg fwaas plugin
self.fwplugin_rpc = FWaaSL3PluginApi(fwaas_constants.FIREWALL_PLUGIN,
host)
def _has_router_insertion_fields(self, fw):
return 'add-router-ids' in fw
def _get_router_ids_for_fw(self, context, fw, to_delete=False):
"""Return the router_ids either from fw dict or tenant routers."""
if self._has_router_insertion_fields(fw):
# it is a new version of plugin
return (fw['del-router-ids'] if to_delete
else fw['add-router-ids'])
else:
return [router['id'] for router in
self.agent_api.get_routers_in_project(fw['tenant_id'])]
def _get_routers_in_project(self, project_id):
if self.agent_api is None:
LOG.exception("FWaaS RPC call failed; L3 agent_api failure")
return self.agent_api.get_routers_in_project(project_id)
def _get_router_info_list_for_tenant(self, router_ids, tenant_id):
"""Returns the list of router info objects on which to apply the fw."""
return [ri for ri in self._get_routers_in_project(tenant_id)
if ri.router_id in router_ids and
self.agent_api.is_router_in_namespace(ri.router_id)]
def _invoke_driver_for_sync_from_plugin(self, ctx, router_info_list, fw):
"""Invoke the delete driver method for status of PENDING_DELETE and
update method for all other status to (re)apply on driver which is
Idempotent.
"""
if fw['status'] == nl_constants.PENDING_DELETE:
try:
self.fwaas_driver.delete_firewall(
self.conf.agent_mode,
router_info_list,
fw)
self.fwplugin_rpc.firewall_deleted(
ctx,
fw['id'])
except fw_ext.FirewallInternalDriverError:
LOG.error("Firewall Driver Error on fw state %(fwmsg)s "
"for fw: %(fwid)s",
{'fwmsg': fw['status'], 'fwid': fw['id']})
self.fwplugin_rpc.set_firewall_status(
ctx,
fw['id'],
nl_constants.ERROR)
else:
# PENDING_UPDATE, PENDING_CREATE, ...
try:
self.fwaas_driver.update_firewall(
self.conf.agent_mode,
router_info_list,
fw)
if fw['admin_state_up']:
status = nl_constants.ACTIVE
else:
status = nl_constants.DOWN
except fw_ext.FirewallInternalDriverError:
LOG.error("Firewall Driver Error on fw state %(fwmsg)s "
"for fw: %(fwid)s",
{'fwmsg': fw['status'], 'fwid': fw['id']})
status = nl_constants.ERROR
self.fwplugin_rpc.set_firewall_status(
ctx,
fw['id'],
status)
def _process_router_add(self, router):
"""On router add, get fw with rules from plugin and update driver."""
LOG.debug("Process router add, router_id: '%s'", router['id'])
router_ids = router['id']
router_info_list = self._get_router_info_list_for_tenant(
[router_ids],
router['tenant_id'])
if router_info_list:
# Get the firewall with rules
# for the tenant the router is on.
ctx = context.Context('', router['tenant_id'])
fw_list = self.fwplugin_rpc.get_firewalls_for_tenant(ctx)
for fw in fw_list:
if self._has_router_insertion_fields(fw):
# if router extension present apply only if router in fw
if (not (router_ids in fw['add-router-ids']) and
not (router_ids in fw['del-router-ids'])):
continue
self._invoke_driver_for_sync_from_plugin(
ctx,
router_info_list,
fw)
# router can be present only on one fw
return
def add_router(self, context, new_router):
"""On router add, get fw with rules from plugin and update driver.
Handles agent restart, when a router is added, query the plugin to
check if this router is in the router list for any firewall. If so
install firewall rules on this router.
"""
# avoid msg to plugin when fwaas is not configured
if not self.fwaas_enabled:
return
try:
self._process_router_add(new_router)
except Exception:
LOG.exception(
"FWaaS RPC info call failed for '%s'.", new_router['id'])
self.services_sync_needed = True
def update_router(self, context, updated_router):
"""The update_router method is just a synonym for add_router"""
self.add_router(context, updated_router)
def delete_router(self, context, new_router):
"""Handles router deletion. There is basically nothing to do for this
in the context of FWaaS with an IPTables driver; the namespace will
already have been deleted, taking the IPTables rules with it.
"""
#TODO(njohnston): When another firewall driver is implemented, look at
# expanding this out so that the driver can handle deletion calls.
pass
def process_services_sync(self, ctx):
if not self.services_sync_needed:
return
"""On RPC issues sync with plugin and apply the sync data."""
# avoid msg to plugin when fwaas is not configured
if not self.fwaas_enabled:
return
try:
# get the list of tenants with firewalls configured
# from the plugin
tenant_ids = self.fwplugin_rpc.get_tenants_with_firewalls(ctx)
LOG.debug("Tenants with Firewalls: '%s'", tenant_ids)
for tenant_id in tenant_ids:
ctx = context.Context('', tenant_id)
fw_list = self.fwplugin_rpc.get_firewalls_for_tenant(ctx)
for fw in fw_list:
if fw['status'] == nl_constants.PENDING_DELETE:
self.delete_firewall(ctx, fw, self.host)
# no need to apply sync data for ACTIVE fw
elif fw['status'] != nl_constants.ACTIVE:
self.update_firewall(ctx, fw, self.host)
self.services_sync_needed = False
except Exception:
LOG.exception("Failed fwaas process services sync")
self.services_sync_needed = True
@log_helpers.log_method_call
def create_firewall(self, context, firewall, host):
"""Handle Rpc from plugin to create a firewall."""
router_ids = self._get_router_ids_for_fw(context, firewall)
if not router_ids:
return
router_info_list = self._get_router_info_list_for_tenant(
router_ids,
firewall['tenant_id'])
LOG.debug("Create: Add firewall on Router List: '%s'",
[ri.router['id'] for ri in router_info_list])
# call into the driver
try:
self.fwaas_driver.create_firewall(
self.conf.agent_mode,
router_info_list,
firewall)
if firewall['admin_state_up']:
status = nl_constants.ACTIVE
else:
status = nl_constants.DOWN
except fw_ext.FirewallInternalDriverError:
LOG.error("Firewall Driver Error for create_firewall "
"for firewall: %s", firewall['id'])
status = nl_constants.ERROR
try:
# send status back to plugin
self.fwplugin_rpc.set_firewall_status(
context,
firewall['id'],
status)
except Exception:
LOG.exception("FWaaS RPC failure in create_firewall "
"for firewall: %s", firewall['id'])
self.services_sync_needed = True
@log_helpers.log_method_call
def update_firewall(self, context, firewall, host):
"""Handle Rpc from plugin to update a firewall."""
status = ""
if self._has_router_insertion_fields(firewall):
# with the router_ids extension, we may need to delete and add
# based on the list of routers. On the older version, we just
# update (add) all routers on the tenant - delete not needed.
router_ids = self._get_router_ids_for_fw(
context, firewall, to_delete=True)
if router_ids:
router_info_list = self._get_router_info_list_for_tenant(
router_ids,
firewall['tenant_id'])
# remove the firewall from this set of routers
# but no ack sent yet, check if we need to add
LOG.debug("Update: Delete firewall on Router List: '%s'",
[ri.router['id'] for ri in router_info_list])
try:
self.fwaas_driver.delete_firewall(
self.conf.agent_mode,
router_info_list,
firewall)
if firewall['last-router']:
status = nl_constants.INACTIVE
elif firewall['admin_state_up']:
status = nl_constants.ACTIVE
else:
status = nl_constants.DOWN
except fw_ext.FirewallInternalDriverError:
LOG.error(
"Firewall Driver Error for "
"update_firewall for firewall: %s", firewall['id'])
status = nl_constants.ERROR
# handle the add router and/or rule, policy, firewall
# attribute updates
if status not in (nl_constants.ERROR, nl_constants.INACTIVE):
router_ids = self._get_router_ids_for_fw(context, firewall)
if router_ids or firewall['router_ids']:
router_info_list = self._get_router_info_list_for_tenant(
router_ids + firewall['router_ids'],
firewall['tenant_id'])
LOG.debug("Update: Add firewall on Router List: '%s'",
[ri.router['id'] for ri in router_info_list])
# call into the driver
try:
self.fwaas_driver.update_firewall(
self.conf.agent_mode,
router_info_list,
firewall)
if firewall['admin_state_up']:
status = nl_constants.ACTIVE
else:
status = nl_constants.DOWN
except fw_ext.FirewallInternalDriverError:
LOG.error(
"Firewall Driver Error for "
"update_firewall for firewall: %s", firewall['id'])
status = nl_constants.ERROR
else:
status = nl_constants.INACTIVE
try:
# send status back to plugin
self.fwplugin_rpc.set_firewall_status(
context,
firewall['id'],
status)
except Exception:
LOG.exception("FWaaS RPC failure in update_firewall "
"for firewall: %s", firewall['id'])
self.services_sync_needed = True
@log_helpers.log_method_call
def delete_firewall(self, context, firewall, host):
"""Handle Rpc from plugin to delete a firewall."""
router_ids = self._get_router_ids_for_fw(
context, firewall, to_delete=True)
if router_ids:
router_info_list = self._get_router_info_list_for_tenant(
router_ids,
firewall['tenant_id'])
LOG.debug(
"Delete firewall %(fw)s on routers: '%(routers)s'",
{'fw': firewall['id'],
'routers': [ri.router['id'] for ri in router_info_list]})
# call into the driver
try:
self.fwaas_driver.delete_firewall(
self.conf.agent_mode,
router_info_list,
firewall)
if firewall['admin_state_up']:
status = nl_constants.ACTIVE
else:
status = nl_constants.DOWN
except fw_ext.FirewallInternalDriverError:
LOG.error("Firewall Driver Error for delete_firewall "
"for firewall: %s", firewall['id'])
status = nl_constants.ERROR
try:
# send status back to plugin
if status in [nl_constants.ACTIVE, nl_constants.DOWN]:
self.fwplugin_rpc.firewall_deleted(context, firewall['id'])
else:
self.fwplugin_rpc.set_firewall_status(
context,
firewall['id'],
status)
except Exception:
LOG.exception("FWaaS RPC failure in delete_firewall "
"for firewall: %s", firewall['id'])
self.services_sync_needed = True
def ha_state_change(self, context, data):
pass
class L3WithFWaaS(FWaaSL3AgentExtension):
def __init__(self, conf=None):
if conf:
self.conf = conf
else:
self.conf = cfg.CONF
super(L3WithFWaaS, self).__init__(host=self.conf.host, conf=self.conf)

View File

@ -22,9 +22,10 @@ from neutron_fwaas.db.models import head
# EXTERNAL_TABLES should contain all names of tables that are not related to
# current repo.
EXTERNAL_TABLES = set(external.TABLES) - set(external.FWAAS_TABLES)
EXTERNAL_TABLES = set(external.TABLES)
# Model moved to vendor repo
EXTERNAL_TABLES.update({'cisco_firewall_associations'})
EXTERNAL_TABLES.update({'firewall_router_associations'})
VERSION_TABLE = 'alembic_version_fwaas'

View File

@ -1,22 +0,0 @@
# Copyright (c) 2015 Midokura SARL
# 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 tempest.api.network import base
from neutron_fwaas.tests.tempest_plugin.tests import fwaas_client
class BaseFWaaSTest(fwaas_client.FWaaSClientMixin, base.BaseNetworkTest):
pass

View File

@ -1,447 +0,0 @@
# Copyright 2014 NEC Corporation. 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.
import six
from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from neutron_fwaas.tests.tempest_plugin.tests.api import base
CONF = config.CONF
class FWaaSExtensionTestJSON(base.BaseFWaaSTest):
"""
Tests the following operations in the Neutron API using the REST client for
Neutron:
List firewall rules
Create firewall rule
Update firewall rule
Delete firewall rule
Show firewall rule
List firewall policies
Create firewall policy
Update firewall policy
Insert firewall rule to policy
Remove firewall rule from policy
Insert firewall rule after/before rule in policy
Update firewall policy audited attribute
Delete firewall policy
Show firewall policy
List firewall
Create firewall
Update firewall
Delete firewall
Show firewall
"""
@classmethod
def resource_setup(cls):
super(FWaaSExtensionTestJSON, cls).resource_setup()
if not utils.is_extension_enabled('fwaas', 'network'):
msg = "FWaaS Extension not enabled."
raise cls.skipException(msg)
def setUp(self):
super(FWaaSExtensionTestJSON, self).setUp()
self.fw_rule = self.create_firewall_rule(action="allow",
protocol="tcp")
self.fw_policy = self.create_firewall_policy()
def _try_delete_router(self, router):
# delete router, if it exists
try:
self.delete_router(router)
# if router is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
def _try_delete_policy(self, policy_id):
# delete policy, if it exists
try:
self.firewall_policies_client.delete_firewall_policy(policy_id)
# if policy is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
def _try_delete_rule(self, rule_id):
# delete rule, if it exists
try:
self.firewall_rules_client.delete_firewall_rule(rule_id)
# if rule is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
def _try_delete_firewall(self, fw_id):
# delete firewall, if it exists
try:
self.firewalls_client.delete_firewall(fw_id)
# if firewall is not found, this means it was deleted in the test
except lib_exc.NotFound:
pass
self.firewalls_client.wait_for_resource_deletion(fw_id)
def _wait_until_ready(self, fw_id):
target_states = ('ACTIVE', 'CREATED')
def _wait():
firewall = self.firewalls_client.show_firewall(fw_id)
firewall = firewall['firewall']
return firewall['status'] in target_states
if not test_utils.call_until_true(_wait, CONF.network.build_timeout,
CONF.network.build_interval):
m = ("Timed out waiting for firewall %s to reach %s state(s)" %
(fw_id, target_states))
raise lib_exc.TimeoutException(m)
def _wait_until_deleted(self, fw_id):
def _wait():
try:
firewall = self.firewalls_client.show_firewall(fw_id)
except lib_exc.NotFound:
return True
fw_status = firewall['firewall']['status']
if fw_status == 'ERROR':
raise lib_exc.DeleteErrorException(resource_id=fw_id)
if not test_utils.call_until_true(_wait, CONF.network.build_timeout,
CONF.network.build_interval):
m = ("Timed out waiting for firewall %s deleted" % fw_id)
raise lib_exc.TimeoutException(m)
@decorators.idempotent_id('1b84cf01-9c09-4ce7-bc72-b15e39076468')
@decorators.attr(type='smoke')
def test_list_firewall_rules(self):
# List firewall rules
fw_rules = self.firewall_rules_client.list_firewall_rules()
fw_rules = fw_rules['firewall_rules']
self.assertIn((self.fw_rule['id'],
self.fw_rule['name'],
self.fw_rule['action'],
self.fw_rule['protocol'],
self.fw_rule['ip_version'],
self.fw_rule['enabled']),
[(m['id'],
m['name'],
m['action'],
m['protocol'],
m['ip_version'],
m['enabled']) for m in fw_rules])
@decorators.idempotent_id('563564f7-7077-4f5e-8cdc-51f37ae5a2b9')
@decorators.attr(type='smoke')
def test_create_update_delete_firewall_rule(self):
# Create firewall rule
body = self.firewall_rules_client.create_firewall_rule(
name=data_utils.rand_name("fw-rule"),
action="allow",
protocol="tcp")
fw_rule_id = body['firewall_rule']['id']
self.addCleanup(self._try_delete_rule, fw_rule_id)
# Update firewall rule
body = self.firewall_rules_client.update_firewall_rule(fw_rule_id,
action="deny")
self.assertEqual("deny", body["firewall_rule"]['action'])
# Delete firewall rule
self.firewall_rules_client.delete_firewall_rule(fw_rule_id)
# Confirm deletion
fw_rules = self.firewall_rules_client.list_firewall_rules()
self.assertNotIn(fw_rule_id,
[m['id'] for m in fw_rules['firewall_rules']])
@decorators.idempotent_id('3ff8c08e-26ff-4034-ae48-810ed213a998')
@decorators.attr(type='smoke')
def test_show_firewall_rule(self):
# show a created firewall rule
fw_rule = self.firewall_rules_client.show_firewall_rule(
self.fw_rule['id'])
for key, value in six.iteritems(fw_rule['firewall_rule']):
self.assertEqual(self.fw_rule[key], value)
@decorators.idempotent_id('1086dd93-a4c0-4bbb-a1bd-6d4bc62c199f')
@decorators.attr(type='smoke')
def test_list_firewall_policies(self):
fw_policies = self.firewall_policies_client.list_firewall_policies()
fw_policies = fw_policies['firewall_policies']
self.assertIn((self.fw_policy['id'],
self.fw_policy['name'],
self.fw_policy['firewall_rules']),
[(m['id'],
m['name'],
m['firewall_rules']) for m in fw_policies])
@decorators.idempotent_id('bbf37b6c-498c-421e-9c95-45897d3ed775')
@decorators.attr(type='smoke')
def test_create_update_delete_firewall_policy(self):
# Create firewall policy
body = self.firewall_policies_client.create_firewall_policy(
name=data_utils.rand_name("fw-policy"))
fw_policy_id = body['firewall_policy']['id']
self.addCleanup(self._try_delete_policy, fw_policy_id)
# Update firewall policy
body = self.firewall_policies_client.update_firewall_policy(
fw_policy_id,
name="updated_policy")
updated_fw_policy = body["firewall_policy"]
self.assertEqual("updated_policy", updated_fw_policy['name'])
# Delete firewall policy
self.firewall_policies_client.delete_firewall_policy(fw_policy_id)
# Confirm deletion
fw_policies = self.firewall_policies_client.list_firewall_policies()
fw_policies = fw_policies['firewall_policies']
self.assertNotIn(fw_policy_id, [m['id'] for m in fw_policies])
@decorators.idempotent_id('1df59b3a-517e-41d4-96f6-fc31cf4ecff2')
@decorators.attr(type='smoke')
def test_show_firewall_policy(self):
# show a created firewall policy
fw_policy = self.firewall_policies_client.show_firewall_policy(
self.fw_policy['id'])
fw_policy = fw_policy['firewall_policy']
for key, value in six.iteritems(fw_policy):
self.assertEqual(self.fw_policy[key], value)
@decorators.idempotent_id('02082a03-3cdd-4789-986a-1327dd80bfb7')
@decorators.attr(type='smoke')
def test_create_show_delete_firewall(self):
# Create tenant network resources required for an ACTIVE firewall
network = self.create_network()
subnet = self.create_subnet(network)
router = self.create_router(
data_utils.rand_name('router-'),
admin_state_up=True)
self.addCleanup(self._try_delete_router, router)
self.routers_client.add_router_interface(router['id'],
subnet_id=subnet['id'])
# Create firewall
body = self.firewalls_client.create_firewall(
name=data_utils.rand_name("firewall"),
firewall_policy_id=self.fw_policy['id'])
created_firewall = body['firewall']
firewall_id = created_firewall['id']
self.addCleanup(self._try_delete_firewall, firewall_id)
# Wait for the firewall resource to become ready
self._wait_until_ready(firewall_id)
# show a created firewall
firewall = self.firewalls_client.show_firewall(firewall_id)
firewall = firewall['firewall']
for key, value in six.iteritems(firewall):
if key == 'status':
continue
self.assertEqual(created_firewall[key], value)
# list firewall
firewalls = self.firewalls_client.list_firewalls()
firewalls = firewalls['firewalls']
self.assertIn((created_firewall['id'],
created_firewall['name'],
created_firewall['firewall_policy_id']),
[(m['id'],
m['name'],
m['firewall_policy_id']) for m in firewalls])
# Delete firewall
self.firewalls_client.delete_firewall(firewall_id)
# Wait for the firewall resource to be deleted
self._wait_until_deleted(firewall_id)
# Confirm deletion
firewalls = self.firewalls_client.list_firewalls()['firewalls']
self.assertNotIn(firewall_id, [m['id'] for m in firewalls])
@decorators.idempotent_id('1355cf5c-77d4-4bb9-87d7-e50c194d08b5')
def test_firewall_insertion_mode_add_remove_router(self):
# Create legacy routers
router1 = self.create_router(
data_utils.rand_name('router-'),
admin_state_up=True)
self.addCleanup(self._try_delete_router, router1)
router2 = self.create_router(
data_utils.rand_name('router-'),
admin_state_up=True)
self.addCleanup(self._try_delete_router, router2)
# Create firewall on a router1
body = self.firewalls_client.create_firewall(
name=data_utils.rand_name("firewall"),
firewall_policy_id=self.fw_policy['id'],
router_ids=[router1['id']])
created_firewall = body['firewall']
firewall_id = created_firewall['id']
self.addCleanup(self._try_delete_firewall, firewall_id)
self.assertEqual([router1['id']], created_firewall['router_ids'])
# Legacy routers are scheduled on L3 agents on network plug events
# Hence firewall resource will not became ready at this stage
network = self.create_network()
subnet = self.create_subnet(network)
self.routers_client.add_router_interface(router1['id'],
subnet_id=subnet['id'])
# Wait for the firewall resource to become ready
self._wait_until_ready(firewall_id)
# Add router2 to the firewall
body = self.firewalls_client.update_firewall(
firewall_id, router_ids=[router1['id'], router2['id']])
updated_firewall = body['firewall']
self.assertIn(router2['id'], updated_firewall['router_ids'])
self.assertEqual(2, len(updated_firewall['router_ids']))
# Wait for the firewall resource to become ready
self._wait_until_ready(firewall_id)
# Remove router1 from the firewall
body = self.firewalls_client.update_firewall(
firewall_id, router_ids=[router2['id']])
updated_firewall = body['firewall']
self.assertNotIn(router1['id'], updated_firewall['router_ids'])
self.assertEqual(1, len(updated_firewall['router_ids']))
@decorators.idempotent_id('c60ceff5-d51f-451d-b6e6-cb983d16ab6b')
def test_firewall_insertion_mode_one_firewall_per_router(self):
# Create router required for an ACTIVE firewall
router = self.create_router(
data_utils.rand_name('router1-'),
admin_state_up=True)
self.addCleanup(self._try_delete_router, router)
# Create firewall
body = self.firewalls_client.create_firewall(
name=data_utils.rand_name("firewall"),
firewall_policy_id=self.fw_policy['id'],
router_ids=[router['id']])
created_firewall = body['firewall']
self.addCleanup(self._try_delete_firewall, created_firewall['id'])
# Try to create firewall with the same router
self.assertRaisesRegex(
lib_exc.Conflict,
"already associated with other firewall",
self.firewalls_client.create_firewall,
name=data_utils.rand_name("firewall"),
firewall_policy_id=self.fw_policy['id'],
router_ids=[router['id']])
@decorators.attr(type='smoke')
@decorators.idempotent_id('53305b4b-9897-4e01-87c0-2ae386083180')
def test_firewall_rule_insertion_position_removal_rule_from_policy(self):
# Create firewall rule
body = self.firewall_rules_client.create_firewall_rule(
name=data_utils.rand_name("fw-rule"),
action="allow",
protocol="tcp")
fw_rule_id1 = body['firewall_rule']['id']
self.addCleanup(self._try_delete_rule, fw_rule_id1)
# Create firewall policy
body = self.firewall_policies_client.create_firewall_policy(
name=data_utils.rand_name("fw-policy"))
fw_policy_id = body['firewall_policy']['id']
self.addCleanup(self._try_delete_policy, fw_policy_id)
# Insert rule to firewall policy
self.firewall_policies_client.insert_firewall_rule_in_policy(
fw_policy_id, fw_rule_id1, '', '')
# Verify insertion of rule in policy
self.assertIn(fw_rule_id1, self._get_list_fw_rule_ids(fw_policy_id))
# Create another firewall rule
body = self.firewall_rules_client.create_firewall_rule(
name=data_utils.rand_name("fw-rule"),
action="allow",
protocol="icmp")
fw_rule_id2 = body['firewall_rule']['id']
self.addCleanup(self._try_delete_rule, fw_rule_id2)
# Insert rule to firewall policy after the first rule
self.firewall_policies_client.insert_firewall_rule_in_policy(
fw_policy_id, fw_rule_id2, fw_rule_id1, '')
# Verify the position of rule after insertion
fw_rule = self.firewall_rules_client.show_firewall_rule(
fw_rule_id2)
self.assertEqual(int(fw_rule['firewall_rule']['position']), 2)
# Remove rule from the firewall policy
self.firewall_policies_client.remove_firewall_rule_from_policy(
fw_policy_id, fw_rule_id2)
# Insert rule to firewall policy before the first rule
self.firewall_policies_client.insert_firewall_rule_in_policy(
fw_policy_id, fw_rule_id2, '', fw_rule_id1)
# Verify the position of rule after insertion
fw_rule = self.firewall_rules_client.show_firewall_rule(
fw_rule_id2)
self.assertEqual(int(fw_rule['firewall_rule']['position']), 1)
# Remove rule from the firewall policy
self.firewall_policies_client.remove_firewall_rule_from_policy(
fw_policy_id, fw_rule_id2)
# Verify removal of rule from firewall policy
self.assertNotIn(fw_rule_id2, self._get_list_fw_rule_ids(fw_policy_id))
# Remove rule from the firewall policy
self.firewall_policies_client.remove_firewall_rule_from_policy(
fw_policy_id, fw_rule_id1)
# Verify removal of rule from firewall policy
self.assertNotIn(fw_rule_id1, self._get_list_fw_rule_ids(fw_policy_id))
def _get_list_fw_rule_ids(self, fw_policy_id):
fw_policy = self.firewall_policies_client.show_firewall_policy(
fw_policy_id)
return [ruleid for ruleid in fw_policy['firewall_policy']
['firewall_rules']]
@decorators.idempotent_id('8515ca8a-0d2f-4298-b5ff-6f924e4587ca')
def test_update_firewall_policy_audited_attribute(self):
# Create firewall rule
body = self.firewall_rules_client.create_firewall_rule(
name=data_utils.rand_name("fw-rule"),
action="allow",
protocol="icmp")
fw_rule_id = body['firewall_rule']['id']
self.addCleanup(self._try_delete_rule, fw_rule_id)
# Create firewall policy
body = self.firewall_policies_client.create_firewall_policy(
name=data_utils.rand_name('fw-policy'))
fw_policy_id = body['firewall_policy']['id']
self.addCleanup(self._try_delete_policy, fw_policy_id)
self.assertFalse(body['firewall_policy']['audited'])
# Update firewall policy audited attribute to true
self.firewall_policies_client.update_firewall_policy(fw_policy_id,
audited=True)
# Insert Firewall rule to firewall policy
self.firewall_policies_client.insert_firewall_rule_in_policy(
fw_policy_id, fw_rule_id, '', '')
body = self.firewall_policies_client.show_firewall_policy(
fw_policy_id)
self.assertFalse(body['firewall_policy']['audited'])

View File

@ -1,122 +0,0 @@
# Copyright (c) 2015 Midokura SARL
# 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.
import time
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions as lib_exc
from neutron_fwaas.tests.tempest_plugin.services import client
from neutron_lib import constants as nl_constants
CONF = config.CONF
class FWaaSClientMixin(object):
@classmethod
def resource_setup(cls):
super(FWaaSClientMixin, cls).resource_setup()
manager = cls.os_primary
default_params = config.service_client_config()
cls.firewalls_client = client.FirewallsClient(
manager.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**default_params)
cls.firewall_policies_client = client.FirewallPoliciesClient(
manager.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**default_params)
cls.firewall_rules_client = client.FirewallRulesClient(
manager.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**default_params)
def create_firewall_rule(self, **kwargs):
body = self.firewall_rules_client.create_firewall_rule(
name=data_utils.rand_name("fw-rule"),
**kwargs)
fw_rule = body['firewall_rule']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.firewall_rules_client.delete_firewall_rule,
fw_rule['id'])
return fw_rule
def create_firewall_policy(self, **kwargs):
body = self.firewall_policies_client.create_firewall_policy(
name=data_utils.rand_name("fw-policy"),
**kwargs)
fw_policy = body['firewall_policy']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.firewall_policies_client.delete_firewall_policy,
fw_policy['id'])
return fw_policy
def create_firewall(self, **kwargs):
body = self.firewalls_client.create_firewall(
name=data_utils.rand_name("fw"),
**kwargs)
fw = body['firewall']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.delete_firewall_and_wait,
fw['id'])
return fw
def delete_firewall_and_wait(self, firewall_id):
self.firewalls_client.delete_firewall(firewall_id)
self._wait_firewall_while(firewall_id, [nl_constants.PENDING_DELETE],
not_found_ok=True)
def _wait_firewall_ready(self, firewall_id):
self._wait_firewall_while(firewall_id,
[nl_constants.PENDING_CREATE,
nl_constants.PENDING_UPDATE])
def _wait_firewall_while(self, firewall_id, statuses, not_found_ok=False):
start = int(time.time())
if not_found_ok:
expected_exceptions = (lib_exc.NotFound)
else:
expected_exceptions = ()
while True:
try:
fw = self.firewalls_client.show_firewall(firewall_id)
except expected_exceptions:
break
status = fw['firewall']['status']
if status not in statuses:
break
if int(time.time()) - start >= self.firewalls_client.build_timeout:
msg = ("Firewall %(firewall)s failed to reach "
"non PENDING status (current %(status)s)") % {
"firewall": firewall_id,
"status": status,
}
raise lib_exc.TimeoutException(msg)
time.sleep(1)

View File

@ -17,7 +17,6 @@ from tempest import config
from tempest.lib.common import ssh
from tempest.lib import exceptions as lib_exc
from neutron_fwaas.tests.tempest_plugin.tests import fwaas_client
from neutron_fwaas.tests.tempest_plugin.tests import fwaas_v2_client
from neutron_fwaas.tests.tempest_plugin.tests.scenario import manager
@ -64,12 +63,6 @@ class FWaaSScenarioTestBase(object):
raise
class FWaaSScenarioTest(fwaas_client.FWaaSClientMixin,
FWaaSScenarioTestBase,
manager.NetworkScenarioTest):
pass
class FWaaSScenarioTest_V2(fwaas_v2_client.FWaaSClientMixin,
FWaaSScenarioTestBase,
manager.NetworkScenarioTest):

View File

@ -1,379 +0,0 @@
# Copyright (c) 2015 Midokura SARL
# 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.
import testscenarios
from tempest.common import utils
from tempest import config
from tempest.lib import decorators
from neutron_fwaas.tests.tempest_plugin.tests.scenario import base
CONF = config.CONF
load_tests = testscenarios.load_tests_apply_scenarios
class TestFWaaS(base.FWaaSScenarioTest):
scenarios = [
('without router insersion', {
'router_insertion': False,
}),
('with router insersion', {
'router_insertion': True,
}),
]
def setUp(self):
super(TestFWaaS, self).setUp()
required_exts = ['fwaas', 'security-group', 'router']
if self.router_insertion:
required_exts.append('fwaasrouterinsertion')
for ext in required_exts:
if not utils.is_extension_enabled(ext, 'network'):
msg = "%s Extension not enabled." % ext
raise self.skipException(msg)
self._router_ids = None
def _create_server(self, network, security_group=None):
keys = self.create_keypair()
kwargs = {}
if security_group is not None:
kwargs['security_groups'] = [{'name': security_group['name']}]
server = self.create_server(
key_name=keys['name'],
networks=[{'uuid': network['id']}],
wait_until='ACTIVE',
**kwargs)
return server, keys
def _create_firewall(self, **kwargs):
if self._router_ids is not None:
kwargs['router_ids'] = self._router_ids
return self.create_firewall(**kwargs)
def _empty_policy(self, **kwargs):
# NOTE(yamamoto): an empty policy would deny all
fw_policy = self.create_firewall_policy(firewall_rules=[])
fw = self._create_firewall(firewall_policy_id=fw_policy['id'])
self._wait_firewall_ready(fw['id'])
return {
'fw': fw,
'fw_policy': fw_policy,
}
def _all_disabled_rules(self, **kwargs):
# NOTE(yamamoto): a policy whose rules are all disabled would deny all
fw_rule = self.create_firewall_rule(action="allow", enabled=False)
fw_policy = self.create_firewall_policy(firewall_rules=[fw_rule['id']])
fw = self._create_firewall(firewall_policy_id=fw_policy['id'])
self._wait_firewall_ready(fw['id'])
return {
'fw': fw,
'fw_policy': fw_policy,
'fw_rule': fw_rule,
}
def _block_ip(self, server1_fixed_ip, server2_fixed_ip, **kwargs):
rules = [
# NOTE(yamamoto): The filtering is taken place after
# destination ip is rewritten to fixed-ip.
self.create_firewall_rule(destination_ip_address=server1_fixed_ip,
action="deny"),
self.create_firewall_rule(destination_ip_address=server2_fixed_ip,
action="deny"),
self.create_firewall_rule(action="allow"),
]
rule_ids = [r['id'] for r in rules]
fw_policy = self.create_firewall_policy(firewall_rules=rule_ids)
fw = self._create_firewall(firewall_policy_id=fw_policy['id'])
self._wait_firewall_ready(fw['id'])
return {
'fw': fw,
'fw_policy': fw_policy,
'server1_fixed_ip': server1_fixed_ip,
'server2_fixed_ip': server2_fixed_ip,
}
def _block_icmp(self, **kwargs):
fw_rule = self.create_firewall_rule(
protocol="icmp",
action="deny")
fw_rule_allow = self.create_firewall_rule(
action="allow")
fw_policy = self.create_firewall_policy(
firewall_rules=[fw_rule['id'], fw_rule_allow['id']])
fw = self._create_firewall(firewall_policy_id=fw_policy['id'])
self._wait_firewall_ready(fw['id'])
return {
'fw': fw,
'fw_policy': fw_policy,
'fw_rule': fw_rule,
}
def _block_all_with_default_allow(self, **kwargs):
fw_rule = self.create_firewall_rule(
action="deny")
fw_rule_allow = self.create_firewall_rule(
action="allow")
fw_policy = self.create_firewall_policy(
firewall_rules=[fw_rule['id'], fw_rule_allow['id']])
fw = self._create_firewall(firewall_policy_id=fw_policy['id'])
self._wait_firewall_ready(fw['id'])
return {
'fw': fw,
'fw_policy': fw_policy,
'fw_rule': fw_rule,
}
def _admin_disable(self, **kwargs):
# NOTE(yamamoto): A firewall with admin_state_up=False would block all
fw_rule = self.create_firewall_rule(action="allow")
fw_policy = self.create_firewall_policy(firewall_rules=[fw_rule['id']])
fw = self._create_firewall(firewall_policy_id=fw_policy['id'],
admin_state_up=False)
self._wait_firewall_ready(fw['id'])
return {
'fw': fw,
'fw_policy': fw_policy,
'fw_rule': fw_rule,
}
def _allow_ssh_and_icmp(self, ctx):
fw_ssh_rule = self.create_firewall_rule(
protocol="tcp",
destination_port=22,
action="allow")
fw_icmp_rule = self.create_firewall_rule(
protocol="icmp",
action="allow")
for rule in [fw_ssh_rule, fw_icmp_rule]:
self.firewall_policies_client.insert_firewall_rule_in_policy(
firewall_policy_id=ctx['fw_policy']['id'],
firewall_rule_id=rule['id'],
insert_before=ctx['fw_rule']['id'])
self.addCleanup(
self._remove_rule_and_wait,
firewall_id=ctx['fw']['id'],
firewall_policy_id=ctx['fw_policy']['id'],
firewall_rule_id=rule['id'])
self._wait_firewall_ready(ctx['fw']['id'])
def _remove_rule_and_wait(self, firewall_id, firewall_policy_id,
firewall_rule_id):
self.firewall_policies_client.remove_firewall_rule_from_policy(
firewall_policy_id=firewall_policy_id,
firewall_rule_id=firewall_rule_id)
self._wait_firewall_ready(firewall_id)
def _delete_fw(self, ctx):
self.delete_firewall_and_wait(ctx['fw']['id'])
def _set_admin_up(self, firewall_id, up):
self.firewalls_client.update_firewall(firewall_id=firewall_id,
admin_state_up=up)
self._wait_firewall_ready(firewall_id=firewall_id)
def _admin_enable(self, ctx):
self._set_admin_up(ctx['fw']['id'], up=True)
def _remove_rule(self, ctx):
self._remove_rule_and_wait(
firewall_id=ctx['fw']['id'],
firewall_policy_id=ctx['fw_policy']['id'],
firewall_rule_id=ctx['fw_rule']['id'])
def _disable_rule(self, ctx):
self.firewall_rules_client.update_firewall_rule(
firewall_rule_id=ctx['fw_rule']['id'],
enabled=False)
self._wait_firewall_ready(ctx['fw']['id'])
def _allow_ip(self, ctx):
self._delete_fw(ctx)
server1_fixed_ip = ctx['server1_fixed_ip']
server2_fixed_ip = ctx['server2_fixed_ip']
rules = [
# NOTE(yamamoto): The filtering is taken place after
# destination ip is rewritten to fixed-ip.
# The return traffic should be allowed regardless
# of firewall rules.
self.create_firewall_rule(
destination_ip_address=server1_fixed_ip,
action="allow"),
self.create_firewall_rule(
destination_ip_address=server2_fixed_ip,
action="allow"),
]
rule_ids = [r['id'] for r in rules]
fw_policy = self.create_firewall_policy(firewall_rules=rule_ids)
fw = self._create_firewall(firewall_policy_id=fw_policy['id'])
self._wait_firewall_ready(fw['id'])
def _confirm_allowed(self, **kwargs):
self.check_connectivity(check_reverse_icmp_ip=self._public_gateway_ip,
**kwargs)
def _confirm_allowed_oneway(self, **kwargs):
# Can ping and ssh, but can't ping back to the public gateway.
# Same as _confirm_allowed if _public_gateway_ip is None.
self.check_connectivity(check_reverse_icmp_ip=self._public_gateway_ip,
should_reverse_connect=False, **kwargs)
def _confirm_blocked(self, **kwargs):
self.check_connectivity(should_connect=False, **kwargs)
def _confirm_icmp_blocked_but_tcp(self, **kwargs):
self.check_connectivity(should_connect=False, check_ssh=False,
**kwargs)
self.check_connectivity(check_icmp=False, **kwargs)
def _create_topology(self):
"""Create a topology for testing
+--------+ +-----------+
|"server"| | "subnet" |
| VM +-------------+ "network" |
+--------+ +----+------+
|
| router interface port
+----+-----+
| "router" |
+----+-----+
| router gateway port
|
|
+----+------------------+
| existing network |
| ("public_network_id") |
+-----------------------+
"""
public_network_id = CONF.network.public_network_id
network, subnet, router = self.create_networks()
security_group = self._create_security_group()
server, keys = self._create_server(network,
security_group=security_group)
private_key = keys['private_key']
server_floating_ip = self.create_floating_ip(server, public_network_id)
fixed_ip = list(server['addresses'].values())[0][0]['addr']
floating_ip = server_floating_ip['floating_ip_address']
return fixed_ip, floating_ip, private_key, router
def _get_public_gateway_ip(self):
self._public_gateway_ip = None
router = self._get_router()
ext_gw_info = router['external_gateway_info']
ext_fixed_ips = ext_gw_info['external_fixed_ips']
for ip in ext_fixed_ips:
subnet_id = ip['subnet_id']
res = self.os_admin.subnets_client.show_subnet(subnet_id)
subnet = res['subnet']
# REVISIT(yamamoto): IPv4 assumption
if subnet['ip_version'] == 4:
self._public_gateway_ip = subnet['gateway_ip']
return
def _test_firewall_basic(self, block, allow=None,
confirm_allowed=None, confirm_blocked=None):
if allow is None:
allow = self._delete_fw
if confirm_allowed is None:
confirm_allowed = self._confirm_allowed
if confirm_blocked is None:
confirm_blocked = self._confirm_blocked
ssh_login = CONF.validation.image_ssh_user
if self.router_insertion and CONF.network.public_router_id:
# NOTE(yamamoto): If public_router_id is configured
# router1 and router2 will be the same router.
msg = "This test assumes no public_router_id configured"
raise self.skipException(msg)
server1_fixed_ip, server1_floating_ip, private_key1, router1 = \
self._create_topology()
server2_fixed_ip, server2_floating_ip, private_key2, router2 = \
self._create_topology()
self._get_public_gateway_ip()
if self.router_insertion:
# Specify the router when creating a firewall and ensures that
# the other router (router2) is not affected by the firewall
self._router_ids = [router1['id']]
confirm_allowed2 = self.check_connectivity
confirm_blocked2 = self.check_connectivity
else:
# Without router insertion, all routers should be affected
# equally
confirm_allowed2 = confirm_allowed
confirm_blocked2 = confirm_blocked
self.check_connectivity(ip_address=server1_floating_ip,
username=ssh_login,
private_key=private_key1)
self.check_connectivity(ip_address=server2_floating_ip,
username=ssh_login,
private_key=private_key2)
ctx = block(server1_fixed_ip=server1_fixed_ip,
server1_floating_ip=server1_floating_ip,
server2_fixed_ip=server2_fixed_ip,
server2_floating_ip=server2_floating_ip)
confirm_blocked(ip_address=server1_floating_ip, username=ssh_login,
private_key=private_key1)
confirm_blocked2(ip_address=server2_floating_ip, username=ssh_login,
private_key=private_key2)
allow(ctx)
confirm_allowed(ip_address=server1_floating_ip, username=ssh_login,
private_key=private_key1)
confirm_allowed2(ip_address=server2_floating_ip, username=ssh_login,
private_key=private_key2)
@decorators.idempotent_id('f970f6b3-6541-47ac-a9ea-f769be1e21a8')
def test_firewall_block_ip(self):
self._test_firewall_basic(block=self._block_ip, allow=self._allow_ip,
confirm_allowed=self._confirm_allowed_oneway)
@decorators.idempotent_id('b985d010-994a-4055-bd5c-9e961464ccde')
def test_firewall_block_icmp(self):
self._test_firewall_basic(
block=self._block_icmp,
confirm_blocked=self._confirm_icmp_blocked_but_tcp)
@decorators.idempotent_id('ca473af0-26f9-4fad-9550-1c34371c900e')
def test_firewall_insert_rule(self):
self._test_firewall_basic(
block=self._block_icmp,
allow=self._allow_ssh_and_icmp,
confirm_blocked=self._confirm_icmp_blocked_but_tcp)
@decorators.idempotent_id('54a937a6-cecf-444c-b3f9-b67a1c1b7411')
def test_firewall_remove_rule(self):
self._test_firewall_basic(block=self._block_all_with_default_allow,
allow=self._remove_rule)
@decorators.idempotent_id('12a18776-9b60-4479-9988-f45971c96a92')
def test_firewall_disable_rule(self):
self._test_firewall_basic(block=self._block_all_with_default_allow,
allow=self._disable_rule)
@decorators.idempotent_id('a2a58c1f-49ad-4b5f-9463-e746b9efe08a')
def test_firewall_empty_policy(self):
self._test_firewall_basic(block=self._empty_policy)
@decorators.idempotent_id('477a47e0-5156-4784-9417-f77970d85c36')
def test_firewall_all_disabled_rules(self):
self._test_firewall_basic(block=self._all_disabled_rules)
@decorators.idempotent_id('a83f51c5-1a18-4d2a-a778-c368e4d95c29')
def test_firewall_admin_disable(self):
self._test_firewall_basic(block=self._admin_disable,
allow=self._admin_enable)

File diff suppressed because it is too large Load Diff

View File

@ -1,412 +0,0 @@
# 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.
import copy
import mock
from neutron.tests import base
from neutron.tests.unit.api.v2 import test_base as test_api_v2
import neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.\
iptables_fwaas as fwaas
_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'
FW_LEGACY = 'legacy'
class IptablesFwaasTestCase(base.BaseTestCase):
def setUp(self):
super(IptablesFwaasTestCase, self).setUp()
self.conntrack_driver = mock.Mock()
self.conntrack_driver.initialize = mock.Mock()
self.conntrack_driver.delete_entries = mock.Mock()
self.conntrack_driver.flush_entries = mock.Mock()
self.iptables_cls_p = mock.patch(
'neutron.agent.linux.iptables_manager.IptablesManager')
self.iptables_cls_p.start()
self.firewall = fwaas.IptablesFwaasDriver()
self.firewall.conntrack = self.conntrack_driver
def _fake_rules_v4(self, fwid, apply_list):
rule_list = []
rule1 = {'enabled': True,
'action': 'allow',
'ip_version': 4,
'protocol': 'tcp',
'destination_port': '80',
'source_ip_address': '10.24.4.2',
'id': 'fake-fw-rule1'}
rule2 = {'enabled': True,
'action': 'deny',
'ip_version': 4,
'protocol': 'tcp',
'destination_port': '22',
'id': 'fake-fw-rule2'}
rule3 = {'enabled': True,
'action': 'reject',
'ip_version': 4,
'protocol': 'tcp',
'destination_port': '23',
'id': 'fake-fw-rule3'}
ingress_chain = ('iv4%s' % fwid)[:11]
egress_chain = ('ov4%s' % fwid)[:11]
for router_info_inst in apply_list:
v4filter_inst = router_info_inst.iptables_manager.ipv4['filter']
v4filter_inst.chains.append(ingress_chain)
v4filter_inst.chains.append(egress_chain)
rule_list.append(rule1)
rule_list.append(rule2)
rule_list.append(rule3)
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):
_rule_list = copy.deepcopy(rule_list)
for rule in _rule_list:
rule['position'] = str(_rule_list.index(rule))
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, router_count=1, distributed=False,
distributed_mode=None):
apply_list = []
while router_count > 0:
iptables_inst = mock.Mock()
if distributed is not None:
router_inst = {'distributed': distributed}
else:
router_inst = {}
v4filter_inst = mock.Mock()
v6filter_inst = mock.Mock()
v4filter_inst.chains = []
v6filter_inst.chains = []
iptables_inst.ipv4 = {'filter': v4filter_inst}
iptables_inst.ipv6 = {'filter': v6filter_inst}
router_info_inst = mock.Mock()
router_info_inst.iptables_manager = iptables_inst
router_info_inst.snat_iptables_manager = iptables_inst
if distributed_mode == 'dvr':
router_info_inst.rtr_fip_connect = True
router_info_inst.router = router_inst
apply_list.append(router_info_inst)
router_count -= 1
return apply_list
def _setup_firewall_with_rules(self, func, router_count=1,
distributed=False, distributed_mode=None):
apply_list = self._fake_apply_list(router_count=router_count,
distributed=distributed, distributed_mode=distributed_mode)
rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list)
firewall = self._fake_firewall(rule_list)
if distributed:
if distributed_mode == 'dvr_snat':
if_prefix = 'sg-+'
if distributed_mode == 'dvr':
if_prefix = 'rfp-+'
else:
if_prefix = 'qr-+'
distributed_mode = 'legacy'
func(distributed_mode, apply_list, firewall)
invalid_rule = '-m state --state INVALID -j DROP'
est_rule = '-m state --state RELATED,ESTABLISHED -j ACCEPT'
rule1 = '-p tcp -s 10.24.4.2/32 -m tcp --dport 80 -j ACCEPT'
rule2 = '-p tcp -m tcp --dport 22 -j DROP'
rule3 = '-p tcp -m tcp --dport 23 -j REJECT'
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])
for router_info_inst in apply_list:
v4filter_inst = router_info_inst.iptables_manager.ipv4['filter']
calls = [mock.call.remove_chain('iv4fake-fw-uuid'),
mock.call.remove_chain('ov4fake-fw-uuid'),
mock.call.remove_chain('fwaas-default-policy'),
mock.call.add_chain('fwaas-default-policy'),
mock.call.add_rule('fwaas-default-policy', '-j DROP'),
mock.call.add_chain(ingress_chain),
mock.call.add_rule(ingress_chain, invalid_rule),
mock.call.add_rule(ingress_chain, est_rule),
mock.call.add_chain(egress_chain),
mock.call.add_rule(egress_chain, invalid_rule),
mock.call.add_rule(egress_chain, est_rule),
mock.call.add_rule(ingress_chain, rule1),
mock.call.add_rule(egress_chain, rule1),
mock.call.add_rule(ingress_chain, rule2),
mock.call.add_rule(egress_chain, rule2),
mock.call.add_rule(ingress_chain, rule3),
mock.call.add_rule(egress_chain, rule3),
mock.call.add_rule('FORWARD',
'-o %s -j %s' % (if_prefix,
ipt_mgr_ichain)),
mock.call.add_rule('FORWARD',
'-i %s -j %s' % (if_prefix,
ipt_mgr_echain)),
mock.call.add_rule('FORWARD',
'-o %s -j %s-fwaas-defau' % (if_prefix,
bname)),
mock.call.add_rule('FORWARD',
'-i %s -j %s-fwaas-defau' % (if_prefix,
bname))]
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('legacy', apply_list, firewall)
invalid_rule = '-m state --state INVALID -j DROP'
est_rule = '-m state --state RELATED,ESTABLISHED -j ACCEPT'
bname = fwaas.iptables_manager.binary_name
for ip_version in (4, 6):
ingress_chain = ('iv%s%s' % (ip_version, firewall['id']))
egress_chain = ('ov%s%s' % (ip_version, firewall['id']))
calls = [mock.call.remove_chain(
'iv%sfake-fw-uuid' % ip_version),
mock.call.remove_chain(
'ov%sfake-fw-uuid' % ip_version),
mock.call.remove_chain('fwaas-default-policy'),
mock.call.add_chain('fwaas-default-policy'),
mock.call.add_rule('fwaas-default-policy', '-j DROP'),
mock.call.add_chain(ingress_chain),
mock.call.add_rule(ingress_chain, invalid_rule),
mock.call.add_rule(ingress_chain, est_rule),
mock.call.add_chain(egress_chain),
mock.call.add_rule(egress_chain, invalid_rule),
mock.call.add_rule(egress_chain, est_rule),
mock.call.add_rule('FORWARD',
'-o qr-+ -j %s-fwaas-defau' % bname),
mock.call.add_rule('FORWARD',
'-i qr-+ -j %s-fwaas-defau' % bname)]
if ip_version == 4:
v4filter_inst = apply_list[0].iptables_manager.ipv4['filter']
v4filter_inst.assert_has_calls(calls)
else:
v6filter_inst = apply_list[0].iptables_manager.ipv6['filter']
v6filter_inst.assert_has_calls(calls)
def test_create_firewall_with_rules(self):
self._setup_firewall_with_rules(self.firewall.create_firewall)
def test_create_firewall_with_rules_without_distributed_attr(self):
self._setup_firewall_with_rules(self.firewall.create_firewall,
distributed=None)
def test_create_firewall_with_rules_two_routers(self):
self._setup_firewall_with_rules(self.firewall.create_firewall,
router_count=2)
def test_update_firewall_with_rules(self):
self._setup_firewall_with_rules(self.firewall.update_firewall)
def test_update_firewall_with_rules_without_distributed_attr(self):
self._setup_firewall_with_rules(self.firewall.update_firewall,
distributed=None)
def _test_delete_firewall(self, distributed=False):
apply_list = self._fake_apply_list(distributed=distributed)
firewall = self._fake_firewall_no_rule()
self.firewall.delete_firewall('legacy', apply_list, firewall)
ingress_chain = 'iv4%s' % firewall['id']
egress_chain = 'ov4%s' % firewall['id']
calls = [mock.call.remove_chain(ingress_chain),
mock.call.remove_chain(egress_chain),
mock.call.remove_chain('fwaas-default-policy')]
apply_list[0].iptables_manager.ipv4['filter'].assert_has_calls(calls)
def test_delete_firewall(self):
self._test_delete_firewall()
def test_delete_firewall_without_distributed_attr(self):
self._test_delete_firewall(distributed=None)
def test_create_firewall_with_admin_down(self):
apply_list = self._fake_apply_list()
rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list)
firewall = self._fake_firewall_with_admin_down(rule_list)
self.firewall.create_firewall('legacy', apply_list, firewall)
calls = [mock.call.remove_chain('iv4fake-fw-uuid'),
mock.call.remove_chain('ov4fake-fw-uuid'),
mock.call.remove_chain('fwaas-default-policy'),
mock.call.add_chain('fwaas-default-policy'),
mock.call.add_rule('fwaas-default-policy', '-j DROP')]
apply_list[0].iptables_manager.ipv4['filter'].assert_has_calls(calls)
def test_create_firewall_with_rules_dvr_snat(self):
self._setup_firewall_with_rules(self.firewall.create_firewall,
distributed=True, distributed_mode='dvr_snat')
def test_update_firewall_with_rules_dvr_snat(self):
self._setup_firewall_with_rules(self.firewall.update_firewall,
distributed=True, distributed_mode='dvr_snat')
def test_create_firewall_with_rules_dvr(self):
self._setup_firewall_with_rules(self.firewall.create_firewall,
distributed=True, distributed_mode='dvr')
def test_update_firewall_with_rules_dvr(self):
self._setup_firewall_with_rules(self.firewall.update_firewall,
distributed=True, distributed_mode='dvr')
def test_remove_conntrack_new_firewall(self):
apply_list = self._fake_apply_list()
firewall = self._fake_firewall_no_rule()
self.firewall.create_firewall(FW_LEGACY, apply_list, firewall)
for router_info_inst in apply_list:
namespace = router_info_inst.iptables_manager.namespace
calls = [mock.call(namespace)]
self.conntrack_driver.flush_entries.assert_has_calls(calls)
def test_remove_conntrack_inserted_rule(self):
apply_list = self._fake_apply_list()
rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list)
firewall = self._fake_firewall(rule_list)
self.firewall.create_firewall(FW_LEGACY, apply_list, firewall)
self.firewall.pre_firewall = dict(firewall)
insert_rule = {'enabled': True,
'action': 'deny',
'ip_version': 4,
'protocol': 'icmp',
'id': 'fake-fw-rule'}
rule_list.insert(2, insert_rule)
firewall = self._fake_firewall(rule_list)
self.firewall.update_firewall(FW_LEGACY, apply_list, firewall)
rules_changed = [
{'destination_port': '23',
'position': '2',
'protocol': 'tcp',
'ip_version': 4,
'enabled': True,
'action': 'reject',
'id': 'fake-fw-rule3'},
{'destination_port': '23',
'position': '3',
'protocol': 'tcp',
'ip_version': 4,
'enabled': True,
'action': 'reject',
'id': 'fake-fw-rule3'}
]
rules_inserted = [
{'id': 'fake-fw-rule',
'protocol': 'icmp',
'ip_version': 4,
'enabled': True,
'action': 'deny',
'position': '2'}
]
for router_info_inst in apply_list:
namespace = router_info_inst.iptables_manager.namespace
self.conntrack_driver.delete_entries.assert_called_once_with(
rules_changed + rules_inserted, namespace
)
def test_remove_conntrack_removed_rule(self):
apply_list = self._fake_apply_list()
rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list)
firewall = self._fake_firewall(rule_list)
self.firewall.create_firewall(FW_LEGACY, apply_list, firewall)
self.firewall.pre_firewall = dict(firewall)
remove_rule = rule_list[1]
rule_list.remove(remove_rule)
firewall = self._fake_firewall(rule_list)
self.firewall.update_firewall(FW_LEGACY, apply_list, firewall)
rules_changed = [
{'destination_port': '23',
'position': '2',
'protocol': 'tcp',
'ip_version': 4,
'enabled': True,
'action': 'reject',
'id': 'fake-fw-rule3'},
{'destination_port': '23',
'position': '1',
'protocol': 'tcp',
'ip_version': 4,
'enabled': True,
'action': 'reject',
'id': 'fake-fw-rule3'}
]
rules_removed = [
{'enabled': True,
'position': '1',
'protocol': 'tcp',
'id': 'fake-fw-rule2',
'ip_version': 4,
'action': 'deny',
'destination_port': '22'}
]
for router_info_inst in apply_list:
namespace = router_info_inst.iptables_manager.namespace
self.conntrack_driver.delete_entries.assert_called_once_with(
rules_changed + rules_removed, namespace
)
def test_remove_conntrack_changed_rule(self):
apply_list = self._fake_apply_list()
rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list)
firewall = self._fake_firewall(rule_list)
self.firewall.create_firewall(FW_LEGACY, apply_list, firewall)
income_rule = {'enabled': True,
'action': 'deny',
'ip_version': 4,
'protocol': 'tcp',
'id': 'fake-fw-rule3'}
rule_list[2] = income_rule
firewall = self._fake_firewall(rule_list)
self.firewall.update_firewall(FW_LEGACY, apply_list, firewall)
rules_changed = [
{'id': 'fake-fw-rule3',
'enabled': True,
'action': 'reject',
'position': '2',
'destination_port': '23',
'ip_version': 4,
'protocol': 'tcp'},
{'position': '2',
'enabled': True,
'action': 'deny',
'id': 'fake-fw-rule3',
'ip_version': 4,
'protocol': 'tcp'}
]
for router_info_inst in apply_list:
namespace = router_info_inst.iptables_manager.namespace
self.conntrack_driver.delete_entries.assert_called_once_with(
rules_changed, namespace
)

View File

@ -1,361 +0,0 @@
# Copyright (c) 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.
import mock
from neutron.agent.l3 import l3_agent_extension_api as l3_agent_api
from neutron.agent.l3 import router_info
from neutron.agent.linux import ip_lib
from neutron.conf.agent.l3 import config as l3_config
from neutron.conf import common as base_config
from neutron_lib import context
from oslo_config import cfg
from oslo_utils import uuidutils
import testtools
from neutron_fwaas.common import fwaas_constants
from neutron_fwaas.services.firewall.service_drivers.agents \
import firewall_agent_api
from neutron_fwaas.services.firewall.service_drivers.agents.l3reference \
import firewall_l3_agent
from neutron_fwaas.tests import base
from neutron_fwaas.tests.unit.services.firewall.service_drivers.agents \
import test_firewall_agent_api
class FWaasHelper(object):
def __init__(self, host):
pass
class FWaasAgent(firewall_l3_agent.FWaaSL3AgentExtension, FWaasHelper):
neutron_service_plugins = []
def _setup_test_agent_class(service_plugins):
class FWaasTestAgent(firewall_l3_agent.FWaaSL3AgentExtension,
FWaasHelper):
neutron_service_plugins = service_plugins
def __init__(self, conf):
self.event_observers = mock.Mock()
self.conf = conf
super(FWaasTestAgent, self).__init__("myhost", conf)
return FWaasTestAgent
class TestFwaasL3AgentRpcCallback(base.BaseTestCase):
def setUp(self):
super(TestFwaasL3AgentRpcCallback, self).setUp()
self.conf = cfg.ConfigOpts()
self.conf.register_opts(base_config.core_opts)
self.conf.register_opts(l3_config.OPTS)
self.conf.register_opts(firewall_agent_api.FWaaSOpts, 'fwaas')
self.api = FWaasAgent(host=None, conf=self.conf)
self.api.fwaas_driver = test_firewall_agent_api.NoopFwaasDriver()
self.adminContext = context.get_admin_context()
self.router_id = uuidutils.generate_uuid()
self.agent_conf = mock.Mock()
# For 'tenant_id' and 'project_id' keys
project_id = uuidutils.generate_uuid()
self.ri_kwargs = {'router': {'id': self.router_id,
'tenant_id': project_id,
'project_id': project_id},
'agent_conf': self.agent_conf,
'interface_driver': mock.ANY,
'use_ipv6': mock.ANY,
}
def test_fw_config_match(self):
test_agent_class = _setup_test_agent_class([fwaas_constants.FIREWALL])
cfg.CONF.set_override('enabled', True, 'fwaas')
with mock.patch('oslo_utils.importutils.import_object'):
test_agent_class(cfg.CONF)
@testtools.skip('needs to be refactored for fwaas v2')
def test_fw_config_mismatch_plugin_enabled_agent_disabled(self):
test_agent_class = _setup_test_agent_class([fwaas_constants.FIREWALL])
cfg.CONF.set_override('enabled', False, 'fwaas')
self.assertRaises(SystemExit, test_agent_class, cfg.CONF)
def test_fw_plugin_list_unavailable(self):
test_agent_class = _setup_test_agent_class(None)
cfg.CONF.set_override('enabled', False, 'fwaas')
with mock.patch('oslo_utils.importutils.import_object'):
test_agent_class(cfg.CONF)
def test_create_firewall(self):
fake_firewall = {'id': 0, 'tenant_id': 1,
'admin_state_up': True,
'add-router-ids': [1, 2]}
self.api.plugin_rpc = mock.Mock()
with mock.patch.object(self.api, '_get_router_info_list_for_tenant'
) as mock_get_router_info_list_for_tenant, \
mock.patch.object(self.api.fwaas_driver, 'create_firewall'
) as mock_driver_create_firewall, \
mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status'
) as mock_set_firewall_status:
mock_driver_create_firewall.return_value = True
self.api.create_firewall(
context=mock.sentinel.context,
firewall=fake_firewall, host='host')
mock_get_router_info_list_for_tenant.assert_called_once_with(
fake_firewall['add-router-ids'], fake_firewall['tenant_id'])
mock_set_firewall_status.assert_called_once_with(
mock.sentinel.context,
fake_firewall['id'],
'ACTIVE')
def test_update_firewall_with_routers_added_and_deleted(self):
fake_firewall = {'id': 0, 'tenant_id': 1,
'admin_state_up': True,
'add-router-ids': [1, 2],
'del-router-ids': [3, 4],
'router_ids': [],
'last-router': False}
self.api.plugin_rpc = mock.Mock()
with mock.patch.object(self.api, '_get_router_info_list_for_tenant'
) as mock_get_router_info_list_for_tenant, \
mock.patch.object(self.api.fwaas_driver, 'update_firewall'
) as mock_driver_delete_firewall, \
mock.patch.object(self.api.fwaas_driver, 'delete_firewall'
) as mock_driver_update_firewall, \
mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status'
) as mock_set_firewall_status:
mock_driver_delete_firewall.return_value = True
mock_driver_update_firewall.return_value = True
calls = [mock.call(fake_firewall['del-router-ids'],
fake_firewall['tenant_id']),
mock.call(fake_firewall['add-router-ids'],
fake_firewall['tenant_id'])]
self.api.update_firewall(
context=mock.sentinel.context,
firewall=fake_firewall, host='host')
self.assertEqual(
mock_get_router_info_list_for_tenant.call_args_list,
calls)
mock_set_firewall_status.assert_called_once_with(
mock.sentinel.context,
fake_firewall['id'],
'ACTIVE')
def test_update_firewall_with_routers_added_and_admin_state_down(self):
fake_firewall = {'id': 0, 'tenant_id': 1,
'admin_state_up': False,
'add-router-ids': [1, 2],
'del-router-ids': [],
'router_ids': [],
'last-router': False}
self.api.plugin_rpc = mock.Mock()
with mock.patch.object(self.api, '_get_router_info_list_for_tenant'
) as mock_get_router_info_list_for_tenant, \
mock.patch.object(self.api.fwaas_driver, 'update_firewall'
) as mock_driver_update_firewall, \
mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status'
) as mock_set_firewall_status:
mock_driver_update_firewall.return_value = True
self.api.update_firewall(
context=mock.sentinel.context,
firewall=fake_firewall, host='host')
mock_get_router_info_list_for_tenant.assert_called_once_with(
fake_firewall['add-router-ids'], fake_firewall['tenant_id'])
mock_set_firewall_status.assert_called_once_with(
mock.sentinel.context,
fake_firewall['id'],
'DOWN')
def test_update_firewall_with_all_routers_deleted(self):
fake_firewall = {'id': 0, 'tenant_id': 1,
'admin_state_up': True,
'add-router-ids': [],
'del-router-ids': [3, 4],
'last-router': True}
self.api.plugin_rpc = mock.Mock()
with mock.patch.object(self.api, '_get_router_info_list_for_tenant'
) as mock_get_router_info_list_for_tenant, \
mock.patch.object(self.api.fwaas_driver, 'delete_firewall'
) as mock_driver_delete_firewall, \
mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status'
) as mock_set_firewall_status:
mock_driver_delete_firewall.return_value = True
self.api.update_firewall(
context=mock.sentinel.context,
firewall=fake_firewall, host='host')
mock_get_router_info_list_for_tenant.assert_called_once_with(
fake_firewall['del-router-ids'], fake_firewall['tenant_id'])
mock_set_firewall_status.assert_called_once_with(
mock.sentinel.context,
fake_firewall['id'],
'INACTIVE')
def test_update_firewall_with_rtrs_and_no_rtrs_added_nor_deleted(self):
fake_firewall = {'id': 0, 'tenant_id': 1,
'admin_state_up': True,
'add-router-ids': [],
'del-router-ids': [],
'router_ids': [1, 2]}
self.api.plugin_rpc = mock.Mock()
with mock.patch.object(self.api.fwaas_driver, 'update_firewall'
) as mock_driver_update_firewall, \
mock.patch.object(self.api, '_get_router_info_list_for_tenant'
) as mock_get_router_info_list_for_tenant, \
mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status'
) as mock_set_firewall_status:
mock_driver_update_firewall.return_value = True
self.api.update_firewall(
context=mock.sentinel.context,
firewall=fake_firewall, host='host')
mock_get_router_info_list_for_tenant.assert_called_once_with(
fake_firewall['router_ids'], fake_firewall['tenant_id'])
mock_set_firewall_status.assert_called_once_with(
mock.sentinel.context,
fake_firewall['id'],
'ACTIVE')
def test_update_firewall_with_no_rtrs_and_no_rtrs_added_nor_deleted(self):
fake_firewall = {'id': 0, 'tenant_id': 1,
'admin_state_up': True,
'add-router-ids': [],
'del-router-ids': [],
'router_ids': []}
self.api.plugin_rpc = mock.Mock()
with mock.patch.object(self.api.fwaas_driver, 'update_firewall'
) as mock_driver_update_firewall, \
mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status'
) as mock_set_firewall_status:
mock_driver_update_firewall.return_value = True
self.api.update_firewall(
context=mock.sentinel.context,
firewall=fake_firewall, host='host')
mock_set_firewall_status.assert_called_once_with(
mock.sentinel.context,
fake_firewall['id'],
'INACTIVE')
def test_delete_firewall(self):
fake_firewall = {'id': 0, 'tenant_id': 1,
'admin_state_up': True,
'add-router-ids': [],
'del-router-ids': [3, 4],
'last-router': True}
self.api.plugin_rpc = mock.Mock()
with mock.patch.object(self.api, '_get_router_info_list_for_tenant'
) as mock_get_router_info_list_for_tenant, \
mock.patch.object(self.api.fwaas_driver, 'delete_firewall'
) as mock_driver_delete_firewall, \
mock.patch.object(self.api.fwplugin_rpc, 'firewall_deleted'
) as mock_firewall_deleted:
mock_driver_delete_firewall.return_value = True
self.api.delete_firewall(
context=mock.sentinel.context,
firewall=fake_firewall, host='host')
mock_get_router_info_list_for_tenant.assert_called_once_with(
fake_firewall['del-router-ids'], fake_firewall['tenant_id'])
mock_firewall_deleted.assert_called_once_with(
mock.sentinel.context,
fake_firewall['id'])
def _prepare_router_data(self):
return router_info.RouterInfo(self.api,
self.router_id,
**self.ri_kwargs)
def test_get_router_info_list_for_tenant(self):
ri = self._prepare_router_data()
router_info = {ri.router_id: ri}
self.api.router_info = router_info
api_object = l3_agent_api.L3AgentExtensionAPI(router_info)
self.api.consume_api(api_object)
routers = [ri.router]
router_ids = [router['id'] for router in routers]
with mock.patch.object(ip_lib,
'list_network_namespaces') as mock_list_netns:
mock_list_netns.return_value = []
router_info_list = self.api._get_router_info_list_for_tenant(
router_ids,
ri.router['tenant_id'])
mock_list_netns.assert_called_once_with()
self.assertFalse(router_info_list)
def _get_router_info_list_router_without_router_info_helper(self,
rtr_with_ri):
# ri.router with associated router_info (ri)
# rtr2 has no router_info
ri = self._prepare_router_data()
rtr2 = {'id': uuidutils.generate_uuid(),
'tenant_id': ri.router['tenant_id']}
routers = [rtr2]
router_info = {}
ri_expected = []
if rtr_with_ri:
router_info[ri.router_id] = ri
routers.append(ri.router)
ri_expected.append(ri)
self.api.router_info = router_info
router_ids = [router['id'] for router in routers]
with mock.patch.object(ip_lib,
'list_network_namespaces') as mock_list_netns:
mock_list_netns.return_value = [ri.ns_name]
api_object = l3_agent_api.L3AgentExtensionAPI(router_info)
self.api.consume_api(api_object)
router_info_list = self.api._get_router_info_list_for_tenant(
router_ids,
ri.router['tenant_id'])
self.assertEqual(ri_expected, router_info_list)
def test_get_router_info_list_router_without_router_info(self):
self._get_router_info_list_router_without_router_info_helper(
rtr_with_ri=False)
def test_get_router_info_list_two_routers_one_without_router_info(self):
self._get_router_info_list_router_without_router_info_helper(
rtr_with_ri=True)

View File

@ -1,786 +0,0 @@
# Copyright 2013 Big Switch Networks, 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.
import mock
from neutron.api import extensions as api_ext
from neutron.common import config
from neutron.tests.common import helpers
from neutron.tests.unit.extensions import test_agent
from neutron.tests.unit.extensions import test_l3 as test_l3_plugin
from neutron_lib.api import attributes as attr
from neutron_lib.api.definitions import firewall as fwaas_def
from neutron_lib.api.definitions import firewallrouterinsertion
from neutron_lib import constants as nl_constants
from neutron_lib import context
from neutron_lib.exceptions import firewall_v1 as f_exc
from neutron_lib.plugins import constants as plugin_constants
from neutron_lib.plugins import directory
from neutron_lib.tests.unit import fake_notifier
from oslo_config import cfg
from oslo_utils import uuidutils
import six
from webob import exc
from neutron_fwaas.db.firewall import firewall_db as fdb
import neutron_fwaas.extensions
from neutron_fwaas.extensions import firewall
from neutron_fwaas.services.firewall import fwaas_plugin
from neutron_fwaas.tests import base
from neutron_fwaas.tests.unit.db.firewall import (
test_firewall_db as test_db_firewall)
extensions_path = neutron_fwaas.extensions.__path__[0]
FW_PLUGIN_KLASS = (
"neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin"
)
class FirewallTestExtensionManager(test_l3_plugin.L3TestExtensionManager):
def get_resources(self):
res = super(FirewallTestExtensionManager, self).get_resources()
fwaas_def.RESOURCE_ATTRIBUTE_MAP['firewalls'].update(
firewallrouterinsertion.RESOURCE_ATTRIBUTE_MAP['firewalls'])
return res + firewall.Firewall.get_resources()
def get_actions(self):
return []
def get_request_extensions(self):
return []
class TestFirewallRouterInsertionBase(
test_db_firewall.FirewallPluginDbTestCase):
def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None):
self.agentapi_del_fw_p = mock.patch(test_db_firewall.DELETEFW_PATH,
create=True, new=test_db_firewall.FakeAgentApi().delete_firewall)
self.agentapi_del_fw_p.start()
# the plugin without L3 support
plugin = 'neutron.tests.unit.extensions.test_l3.TestNoL3NatPlugin'
# the L3 service plugin
l3_plugin = ('neutron.tests.unit.extensions.test_l3.'
'TestL3NatAgentSchedulingServicePlugin')
cfg.CONF.set_override('api_extensions_path', extensions_path)
self.saved_attr_map = {}
for resource, attrs in six.iteritems(attr.RESOURCES):
self.saved_attr_map[resource] = attrs.copy()
if not fw_plugin:
fw_plugin = FW_PLUGIN_KLASS
service_plugins = {'l3_plugin_name': l3_plugin,
'fw_plugin_name': fw_plugin}
if not ext_mgr:
ext_mgr = FirewallTestExtensionManager()
super(test_db_firewall.FirewallPluginDbTestCase, self).setUp(
plugin=plugin, service_plugins=service_plugins, ext_mgr=ext_mgr)
self.addCleanup(self.restore_attribute_map)
self.setup_notification_driver()
self.l3_plugin = directory.get_plugin(plugin_constants.L3)
self.plugin = directory.get_plugin('FIREWALL')
self.callbacks = fwaas_plugin.FirewallCallbacks(self.plugin)
def restore_attribute_map(self):
# Remove the fwaasrouterinsertion extension
fwaas_def.RESOURCE_ATTRIBUTE_MAP['firewalls'].pop('router_ids')
# Restore the original RESOURCE_ATTRIBUTE_MAP
attr.RESOURCES = self.saved_attr_map
def _create_firewall(self, fmt, name, description, firewall_policy_id=None,
admin_state_up=True, expected_res_status=None,
**kwargs):
tenant_id = kwargs.get('tenant_id', self._tenant_id)
router_ids = kwargs.get('router_ids')
if firewall_policy_id is None:
res = self._create_firewall_policy(fmt, 'fwp',
description="firewall_policy",
shared=True,
firewall_rules=[],
audited=True)
firewall_policy = self.deserialize(fmt or self.fmt, res)
firewall_policy_id = firewall_policy["firewall_policy"]["id"]
data = {'firewall': {'name': name,
'description': description,
'firewall_policy_id': firewall_policy_id,
'admin_state_up': admin_state_up,
'tenant_id': tenant_id}}
if router_ids is not None:
data['firewall']['router_ids'] = router_ids
firewall_req = self.new_create_request('firewalls', data, fmt)
firewall_res = firewall_req.get_response(self.ext_api)
if expected_res_status:
self.assertEqual(expected_res_status, firewall_res.status_int)
return firewall_res
class TestFirewallCallbacks(TestFirewallRouterInsertionBase):
def test_set_firewall_status(self):
ctx = context.get_admin_context()
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP
) as fw:
fw_id = fw['firewall']['id']
res = self.callbacks.set_firewall_status(ctx, fw_id,
nl_constants.ACTIVE)
fw_db = self.plugin.get_firewall(ctx, fw_id)
self.assertEqual(nl_constants.ACTIVE, fw_db['status'])
self.assertTrue(res)
res = self.callbacks.set_firewall_status(ctx, fw_id,
nl_constants.ERROR)
fw_db = self.plugin.get_firewall(ctx, fw_id)
self.assertEqual(nl_constants.ERROR, fw_db['status'])
self.assertFalse(res)
def test_set_firewall_status_pending_delete(self):
ctx = context.get_admin_context()
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP
) as fw:
fw_id = fw['firewall']['id']
fw_db = self.plugin._get_firewall(ctx, fw_id)
fw_db['status'] = nl_constants.PENDING_DELETE
ctx.session.flush()
res = self.callbacks.set_firewall_status(ctx, fw_id,
nl_constants.ACTIVE)
fw_db = self.plugin.get_firewall(ctx, fw_id)
self.assertEqual(nl_constants.PENDING_DELETE, fw_db['status'])
self.assertFalse(res)
def test_firewall_deleted(self):
ctx = context.get_admin_context()
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
do_delete=False) as fw:
fw_id = fw['firewall']['id']
with ctx.session.begin(subtransactions=True):
fw_db = self.plugin._get_firewall(ctx, fw_id)
fw_db['status'] = nl_constants.PENDING_DELETE
ctx.session.flush()
res = self.callbacks.firewall_deleted(ctx, fw_id)
self.assertTrue(res)
self.assertRaises(f_exc.FirewallNotFound,
self.plugin.get_firewall,
ctx, fw_id)
def test_firewall_deleted_concurrently(self):
ctx = context.get_admin_context()
alt_ctx = context.get_admin_context()
_get_firewall = self.plugin._get_firewall
def getdelete(context, firewall_id):
fw_db = _get_firewall(context, firewall_id)
# NOTE(cby): Use a different session to simulate a concurrent del
self.plugin.delete_db_firewall_object(alt_ctx, firewall_id)
return fw_db
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
do_delete=False
) as fw:
fw_id = fw['firewall']['id']
with ctx.session.begin(subtransactions=True):
fw_db = self.plugin._get_firewall(ctx, fw_id)
fw_db['status'] = nl_constants.PENDING_DELETE
ctx.session.flush()
with mock.patch.object(
self.plugin, '_get_firewall', side_effect=getdelete
):
observed = self.callbacks.firewall_deleted(ctx, fw_id)
self.assertTrue(observed)
self.assertRaises(f_exc.FirewallNotFound,
self.plugin.get_firewall,
ctx, fw_id)
def test_firewall_deleted_not_found(self):
ctx = context.get_admin_context()
observed = self.callbacks.firewall_deleted(ctx, 'notfound')
self.assertTrue(observed)
def test_firewall_deleted_error(self):
ctx = context.get_admin_context()
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
) as fw:
fw_id = fw['firewall']['id']
res = self.callbacks.firewall_deleted(ctx, fw_id)
self.assertFalse(res)
fw_db = self.plugin._get_firewall(ctx, fw_id)
self.assertEqual(nl_constants.ERROR, fw_db['status'])
def test_get_firewall_for_tenant(self):
tenant_id = 'test-tenant'
ctx = context.Context('', tenant_id)
with self.firewall_rule(name='fwr1', tenant_id=tenant_id) as fwr1, \
self.firewall_rule(name='fwr2', tenant_id=tenant_id) as fwr2, \
self.firewall_rule(name='fwr3', tenant_id=tenant_id) as fwr3:
with self.firewall_policy(tenant_id=tenant_id) as fwp:
fwp_id = fwp['firewall_policy']['id']
fr = [fwr1, fwr2, fwr3]
fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
data = {'firewall_policy':
{'firewall_rules': fw_rule_ids}}
req = self.new_update_request('firewall_policies', data,
fwp_id)
res = req.get_response(self.ext_api)
attrs = self._get_test_firewall_attrs()
attrs['firewall_policy_id'] = fwp_id
with self.firewall(
firewall_policy_id=fwp_id,
tenant_id=tenant_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP) as fw:
fw_id = fw['firewall']['id']
res = self.callbacks.get_firewalls_for_tenant(ctx)
fw_rules = (
self.plugin._make_firewall_dict_with_rules(ctx,
fw_id)
)
fw_rules['add-router-ids'] = []
fw_rules['del-router-ids'] = []
self.assertEqual(fw_rules, res[0])
self._compare_firewall_rule_lists(
fwp_id, fr, res[0]['firewall_rule_list'])
class TestFirewallAgentApi(base.BaseTestCase):
def setUp(self):
super(TestFirewallAgentApi, self).setUp()
self.api = fwaas_plugin.FirewallAgentApi('topic', 'host')
def test_init(self):
self.assertEqual('topic', self.api.client.target.topic)
self.assertEqual('host', self.api.host)
def _call_test_helper(self, method_name, host):
with mock.patch.object(self.api.client, 'cast') as rpc_mock, \
mock.patch.object(self.api.client, 'prepare') as prepare_mock:
prepare_mock.return_value = self.api.client
getattr(self.api, method_name)(mock.sentinel.context, 'test', host)
prepare_args = {'server': host}
prepare_mock.assert_called_once_with(**prepare_args)
rpc_mock.assert_called_once_with(mock.sentinel.context, method_name,
firewall='test', host='host')
def test_create_firewall(self):
self._call_test_helper('create_firewall', 'host')
def test_update_firewall(self):
self._call_test_helper('update_firewall', 'host')
def test_delete_firewall(self):
self._call_test_helper('delete_firewall', 'host')
class TestFirewallPluginBase(TestFirewallRouterInsertionBase,
test_l3_plugin.L3NatTestCaseMixin):
def setUp(self):
super(TestFirewallPluginBase, self).setUp(fw_plugin=FW_PLUGIN_KLASS)
fake_notifier.reset()
def test_create_firewall_routers_not_specified(self):
"""neutron firewall-create test-policy """
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id):
with self.router(name='router2', admin_state_up=True,
tenant_id=self._tenant_id):
with self.firewall() as fw1:
self.assertEqual(nl_constants.PENDING_CREATE,
fw1['firewall']['status'])
def test_create_firewall_routers_specified(self):
"""neutron firewall-create test-policy --router-ids "r1 r2" """
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id) as router1:
with self.router(name='router2', admin_state_up=True,
tenant_id=self._tenant_id) as router2:
router_ids = [router1['router']['id'], router2['router']['id']]
with self.firewall(router_ids=router_ids) as fw1:
self.assertEqual(nl_constants.PENDING_CREATE,
fw1['firewall']['status'])
def test_create_firewall_routers_present_empty_list_specified(self):
"""neutron firewall-create test-policy --router-ids "" """
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id):
with self.router(name='router2', admin_state_up=True,
tenant_id=self._tenant_id):
router_ids = []
with self.firewall(router_ids=router_ids) as fw1:
self.assertEqual(nl_constants.INACTIVE,
fw1['firewall']['status'])
def test_create_firewall_no_routers_empty_list_specified(self):
"""neutron firewall-create test-policy --router-ids "" """
router_ids = []
with self.firewall(router_ids=router_ids) as fw1:
self.assertEqual(nl_constants.INACTIVE,
fw1['firewall']['status'])
def test_create_second_firewall_on_same_tenant(self):
"""fw1 created with default routers, fw2 no routers on same tenant."""
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id):
with self.router(name='router2', admin_state_up=True,
tenant_id=self._tenant_id):
router_ids = []
with self.firewall() as fw1:
with self.firewall(router_ids=router_ids) as fw2:
self.assertEqual(nl_constants.PENDING_CREATE,
fw1['firewall']['status'])
self.assertEqual(nl_constants.INACTIVE,
fw2['firewall']['status'])
def test_create_firewall_admin_not_affected_by_other_tenant(self):
# Create fw with admin after creating fw with other tenant
with self.firewall(tenant_id='other-tenant') as fw1:
with self.firewall() as fw2:
self.assertEqual('other-tenant', fw1['firewall']['tenant_id'])
self.assertEqual(self._tenant_id, fw2['firewall']['tenant_id'])
def test_update_firewall(self):
ctx = context.get_admin_context()
name = "new_firewall1"
attrs = self._get_test_firewall_attrs(name)
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id) as router1:
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
attrs['firewall_policy_id'] = fwp_id
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
router_ids=[router1['router']['id']]
) as firewall:
fw_id = firewall['firewall']['id']
res = self.callbacks.set_firewall_status(ctx, fw_id,
nl_constants.ACTIVE)
data = {'firewall': {'name': name}}
req = self.new_update_request('firewalls', data, fw_id)
res = self.deserialize(self.fmt,
req.get_response(self.ext_api))
attrs = self._replace_firewall_status(attrs,
nl_constants.
PENDING_CREATE,
nl_constants.
PENDING_UPDATE)
for k, v in six.iteritems(attrs):
self.assertEqual(v, res['firewall'][k])
def test_update_firewall_fails_when_firewall_pending(self):
name = "new_firewall1"
attrs = self._get_test_firewall_attrs(name)
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id) as router1:
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
attrs['firewall_policy_id'] = fwp_id
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
router_ids=[router1['router']['id']]
) as firewall:
fw_id = firewall['firewall']['id']
data = {'firewall': {'name': name}}
req = self.new_update_request('firewalls', data, fw_id)
res = req.get_response(self.ext_api)
self.assertEqual(exc.HTTPConflict.code, res.status_int)
def test_update_firewall_with_router_when_firewall_inactive(self):
name = "firewall1"
attrs = self._get_test_firewall_attrs(name)
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id) as router1:
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
attrs['firewall_policy_id'] = fwp_id
with self.firewall(
name=name,
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
router_ids=[]
) as firewall:
fw_id = firewall['firewall']['id']
data = {
'firewall': {'router_ids': [router1['router']['id']]}}
req = self.new_update_request('firewalls', data, fw_id)
res = self.deserialize(self.fmt,
req.get_response(self.ext_api))
attrs = self._replace_firewall_status(attrs,
nl_constants.
PENDING_CREATE,
nl_constants.
PENDING_UPDATE)
for k, v in six.iteritems(attrs):
self.assertEqual(v, res['firewall'][k])
def test_update_firewall_policy_fails_when_firewall_pending(self):
name = "new_firewall1"
attrs = self._get_test_firewall_attrs(name)
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id):
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
attrs['firewall_policy_id'] = fwp_id
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP
):
data = {'firewall_policy': {'name': name}}
req = self.new_update_request('firewall_policies',
data, fwp_id)
res = req.get_response(self.ext_api)
self.assertEqual(exc.HTTPConflict.code, res.status_int)
def test_update_firewall_rule_fails_when_firewall_pending(self):
with self.router(name='router1', admin_state_up=True,
tenant_id=self._tenant_id):
with self.firewall_rule(name='fwr1') as fr:
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
fr_id = fr['firewall_rule']['id']
fw_rule_ids = [fr_id]
data = {'firewall_policy':
{'firewall_rules': fw_rule_ids}}
req = self.new_update_request('firewall_policies', data,
fwp_id)
req.get_response(self.ext_api)
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP
):
data = {'firewall_rule': {'protocol': 'udp'}}
req = self.new_update_request('firewall_rules',
data, fr_id)
res = req.get_response(self.ext_api)
self.assertEqual(exc.HTTPConflict.code, res.status_int)
def test_delete_firewall_with_no_routers(self):
ctx = context.get_admin_context()
# stop the AgentRPC patch for this one to test pending states
self.agentapi_del_fw_p.stop()
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
do_delete=False
) as fw:
fw_id = fw['firewall']['id']
req = self.new_delete_request('firewalls', fw_id)
res = req.get_response(self.ext_api)
self.assertEqual(exc.HTTPNoContent.code, res.status_int)
self.assertRaises(f_exc.FirewallNotFound,
self.plugin.get_firewall,
ctx, fw_id)
def test_delete_firewall_after_agent_delete(self):
ctx = context.get_admin_context()
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(firewall_policy_id=fwp_id,
do_delete=False) as fw:
fw_id = fw['firewall']['id']
req = self.new_delete_request('firewalls', fw_id)
res = req.get_response(self.ext_api)
self.assertEqual(exc.HTTPNoContent.code, res.status_int)
self.assertRaises(f_exc.FirewallNotFound,
self.plugin.get_firewall,
ctx, fw_id)
def test_make_firewall_dict_with_in_place_rules(self):
ctx = context.get_admin_context()
with self.firewall_rule(name='fwr1') as fwr1, \
self.firewall_rule(name='fwr2') as fwr2, \
self.firewall_rule(name='fwr3') as fwr3:
with self.firewall_policy() as fwp:
fr = [fwr1, fwr2, fwr3]
fwp_id = fwp['firewall_policy']['id']
fw_rule_ids = [r['firewall_rule']['id'] for r in fr]
data = {'firewall_policy':
{'firewall_rules': fw_rule_ids}}
req = self.new_update_request('firewall_policies', data,
fwp_id)
req.get_response(self.ext_api)
attrs = self._get_test_firewall_attrs()
attrs['firewall_policy_id'] = fwp_id
with self.firewall(
firewall_policy_id=fwp_id,
admin_state_up=test_db_firewall.ADMIN_STATE_UP,
router_ids=[]
) as fw:
fw_id = fw['firewall']['id']
fw_rules = (
self.plugin._make_firewall_dict_with_rules(ctx,
fw_id)
)
self.assertEqual(fw_id, fw_rules['id'])
self._compare_firewall_rule_lists(
fwp_id, fr, fw_rules['firewall_rule_list'])
def test_make_firewall_dict_with_in_place_rules_no_policy(self):
ctx = context.get_admin_context()
with self.firewall() as fw:
fw_id = fw['firewall']['id']
fw_rules = self.plugin._make_firewall_dict_with_rules(ctx, fw_id)
self.assertEqual([], fw_rules['firewall_rule_list'])
def test_list_firewalls(self):
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(name='fw1', firewall_policy_id=fwp_id,
description='fw') as fwalls:
self._test_list_resources('firewall', [fwalls],
query_params='description=fw')
def test_list_firewalls_with_filtering(self):
with self.router(name='my_router', admin_state_up=True,
tenant_id=self._tenant_id) as router:
router_id = router['router']['id']
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(name='fw1', firewall_policy_id=fwp_id,
description='fw',
router_ids=[router_id]) as fwalls:
filter_pattern = None
fw = fwalls['firewall']
for filter_pattern in fw:
query_params = 'fields=%s' % filter_pattern
expect = [{filter_pattern: fw[filter_pattern]}]
self._test_list_resources('firewall', expect,
query_params=query_params)
def test_insert_rule(self):
ctx = context.get_admin_context()
with self.firewall_rule() as fwr:
fr_id = fwr['firewall_rule']['id']
rule_info = {'firewall_rule_id': fr_id}
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(firewall_policy_id=fwp_id) as fw:
fw_id = fw['firewall']['id']
self.plugin.insert_rule(ctx, fwp_id, rule_info)
fw_rules = self.plugin._make_firewall_dict_with_rules(
ctx, fw_id)
self.assertEqual(1, len(fw_rules['firewall_rule_list']))
self.assertEqual(fr_id,
fw_rules['firewall_rule_list'][0]['id'])
def test_insert_rule_notif(self):
ctx = context.get_admin_context()
with self.firewall_rule() as fwr:
fr_id = fwr['firewall_rule']['id']
rule_info = {'firewall_rule_id': fr_id}
with self.firewall_policy() as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(firewall_policy_id=fwp_id):
self.plugin.insert_rule(ctx, fwp_id, rule_info)
notifications = fake_notifier.NOTIFICATIONS
expected_event_type = 'firewall_policy.update.insert_rule'
event_types = [event['event_type'] for event in notifications]
self.assertIn(expected_event_type, event_types)
def test_remove_rule(self):
ctx = context.get_admin_context()
with self.firewall_rule() as fwr:
fr_id = fwr['firewall_rule']['id']
rule_info = {'firewall_rule_id': fr_id}
with self.firewall_policy(firewall_rules=[fr_id]) as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(firewall_policy_id=fwp_id) as fw:
fw_id = fw['firewall']['id']
self.plugin.remove_rule(ctx, fwp_id, rule_info)
fw_rules = self.plugin._make_firewall_dict_with_rules(
ctx, fw_id)
self.assertEqual([], fw_rules['firewall_rule_list'])
def test_remove_rule_notif(self):
ctx = context.get_admin_context()
with self.firewall_rule() as fwr:
fr_id = fwr['firewall_rule']['id']
rule_info = {'firewall_rule_id': fr_id}
with self.firewall_policy(firewall_rules=[fr_id]) as fwp:
fwp_id = fwp['firewall_policy']['id']
with self.firewall(firewall_policy_id=fwp_id):
self.plugin.remove_rule(ctx, fwp_id, rule_info)
notifications = fake_notifier.NOTIFICATIONS
expected_event_type = 'firewall_policy.update.remove_rule'
event_types = [event['event_type'] for event in notifications]
self.assertIn(expected_event_type, event_types)
def test_firewall_quota_lower(self):
"""Test quota using overridden value."""
cfg.CONF.set_override('quota_firewall', 3, group='QUOTAS')
with self.firewall(name='quota1'), \
self.firewall(name='quota2'), \
self.firewall(name='quota3'):
data = {'firewall': {'name': 'quota4',
'firewall_policy_id': None,
'tenant_id': self._tenant_id}}
req = self.new_create_request('firewalls', data, 'json')
res = req.get_response(self.ext_api)
self.assertIn('Quota exceeded', res.body.decode('utf-8'))
self.assertEqual(exc.HTTPConflict.code, res.status_int)
def test_firewall_quota_default(self):
"""Test quota using default value."""
with self.firewall(name='quota1'), \
self.firewall(name='quota2'), \
self.firewall(name='quota3'), \
self.firewall(name='quota4'), \
self.firewall(name='quota5'), \
self.firewall(name='quota6'), \
self.firewall(name='quota7'), \
self.firewall(name='quota8'), \
self.firewall(name='quota9'), \
self.firewall(name='quota10'):
data = {'firewall': {'name': 'quota11',
'firewall_policy_id': None,
'tenant_id': self._tenant_id}}
req = self.new_create_request('firewalls', data, 'json')
res = req.get_response(self.ext_api)
self.assertIn('Quota exceeded', res.body.decode('utf-8'))
self.assertEqual(exc.HTTPConflict.code, res.status_int)
class TestFirewallRouterPluginBase(test_db_firewall.FirewallPluginDbTestCase,
test_l3_plugin.L3NatTestCaseMixin,
test_agent.AgentDBTestMixIn):
def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None):
self.agentapi_del_fw_p = mock.patch(test_db_firewall.DELETEFW_PATH,
create=True, new=test_db_firewall.FakeAgentApi().delete_firewall)
self.agentapi_del_fw_p.start()
self.client_mock = mock.MagicMock(name="mocked client")
mock.patch('neutron.common.rpc.get_client'
).start().return_value = self.client_mock
# the L3 routing with L3 agent scheduling service plugin
l3_plugin = ('neutron.tests.unit.extensions.test_l3.'
'TestL3NatAgentSchedulingServicePlugin')
cfg.CONF.set_override('api_extensions_path', extensions_path)
if not fw_plugin:
fw_plugin = FW_PLUGIN_KLASS
service_plugins = {'l3_plugin_name': l3_plugin,
'fw_plugin_name': fw_plugin}
fdb.Firewall_db_mixin.\
supported_extension_aliases = ["fwaas",
"fwaasrouterinsertion"]
fdb.Firewall_db_mixin.path_prefix = fwaas_def.API_PREFIX
super(test_db_firewall.FirewallPluginDbTestCase, self).setUp(
ext_mgr=ext_mgr,
service_plugins=service_plugins
)
if not ext_mgr:
ext_mgr = FirewallTestExtensionManager()
app = config.load_paste_app('extensions_test_app')
self.ext_api = api_ext.ExtensionMiddleware(app, ext_mgr=ext_mgr)
self.l3_plugin = directory.get_plugin(plugin_constants.L3)
self.plugin = directory.get_plugin('FIREWALL')
def test_get_firewall_tenant_ids_on_host_with_associated_router(self):
agent = helpers.register_l3_agent("host1")
tenant_id = uuidutils.generate_uuid()
ctxt = context.get_admin_context()
with self.router(name='router1', admin_state_up=True,
tenant_id=tenant_id) as router1:
router_id = router1['router']['id']
self.l3_plugin.add_router_to_l3_agent(ctxt, agent.id,
router_id)
with self.firewall(tenant_id=tenant_id,
router_ids=[router_id]):
tenant_ids = self.plugin.get_firewall_tenant_ids_on_host(
ctxt, 'host1')
self.assertEqual([tenant_id], tenant_ids)
def test_get_firewall_tenant_ids_on_host_without_associated_router(self):
agent1 = helpers.register_l3_agent("host1")
helpers.register_l3_agent("host2")
tenant_id = uuidutils.generate_uuid()
ctxt = context.get_admin_context()
with self.router(name='router1', admin_state_up=True,
tenant_id=tenant_id) as router1:
router_id = router1['router']['id']
self.l3_plugin.add_router_to_l3_agent(ctxt, agent1.id,
router_id)
with self.firewall(tenant_id=tenant_id,
router_ids=[router_id]):
tenant_ids = self.plugin.get_firewall_tenant_ids_on_host(
ctxt, 'host_2')
self.assertEqual([], tenant_ids)
def test_get_firewall_tenant_ids_on_host_with_routers(self):
agent1 = helpers.register_l3_agent("host1")
tenant_id1 = uuidutils.generate_uuid()
tenant_id2 = uuidutils.generate_uuid()
ctxt = context.get_admin_context()
with self.router(name='router1', admin_state_up=True,
tenant_id=tenant_id1) as router1:
with self.router(name='router2', admin_state_up=True,
tenant_id=tenant_id2) as router2:
router_id1 = router1['router']['id']
router_id2 = router2['router']['id']
self.l3_plugin.add_router_to_l3_agent(ctxt, agent1.id,
router_id1)
self.l3_plugin.add_router_to_l3_agent(ctxt, agent1.id,
router_id2)
with self.firewall(tenant_id=tenant_id1,
router_ids=[router_id1]):
with self.firewall(tenant_id=tenant_id2,
router_ids=[router_id2]):
tenant_ids = (self.plugin
.get_firewall_tenant_ids_on_host(
ctxt, 'host1'))
self.assertItemsEqual([tenant_id1, tenant_id2],
tenant_ids)

View File

@ -0,0 +1,7 @@
---
prelude: >
- FWaaS V1 is being removed from the neutron-fwaas repo. Because FWaaS V2
has been available since the Newton release.
upgrade:
- The FWaaS V1 source code will not be available in neutron-fwaas repo from
Stein. FWaaS team will provide a migration script to upgrade.

View File

@ -32,15 +32,9 @@ setup-hooks =
[entry_points]
firewall_drivers =
# These are for backwards compat with Juno firewall service provider
# configuration values
neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas:IptablesFwaasDriver
iptables = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas:IptablesFwaasDriver
iptables_v2 = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas_v2:IptablesFwaasDriver
neutron.service_plugins =
firewall = neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin
firewall_v2 = neutron_fwaas.services.firewall.fwaas_plugin_v2:FirewallPluginV2
neutron.services.firewall.fwaas_plugin.FirewallPlugin = neutron_fwaas.services.firewall.fwaas_plugin:FirewallPlugin
neutron.db.alembic_migrations =
neutron-fwaas = neutron_fwaas.db.migration:alembic_migrations
@ -59,7 +53,6 @@ neutron.agent.l2.firewall_drivers =
noop = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.noop.noop_driver:NoopFirewallL2Driver
ovs = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.l2.openvswitch_firewall.firewall:OVSFirewallDriver
neutron.agent.l3.extensions =
fwaas = neutron_fwaas.services.firewall.service_drivers.agents.l3reference.firewall_l3_agent:L3WithFWaaS
fwaas_v2 = neutron_fwaas.services.firewall.service_drivers.agents.l3reference.firewall_l3_agent_v2:L3WithFWaaS
fwaas_v2_log = neutron_fwaas.services.logapi.agents.l3.fwg_log:FWaaSL3LoggingExtension
neutron.agent.l3.firewall_drivers =