Remove vendor driver: vArmour from community repo
Vendor drivers are being removed from the community repo and they can continue to be hosted in respective vendor repos. This has been discussed and communicated during the Mitaka release and time given until the Newton release. Change-Id: Id60a2cdb225a2acfa28efcf54f5bcae8cf9cf55a
This commit is contained in:
parent
fd8d6d27f0
commit
ca7c5c2b72
|
@ -1,146 +0,0 @@
|
||||||
# Copyright 2013 vArmour 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 base64
|
|
||||||
|
|
||||||
import httplib2
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_log import log as logging
|
|
||||||
from oslo_serialization import jsonutils
|
|
||||||
|
|
||||||
from neutron_fwaas._i18n import _, _LE
|
|
||||||
from neutron_fwaas.services.firewall.agents.varmour \
|
|
||||||
import varmour_utils as va_utils
|
|
||||||
|
|
||||||
OPTS = [
|
|
||||||
cfg.StrOpt('director', default='localhost',
|
|
||||||
help=_("vArmour director ip")),
|
|
||||||
cfg.StrOpt('director_port', default='443',
|
|
||||||
help=_("vArmour director port")),
|
|
||||||
cfg.StrOpt('username', default='varmour',
|
|
||||||
help=_("vArmour director username")),
|
|
||||||
cfg.StrOpt('password', default='varmour', secret=True,
|
|
||||||
help=_("vArmour director password")), ]
|
|
||||||
|
|
||||||
cfg.CONF.register_opts(OPTS, "vArmour")
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
REST_URL_PREFIX = '/api/v1.0'
|
|
||||||
|
|
||||||
|
|
||||||
class vArmourAPIException(Exception):
|
|
||||||
message = _("An unknown exception.")
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
try:
|
|
||||||
self.err = self.message % kwargs
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
self.err = self.message
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.err
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationFailure(vArmourAPIException):
|
|
||||||
message = _("Invalid login credential.")
|
|
||||||
|
|
||||||
|
|
||||||
class vArmourRestAPI(object):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
LOG.debug('vArmourRestAPI: started')
|
|
||||||
self.user = cfg.CONF.vArmour.username
|
|
||||||
self.passwd = cfg.CONF.vArmour.password
|
|
||||||
self.server = cfg.CONF.vArmour.director
|
|
||||||
self.port = cfg.CONF.vArmour.director_port
|
|
||||||
self.timeout = 3
|
|
||||||
self.key = ''
|
|
||||||
|
|
||||||
def auth(self):
|
|
||||||
headers = {}
|
|
||||||
enc = base64.b64encode(self.user + ':' + self.passwd)
|
|
||||||
headers['Authorization'] = 'Basic ' + enc
|
|
||||||
resp = self.rest_api('POST', va_utils.REST_URL_AUTH, None, headers)
|
|
||||||
if resp and resp['status'] == 200:
|
|
||||||
self.key = resp['body']['auth']
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
raise AuthenticationFailure()
|
|
||||||
|
|
||||||
def commit(self):
|
|
||||||
self.rest_api('POST', va_utils.REST_URL_COMMIT)
|
|
||||||
|
|
||||||
def rest_api(self, method, url, body=None, headers=None):
|
|
||||||
url = REST_URL_PREFIX + url
|
|
||||||
if body:
|
|
||||||
body_data = jsonutils.dumps(body)
|
|
||||||
else:
|
|
||||||
body_data = ''
|
|
||||||
if not headers:
|
|
||||||
headers = {}
|
|
||||||
enc = base64.b64encode('%s:%s' % (self.user, self.key))
|
|
||||||
headers['Authorization'] = 'Basic ' + enc
|
|
||||||
|
|
||||||
LOG.debug("vArmourRestAPI: %(server)s %(port)s",
|
|
||||||
{'server': self.server, 'port': self.port})
|
|
||||||
|
|
||||||
try:
|
|
||||||
action = "https://" + self.server + ":" + self.port + url
|
|
||||||
|
|
||||||
LOG.debug("vArmourRestAPI Sending: "
|
|
||||||
"%(method)s %(action)s %(headers)s %(body_data)s",
|
|
||||||
{'method': method, 'action': action,
|
|
||||||
'headers': headers, 'body_data': body_data})
|
|
||||||
|
|
||||||
h = httplib2.Http(timeout=3,
|
|
||||||
disable_ssl_certificate_validation=True)
|
|
||||||
resp, resp_str = h.request(action, method,
|
|
||||||
body=body_data,
|
|
||||||
headers=headers)
|
|
||||||
|
|
||||||
LOG.debug("vArmourRestAPI Response: %(status)s %(resp_str)s",
|
|
||||||
{'status': resp.status, 'resp_str': resp_str})
|
|
||||||
|
|
||||||
if resp.status == 200:
|
|
||||||
return {'status': resp.status,
|
|
||||||
'reason': resp.reason,
|
|
||||||
'body': jsonutils.loads(resp_str)}
|
|
||||||
except Exception:
|
|
||||||
LOG.error(_LE('vArmourRestAPI: Could not establish HTTP '
|
|
||||||
'connection'))
|
|
||||||
|
|
||||||
def del_cfg_objs(self, url, prefix):
|
|
||||||
resp = self.rest_api('GET', url)
|
|
||||||
if resp and resp['status'] == 200:
|
|
||||||
olist = resp['body']['response']
|
|
||||||
if not olist:
|
|
||||||
return
|
|
||||||
|
|
||||||
for o in olist:
|
|
||||||
if o.startswith(prefix):
|
|
||||||
self.rest_api('DELETE', url + '/"name:%s"' % o)
|
|
||||||
self.commit()
|
|
||||||
|
|
||||||
def count_cfg_objs(self, url, prefix):
|
|
||||||
count = 0
|
|
||||||
resp = self.rest_api('GET', url)
|
|
||||||
if resp and resp['status'] == 200:
|
|
||||||
for o in resp['body']['response']:
|
|
||||||
if o.startswith(prefix):
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
return count
|
|
|
@ -1,347 +0,0 @@
|
||||||
# Copyright 2013 vArmour 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 sys
|
|
||||||
|
|
||||||
import eventlet
|
|
||||||
eventlet.monkey_patch()
|
|
||||||
|
|
||||||
import netaddr
|
|
||||||
from neutron.agent.common import config
|
|
||||||
from neutron.agent.l3 import agent
|
|
||||||
from neutron.agent.l3 import config as l3_config
|
|
||||||
from neutron.agent.l3 import ha
|
|
||||||
from neutron.agent.l3 import router_info
|
|
||||||
from neutron.agent.linux import external_process
|
|
||||||
from neutron.agent.linux import interface
|
|
||||||
from neutron.agent.linux import ip_lib
|
|
||||||
from neutron.common import config as common_config
|
|
||||||
from neutron import service as neutron_service
|
|
||||||
from neutron_lib import constants as l3_constants
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_log import log as logging
|
|
||||||
from oslo_service import service
|
|
||||||
|
|
||||||
from neutron_fwaas._i18n import _, _LW
|
|
||||||
from neutron_fwaas.common import fwaas_constants as f_const
|
|
||||||
from neutron_fwaas.services.firewall.agents.l3reference \
|
|
||||||
import firewall_l3_agent
|
|
||||||
from neutron_fwaas.services.firewall.agents.varmour import varmour_api
|
|
||||||
from neutron_fwaas.services.firewall.agents.varmour \
|
|
||||||
import varmour_utils as va_utils
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class vArmourL3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
|
|
||||||
agent.L3NATAgent):
|
|
||||||
def __init__(self, host, conf=None):
|
|
||||||
LOG.debug('vArmourL3NATAgent: __init__')
|
|
||||||
self.rest = varmour_api.vArmourRestAPI()
|
|
||||||
super(vArmourL3NATAgent, self).__init__(host, conf)
|
|
||||||
|
|
||||||
def _destroy_router_namespace(self, namespace):
|
|
||||||
return
|
|
||||||
|
|
||||||
def _create_router_namespace(self, ri):
|
|
||||||
return
|
|
||||||
|
|
||||||
def _router_added(self, router_id, router):
|
|
||||||
LOG.debug("_router_added: %s", router_id)
|
|
||||||
ri = router_info.RouterInfo(router_id=router_id, router=router,
|
|
||||||
agent_conf=self.conf,
|
|
||||||
interface_driver=self.driver)
|
|
||||||
self.router_info[router_id] = ri
|
|
||||||
super(vArmourL3NATAgent, self).process_router_add(ri)
|
|
||||||
|
|
||||||
def _router_removed(self, router_id):
|
|
||||||
LOG.debug("_router_removed: %s", router_id)
|
|
||||||
|
|
||||||
ri = self.router_info[router_id]
|
|
||||||
if ri:
|
|
||||||
ri.router['gw_port'] = None
|
|
||||||
ri.router[l3_constants.INTERFACE_KEY] = []
|
|
||||||
ri.router[l3_constants.FLOATINGIP_KEY] = []
|
|
||||||
self.process_router(ri)
|
|
||||||
|
|
||||||
name = va_utils.get_snat_rule_name(ri)
|
|
||||||
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, name)
|
|
||||||
|
|
||||||
name = va_utils.get_dnat_rule_name(ri)
|
|
||||||
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, name)
|
|
||||||
|
|
||||||
name = va_utils.get_trusted_zone_name(ri)
|
|
||||||
self._va_unset_zone_interfaces(name, True)
|
|
||||||
|
|
||||||
name = va_utils.get_untrusted_zone_name(ri)
|
|
||||||
self._va_unset_zone_interfaces(name, True)
|
|
||||||
|
|
||||||
del self.router_info[router_id]
|
|
||||||
|
|
||||||
def _spawn_metadata_proxy(self, router_id, ns_name):
|
|
||||||
return
|
|
||||||
|
|
||||||
def _destroy_metadata_proxy(self, router_id, ns_name):
|
|
||||||
return
|
|
||||||
|
|
||||||
def _set_subnet_info(self, port):
|
|
||||||
ips = port['fixed_ips']
|
|
||||||
if not ips:
|
|
||||||
raise Exception(_("Router port %s has no IP address") % port['id'])
|
|
||||||
if len(ips) > 1:
|
|
||||||
LOG.warning(_LW("Ignoring multiple IPs on router port %s"),
|
|
||||||
port['id'])
|
|
||||||
prefixlen = netaddr.IPNetwork(port['subnet']['cidr']).prefixlen
|
|
||||||
port['ip_cidr'] = "%s/%s" % (ips[0]['ip_address'], prefixlen)
|
|
||||||
|
|
||||||
def _va_unset_zone_interfaces(self, zone_name, remove_zone=False):
|
|
||||||
# return True if zone exists; otherwise, return False
|
|
||||||
LOG.debug("_va_unset_zone_interfaces: %s", zone_name)
|
|
||||||
resp = self.rest.rest_api('GET', va_utils.REST_URL_CONF_ZONE)
|
|
||||||
if resp and resp['status'] == 200:
|
|
||||||
zlist = resp['body']['response']
|
|
||||||
for zn in zlist:
|
|
||||||
if zn == zone_name:
|
|
||||||
commit = False
|
|
||||||
|
|
||||||
if 'interface' in zlist[zn]:
|
|
||||||
for intf in zlist[zn]['interface']:
|
|
||||||
self.rest.rest_api('DELETE',
|
|
||||||
va_utils.REST_URL_CONF +
|
|
||||||
va_utils.REST_ZONE_NAME % zn +
|
|
||||||
va_utils.REST_INTF_NAME % intf)
|
|
||||||
commit = True
|
|
||||||
if remove_zone:
|
|
||||||
self.rest.rest_api('DELETE',
|
|
||||||
va_utils.REST_URL_CONF +
|
|
||||||
va_utils.REST_ZONE_NAME % zn)
|
|
||||||
commit = True
|
|
||||||
|
|
||||||
if commit:
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _va_pif_2_lif(self, pif):
|
|
||||||
return pif + '.0'
|
|
||||||
|
|
||||||
def _va_set_interface_ip(self, pif, cidr):
|
|
||||||
LOG.debug("_va_set_interface_ip: %(pif)s %(cidr)s",
|
|
||||||
{'pif': pif, 'cidr': cidr})
|
|
||||||
|
|
||||||
lif = self._va_pif_2_lif(pif)
|
|
||||||
obj = va_utils.REST_INTF_NAME % pif + va_utils.REST_LOGIC_NAME % lif
|
|
||||||
body = {
|
|
||||||
'name': lif,
|
|
||||||
'family': 'ipv4',
|
|
||||||
'address': cidr
|
|
||||||
}
|
|
||||||
self.rest.rest_api('PUT', va_utils.REST_URL_CONF + obj, body)
|
|
||||||
|
|
||||||
def _va_get_port_name(self, port_list, name):
|
|
||||||
if name:
|
|
||||||
for p in port_list:
|
|
||||||
if p['VM name'] == name:
|
|
||||||
return p['name']
|
|
||||||
|
|
||||||
def _va_config_trusted_zone(self, ri, plist):
|
|
||||||
zone = va_utils.get_trusted_zone_name(ri)
|
|
||||||
LOG.debug("_va_config_trusted_zone: %s", zone)
|
|
||||||
|
|
||||||
body = {
|
|
||||||
'name': zone,
|
|
||||||
'type': 'L3',
|
|
||||||
'interface': []
|
|
||||||
}
|
|
||||||
|
|
||||||
if not self._va_unset_zone_interfaces(zone):
|
|
||||||
# if zone doesn't exist, create it
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body)
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
# add new internal ports to trusted zone
|
|
||||||
for p in ri.internal_ports:
|
|
||||||
if p['admin_state_up']:
|
|
||||||
dev = self.get_internal_device_name(p['id'])
|
|
||||||
pif = self._va_get_port_name(plist, dev)
|
|
||||||
if pif:
|
|
||||||
lif = self._va_pif_2_lif(pif)
|
|
||||||
if lif not in body['interface']:
|
|
||||||
body['interface'].append(lif)
|
|
||||||
|
|
||||||
self._va_set_interface_ip(pif, p['ip_cidr'])
|
|
||||||
|
|
||||||
if body['interface']:
|
|
||||||
self.rest.rest_api('PUT', va_utils.REST_URL_CONF_ZONE, body)
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
def _va_config_untrusted_zone(self, ri, plist):
|
|
||||||
zone = va_utils.get_untrusted_zone_name(ri)
|
|
||||||
LOG.debug("_va_config_untrusted_zone: %s", zone)
|
|
||||||
|
|
||||||
body = {
|
|
||||||
'name': zone,
|
|
||||||
'type': 'L3',
|
|
||||||
'interface': []
|
|
||||||
}
|
|
||||||
|
|
||||||
if not self._va_unset_zone_interfaces(zone):
|
|
||||||
# if zone doesn't exist, create it
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body)
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
# add new gateway ports to untrusted zone
|
|
||||||
if ri.ex_gw_port:
|
|
||||||
LOG.debug("_va_config_untrusted_zone: gw=%r", ri.ex_gw_port)
|
|
||||||
dev = self.get_external_device_name(ri.ex_gw_port['id'])
|
|
||||||
pif = self._va_get_port_name(plist, dev)
|
|
||||||
if pif:
|
|
||||||
lif = self._va_pif_2_lif(pif)
|
|
||||||
|
|
||||||
self._va_set_interface_ip(pif, ri.ex_gw_port['ip_cidr'])
|
|
||||||
|
|
||||||
body['interface'].append(lif)
|
|
||||||
self.rest.rest_api('PUT', va_utils.REST_URL_CONF_ZONE, body)
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
def _va_config_router_snat_rules(self, ri, plist):
|
|
||||||
LOG.debug('_va_config_router_snat_rules: %s', ri.router['id'])
|
|
||||||
|
|
||||||
prefix = va_utils.get_snat_rule_name(ri)
|
|
||||||
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, prefix)
|
|
||||||
|
|
||||||
if not ri.enable_snat:
|
|
||||||
return
|
|
||||||
|
|
||||||
for idx, p in enumerate(ri.internal_ports):
|
|
||||||
if p['admin_state_up']:
|
|
||||||
dev = self.get_internal_device_name(p['id'])
|
|
||||||
pif = self._va_get_port_name(plist, dev)
|
|
||||||
if pif:
|
|
||||||
net = netaddr.IPNetwork(p['ip_cidr'])
|
|
||||||
body = {
|
|
||||||
'name': '%s_%d' % (prefix, idx),
|
|
||||||
'ingress-context-type': 'interface',
|
|
||||||
'ingress-index': self._va_pif_2_lif(pif),
|
|
||||||
'source-address': [
|
|
||||||
[str(netaddr.IPAddress(net.first + 2)),
|
|
||||||
str(netaddr.IPAddress(net.last - 1))]
|
|
||||||
],
|
|
||||||
'flag': 'interface translate-source'
|
|
||||||
}
|
|
||||||
self.rest.rest_api('POST',
|
|
||||||
va_utils.REST_URL_CONF_NAT_RULE,
|
|
||||||
body)
|
|
||||||
|
|
||||||
if ri.internal_ports:
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
def _va_config_floating_ips(self, ri):
|
|
||||||
LOG.debug('_va_config_floating_ips: %s', ri.router['id'])
|
|
||||||
|
|
||||||
prefix = va_utils.get_dnat_rule_name(ri)
|
|
||||||
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, prefix)
|
|
||||||
|
|
||||||
# add new dnat rules
|
|
||||||
for idx, fip in enumerate(ri.floating_ips):
|
|
||||||
body = {
|
|
||||||
'name': '%s_%d' % (prefix, idx),
|
|
||||||
'ingress-context-type': 'zone',
|
|
||||||
'ingress-index': va_utils.get_untrusted_zone_name(ri),
|
|
||||||
'destination-address': [[fip['floating_ip_address'],
|
|
||||||
fip['floating_ip_address']]],
|
|
||||||
'static': [fip['fixed_ip_address'], fip['fixed_ip_address']],
|
|
||||||
'flag': 'translate-destination'
|
|
||||||
}
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_NAT_RULE, body)
|
|
||||||
|
|
||||||
if ri.floating_ips:
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
def process_router(self, ri):
|
|
||||||
LOG.debug("process_router: %s", ri.router['id'])
|
|
||||||
super(vArmourL3NATAgent, self).process_router(ri)
|
|
||||||
|
|
||||||
self.rest.auth()
|
|
||||||
|
|
||||||
# read internal port name and configuration port name map
|
|
||||||
resp = self.rest.rest_api('GET', va_utils.REST_URL_INTF_MAP)
|
|
||||||
if resp and resp['status'] == 200:
|
|
||||||
try:
|
|
||||||
plist = resp['body']['response']
|
|
||||||
except ValueError:
|
|
||||||
LOG.warning(_LW("Unable to parse interface mapping."))
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
LOG.warning(_LW("Unable to read interface mapping."))
|
|
||||||
return
|
|
||||||
|
|
||||||
if ri.ex_gw_port:
|
|
||||||
self._set_subnet_info(ri.ex_gw_port)
|
|
||||||
self._va_config_trusted_zone(ri, plist)
|
|
||||||
self._va_config_untrusted_zone(ri, plist)
|
|
||||||
self._va_config_router_snat_rules(ri, plist)
|
|
||||||
self._va_config_floating_ips(ri)
|
|
||||||
|
|
||||||
def _handle_router_snat_rules(self, ri, ex_gw_port,
|
|
||||||
interface_name, action):
|
|
||||||
return
|
|
||||||
|
|
||||||
def _send_gratuitous_arp_packet(self, ri, interface_name, ip_address):
|
|
||||||
return
|
|
||||||
|
|
||||||
def external_gateway_added(self, ri, ex_gw_port,
|
|
||||||
interface_name, internal_cidrs):
|
|
||||||
LOG.debug("external_gateway_added: %s", ri.router['id'])
|
|
||||||
|
|
||||||
if not ip_lib.device_exists(interface_name, namespace=ri.ns_name):
|
|
||||||
self.driver.plug(ex_gw_port['network_id'],
|
|
||||||
ex_gw_port['id'], interface_name,
|
|
||||||
ex_gw_port['mac_address'],
|
|
||||||
bridge=self.conf.external_network_bridge,
|
|
||||||
namespace=ri.ns_name,
|
|
||||||
prefix=agent.EXTERNAL_DEV_PREFIX)
|
|
||||||
self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']],
|
|
||||||
namespace=ri.ns_name)
|
|
||||||
|
|
||||||
def _update_routing_table(self, ri, operation, route):
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class vArmourL3NATAgentWithStateReport(vArmourL3NATAgent,
|
|
||||||
agent.L3NATAgentWithStateReport):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
conf = cfg.CONF
|
|
||||||
conf.register_opts(l3_config.OPTS)
|
|
||||||
conf.register_opts(ha.OPTS)
|
|
||||||
config.register_interface_driver_opts_helper(conf)
|
|
||||||
config.register_agent_state_opts_helper(conf)
|
|
||||||
conf.register_opts(interface.OPTS)
|
|
||||||
conf.register_opts(external_process.OPTS)
|
|
||||||
common_config.init(sys.argv[1:])
|
|
||||||
config.setup_logging()
|
|
||||||
server = neutron_service.Service.create(
|
|
||||||
binary='neutron-l3-agent',
|
|
||||||
topic=f_const.L3_AGENT,
|
|
||||||
report_interval=cfg.CONF.AGENT.report_interval,
|
|
||||||
manager='neutron_fwaas.services.firewall.agents.varmour.'
|
|
||||||
'varmour_router.vArmourL3NATAgentWithStateReport')
|
|
||||||
service.launch(conf, server).wait()
|
|
|
@ -1,70 +0,0 @@
|
||||||
# Copyright 2013 vArmour 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.
|
|
||||||
|
|
||||||
ROUTER_OBJ_PREFIX = 'r-'
|
|
||||||
OBJ_PREFIX_LEN = 8
|
|
||||||
TRUST_ZONE = '_z_trust'
|
|
||||||
UNTRUST_ZONE = '_z_untrust'
|
|
||||||
SNAT_RULE = '_snat'
|
|
||||||
DNAT_RULE = '_dnat'
|
|
||||||
ROUTER_POLICY = '_p'
|
|
||||||
|
|
||||||
REST_URL_CONF = '/config'
|
|
||||||
REST_URL_AUTH = '/auth'
|
|
||||||
REST_URL_COMMIT = '/commit'
|
|
||||||
REST_URL_INTF_MAP = '/operation/interface/mapping'
|
|
||||||
|
|
||||||
REST_URL_CONF_NAT_RULE = REST_URL_CONF + '/nat/rule'
|
|
||||||
REST_URL_CONF_ZONE = REST_URL_CONF + '/zone'
|
|
||||||
REST_URL_CONF_POLICY = REST_URL_CONF + '/policy'
|
|
||||||
REST_URL_CONF_ADDR = REST_URL_CONF + '/address'
|
|
||||||
REST_URL_CONF_SERVICE = REST_URL_CONF + '/service'
|
|
||||||
|
|
||||||
REST_ZONE_NAME = '/zone/"name:%s"'
|
|
||||||
REST_INTF_NAME = '/interface/"name:%s"'
|
|
||||||
REST_LOGIC_NAME = '/logical/"name:%s"'
|
|
||||||
REST_SERVICE_NAME = '/service/"name:%s"/rule'
|
|
||||||
|
|
||||||
|
|
||||||
def get_router_object_prefix(ri):
|
|
||||||
return ROUTER_OBJ_PREFIX + ri.router['id'][:OBJ_PREFIX_LEN]
|
|
||||||
|
|
||||||
|
|
||||||
def get_firewall_object_prefix(ri, fw):
|
|
||||||
return get_router_object_prefix(ri) + '-' + fw['id'][:OBJ_PREFIX_LEN]
|
|
||||||
|
|
||||||
|
|
||||||
def get_trusted_zone_name(ri):
|
|
||||||
return get_router_object_prefix(ri) + TRUST_ZONE
|
|
||||||
|
|
||||||
|
|
||||||
def get_untrusted_zone_name(ri):
|
|
||||||
return get_router_object_prefix(ri) + UNTRUST_ZONE
|
|
||||||
|
|
||||||
|
|
||||||
def get_snat_rule_name(ri):
|
|
||||||
return get_router_object_prefix(ri) + SNAT_RULE
|
|
||||||
|
|
||||||
|
|
||||||
def get_dnat_rule_name(ri):
|
|
||||||
return get_router_object_prefix(ri) + DNAT_RULE
|
|
||||||
|
|
||||||
|
|
||||||
def get_router_policy_name(ri):
|
|
||||||
return get_router_object_prefix(ri) + ROUTER_POLICY
|
|
||||||
|
|
||||||
|
|
||||||
def get_firewall_policy_name(ri, fw, rule):
|
|
||||||
return get_firewall_object_prefix(ri, fw) + rule['id'][:OBJ_PREFIX_LEN]
|
|
|
@ -1,208 +0,0 @@
|
||||||
# Copyright 2013 vArmour 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 oslo_log import log as logging
|
|
||||||
|
|
||||||
from neutron_fwaas._i18n import _LW
|
|
||||||
from neutron_fwaas.services.firewall.agents.varmour import varmour_api
|
|
||||||
from neutron_fwaas.services.firewall.agents.varmour \
|
|
||||||
import varmour_utils as va_utils
|
|
||||||
from neutron_fwaas.services.firewall.drivers import fwaas_base
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class vArmourFwaasDriver(fwaas_base.FwaasDriverBase):
|
|
||||||
def __init__(self):
|
|
||||||
LOG.debug("Initializing fwaas vArmour driver")
|
|
||||||
|
|
||||||
self.fake_agent_mode = None
|
|
||||||
self.rest = varmour_api.vArmourRestAPI()
|
|
||||||
|
|
||||||
def create_firewall(self, agent_mode, apply_list, firewall):
|
|
||||||
LOG.debug('create_firewall (%s)', firewall['id'])
|
|
||||||
|
|
||||||
return self.update_firewall(self.fake_agent_mode, apply_list, firewall)
|
|
||||||
|
|
||||||
def update_firewall(self, agent_mode, apply_list, firewall):
|
|
||||||
LOG.debug("update_firewall (%s)", firewall['id'])
|
|
||||||
|
|
||||||
if firewall['admin_state_up']:
|
|
||||||
return self._update_firewall(apply_list, firewall)
|
|
||||||
else:
|
|
||||||
return self.apply_default_policy(apply_list, firewall)
|
|
||||||
|
|
||||||
def delete_firewall(self, agent_mode, apply_list, firewall):
|
|
||||||
LOG.debug("delete_firewall (%s)", firewall['id'])
|
|
||||||
|
|
||||||
return self.apply_default_policy(self.fake_agent_mode, apply_list,
|
|
||||||
firewall)
|
|
||||||
|
|
||||||
def apply_default_policy(self, agent_mode, apply_list, firewall):
|
|
||||||
LOG.debug("apply_default_policy (%s)", firewall['id'])
|
|
||||||
|
|
||||||
self.rest.auth()
|
|
||||||
|
|
||||||
for ri in apply_list:
|
|
||||||
self._clear_policy(ri, firewall)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _update_firewall(self, apply_list, firewall):
|
|
||||||
LOG.debug("Updating firewall (%s)", firewall['id'])
|
|
||||||
|
|
||||||
self.rest.auth()
|
|
||||||
|
|
||||||
for ri in apply_list:
|
|
||||||
self._clear_policy(ri, firewall)
|
|
||||||
self._setup_policy(ri, firewall)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _setup_policy(self, ri, fw):
|
|
||||||
# create zones no matter if they exist. Interfaces are added by router
|
|
||||||
body = {
|
|
||||||
'type': 'L3',
|
|
||||||
'interface': []
|
|
||||||
}
|
|
||||||
|
|
||||||
body['name'] = va_utils.get_trusted_zone_name(ri)
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body)
|
|
||||||
body['name'] = va_utils.get_untrusted_zone_name(ri)
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body)
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
servs = dict()
|
|
||||||
addrs = dict()
|
|
||||||
for rule in fw['firewall_rule_list']:
|
|
||||||
if not rule['enabled']:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if rule['ip_version'] == 4:
|
|
||||||
service = self._make_service(ri, fw, rule, servs)
|
|
||||||
s_addr = self._make_address(ri, fw, rule, addrs, True)
|
|
||||||
d_addr = self._make_address(ri, fw, rule, addrs, False)
|
|
||||||
|
|
||||||
policy = va_utils.get_firewall_policy_name(ri, fw, rule)
|
|
||||||
z0 = va_utils.get_trusted_zone_name(ri)
|
|
||||||
z1 = va_utils.get_untrusted_zone_name(ri)
|
|
||||||
body = self._make_policy(policy + '_0', rule,
|
|
||||||
z0, z0, s_addr, d_addr, service)
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_POLICY, body)
|
|
||||||
body = self._make_policy(policy + '_1', rule,
|
|
||||||
z0, z1, s_addr, d_addr, service)
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_POLICY, body)
|
|
||||||
body = self._make_policy(policy + '_2', rule,
|
|
||||||
z1, z0, s_addr, d_addr, service)
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_POLICY, body)
|
|
||||||
|
|
||||||
self.rest.commit()
|
|
||||||
else:
|
|
||||||
LOG.warning(_LW("Unsupported IP version rule."))
|
|
||||||
|
|
||||||
def _clear_policy(self, ri, fw):
|
|
||||||
prefix = va_utils.get_firewall_object_prefix(ri, fw)
|
|
||||||
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_POLICY, prefix)
|
|
||||||
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_ADDR, prefix)
|
|
||||||
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_SERVICE, prefix)
|
|
||||||
|
|
||||||
def _make_service(self, ri, fw, rule, servs):
|
|
||||||
prefix = va_utils.get_firewall_object_prefix(ri, fw)
|
|
||||||
|
|
||||||
if rule.get('protocol'):
|
|
||||||
key = rule.get('protocol')
|
|
||||||
if rule.get('source_port'):
|
|
||||||
key += '-' + rule.get('source_port')
|
|
||||||
if rule.get('destination_port'):
|
|
||||||
key += '-' + rule.get('destination_port')
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
if key in servs:
|
|
||||||
name = '%s_%d' % (prefix, servs[key])
|
|
||||||
else:
|
|
||||||
# create new service object with index
|
|
||||||
idx = len(servs)
|
|
||||||
servs[key] = idx
|
|
||||||
name = '%s_%d' % (prefix, idx)
|
|
||||||
|
|
||||||
body = {'name': name}
|
|
||||||
self.rest.rest_api('POST',
|
|
||||||
va_utils.REST_URL_CONF_SERVICE,
|
|
||||||
body)
|
|
||||||
body = self._make_service_rule(rule)
|
|
||||||
self.rest.rest_api('POST',
|
|
||||||
va_utils.REST_URL_CONF +
|
|
||||||
va_utils.REST_SERVICE_NAME % name,
|
|
||||||
body)
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
return name
|
|
||||||
|
|
||||||
def _make_service_rule(self, rule):
|
|
||||||
body = {
|
|
||||||
'name': '1',
|
|
||||||
'protocol': rule.get('protocol')
|
|
||||||
}
|
|
||||||
if 'source_port' in rule:
|
|
||||||
body['source-start'] = rule['source_port']
|
|
||||||
body['source-end'] = rule['source_port']
|
|
||||||
if 'destination_port' in rule:
|
|
||||||
body['dest-start'] = rule['destination_port']
|
|
||||||
body['dest-end'] = rule['destination_port']
|
|
||||||
|
|
||||||
return body
|
|
||||||
|
|
||||||
def _make_address(self, ri, fw, rule, addrs, is_src):
|
|
||||||
prefix = va_utils.get_firewall_object_prefix(ri, fw)
|
|
||||||
|
|
||||||
if is_src:
|
|
||||||
key = rule.get('source_ip_address')
|
|
||||||
else:
|
|
||||||
key = rule.get('destination_ip_address')
|
|
||||||
|
|
||||||
if not key:
|
|
||||||
return
|
|
||||||
|
|
||||||
if key in addrs:
|
|
||||||
name = '%s_%d' % (prefix, addrs[key])
|
|
||||||
else:
|
|
||||||
# create new address object with idx
|
|
||||||
idx = len(addrs)
|
|
||||||
addrs[key] = idx
|
|
||||||
name = '%s_%d' % (prefix, idx)
|
|
||||||
|
|
||||||
body = {
|
|
||||||
'name': name,
|
|
||||||
'type': 'ipv4',
|
|
||||||
'ipv4': key
|
|
||||||
}
|
|
||||||
self.rest.rest_api('POST', va_utils.REST_URL_CONF_ADDR, body)
|
|
||||||
self.rest.commit()
|
|
||||||
|
|
||||||
return name
|
|
||||||
|
|
||||||
def _make_policy(self, name, rule, zone0, zone1, s_addr, d_addr, service):
|
|
||||||
body = {
|
|
||||||
'name': name,
|
|
||||||
'action': 'permit' if rule.get('action') == 'allow' else 'deny',
|
|
||||||
'from': zone0,
|
|
||||||
'to': zone1,
|
|
||||||
'match-source-address': [s_addr or 'Any'],
|
|
||||||
'match-dest-address': [d_addr or 'Any'],
|
|
||||||
'match-service': [service or 'Any']
|
|
||||||
}
|
|
||||||
|
|
||||||
return body
|
|
|
@ -1,202 +0,0 @@
|
||||||
# Copyright 2013 vArmour 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.agent.common import config as agent_config
|
|
||||||
from neutron.agent.l3 import config as l3_config
|
|
||||||
from neutron.agent.l3 import ha
|
|
||||||
from neutron.agent.l3 import router_info
|
|
||||||
from neutron.agent.linux import interface
|
|
||||||
from neutron_fwaas.services.firewall.agents.varmour import varmour_router
|
|
||||||
from neutron_fwaas.tests import base
|
|
||||||
from neutron_lib import constants as l3_constants
|
|
||||||
from oslo_utils import uuidutils
|
|
||||||
|
|
||||||
|
|
||||||
_uuid = uuidutils.generate_uuid
|
|
||||||
HOSTNAME = 'myhost'
|
|
||||||
FAKE_DIRECTOR = '1.1.1.1'
|
|
||||||
|
|
||||||
|
|
||||||
class TestVarmourRouter(base.BaseTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.skipTest('this is broken')
|
|
||||||
super(TestVarmourRouter, self).setUp()
|
|
||||||
self.conf = agent_config.setup_conf()
|
|
||||||
self.conf.register_opts(l3_config.OPTS)
|
|
||||||
self.conf.register_opts(ha.OPTS)
|
|
||||||
agent_config.register_process_monitor_opts(self.conf)
|
|
||||||
agent_config.register_interface_driver_opts_helper(self.conf)
|
|
||||||
self.conf.register_opts(interface.OPTS)
|
|
||||||
self.conf.set_override('interface_driver',
|
|
||||||
'neutron.agent.linux.interface.NullDriver')
|
|
||||||
self.conf.state_path = ''
|
|
||||||
|
|
||||||
self.device_exists_p = mock.patch(
|
|
||||||
'neutron.agent.linux.ip_lib.device_exists')
|
|
||||||
self.device_exists = self.device_exists_p.start()
|
|
||||||
|
|
||||||
self.utils_exec_p = mock.patch(
|
|
||||||
'neutron.agent.linux.utils.execute')
|
|
||||||
self.utils_exec = self.utils_exec_p.start()
|
|
||||||
|
|
||||||
self.external_process_p = mock.patch(
|
|
||||||
'neutron.agent.linux.external_process.ProcessManager')
|
|
||||||
self.external_process = self.external_process_p.start()
|
|
||||||
|
|
||||||
self.makedirs_p = mock.patch('os.makedirs')
|
|
||||||
self.makedirs = self.makedirs_p.start()
|
|
||||||
|
|
||||||
self.dvr_cls_p = mock.patch('neutron.agent.linux.interface.NullDriver')
|
|
||||||
driver_cls = self.dvr_cls_p.start()
|
|
||||||
self.mock_driver = mock.MagicMock()
|
|
||||||
self.mock_driver.DEV_NAME_LEN = (
|
|
||||||
interface.LinuxInterfaceDriver.DEV_NAME_LEN)
|
|
||||||
driver_cls.return_value = self.mock_driver
|
|
||||||
|
|
||||||
self.ip_cls_p = mock.patch('neutron.agent.linux.ip_lib.IPWrapper')
|
|
||||||
ip_cls = self.ip_cls_p.start()
|
|
||||||
self.mock_ip = mock.MagicMock()
|
|
||||||
ip_cls.return_value = self.mock_ip
|
|
||||||
|
|
||||||
mock.patch('neutron.agent.l3.agent.L3PluginApi').start()
|
|
||||||
|
|
||||||
self.looping_call_p = mock.patch(
|
|
||||||
'oslo_service.loopingcall.FixedIntervalLoopingCall')
|
|
||||||
self.looping_call_p.start()
|
|
||||||
self.ri_kwargs = {'agent_conf': self.conf,
|
|
||||||
'interface_driver': self.mock_driver}
|
|
||||||
|
|
||||||
def _create_router(self):
|
|
||||||
router = varmour_router.vArmourL3NATAgent(HOSTNAME, self.conf)
|
|
||||||
router.rest.server = FAKE_DIRECTOR
|
|
||||||
router.rest.user = 'varmour'
|
|
||||||
router.rest.passwd = 'varmour'
|
|
||||||
return router
|
|
||||||
|
|
||||||
def _del_all_internal_ports(self, router):
|
|
||||||
router[l3_constants.INTERFACE_KEY] = []
|
|
||||||
|
|
||||||
def _del_internal_ports(self, router, port_idx):
|
|
||||||
del router[l3_constants.INTERFACE_KEY][port_idx]
|
|
||||||
|
|
||||||
def _add_internal_ports(self, router, port_count=1):
|
|
||||||
self._del_all_internal_ports(router)
|
|
||||||
for i in range(port_count):
|
|
||||||
port = {'id': _uuid(),
|
|
||||||
'network_id': _uuid(),
|
|
||||||
'admin_state_up': True,
|
|
||||||
'fixed_ips': [{'ip_address': '10.0.%s.4' % i,
|
|
||||||
'subnet_id': _uuid()}],
|
|
||||||
'mac_address': 'ca:fe:de:ad:be:ef',
|
|
||||||
'subnet': {'cidr': '10.0.%s.0/24' % i,
|
|
||||||
'gateway_ip': '10.0.%s.1' % i}}
|
|
||||||
router[l3_constants.INTERFACE_KEY].append(port)
|
|
||||||
|
|
||||||
def _del_all_floating_ips(self, router):
|
|
||||||
router[l3_constants.FLOATINGIP_KEY] = []
|
|
||||||
|
|
||||||
def _del_floating_ips(self, router, port_idx):
|
|
||||||
del router[l3_constants.FLOATINGIP_KEY][port_idx]
|
|
||||||
|
|
||||||
def _add_floating_ips(self, router, port_count=1):
|
|
||||||
self._del_all_floating_ips(router)
|
|
||||||
for i in range(port_count):
|
|
||||||
fip = {'id': _uuid(),
|
|
||||||
'port_id': router['gw_port']['id'],
|
|
||||||
'floating_ip_address': '172.24.4.%s' % (100 + i),
|
|
||||||
'fixed_ip_address': '10.0.0.%s' % (100 + i)}
|
|
||||||
router[l3_constants.FLOATINGIP_KEY].append(fip)
|
|
||||||
|
|
||||||
def _prepare_router_data(self, enable_snat=None):
|
|
||||||
router_id = _uuid()
|
|
||||||
ex_gw_port = {'id': _uuid(),
|
|
||||||
'mac_address': 'ca:fe:de:ad:be:ee',
|
|
||||||
'network_id': _uuid(),
|
|
||||||
'fixed_ips': [{'ip_address': '172.24.4.2',
|
|
||||||
'subnet_id': _uuid()}],
|
|
||||||
'subnet': {'cidr': '172.24.4.0/24',
|
|
||||||
'gateway_ip': '172.24.4.1'},
|
|
||||||
'ip_cidr': '172.24.4.226/28'}
|
|
||||||
int_ports = []
|
|
||||||
|
|
||||||
router = {
|
|
||||||
'id': router_id,
|
|
||||||
'distributed': False,
|
|
||||||
l3_constants.INTERFACE_KEY: int_ports,
|
|
||||||
'routes': [],
|
|
||||||
'gw_port': ex_gw_port}
|
|
||||||
if enable_snat is not None:
|
|
||||||
router['enable_snat'] = enable_snat
|
|
||||||
|
|
||||||
ri = router_info.RouterInfo(router_id=router['id'], router=router,
|
|
||||||
**self.ri_kwargs)
|
|
||||||
return ri
|
|
||||||
|
|
||||||
def test_agent_add_internal_network(self):
|
|
||||||
router = self._create_router()
|
|
||||||
self._add_internal_ports = mock.Mock()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
router._router_added(ri.router['id'], ri.router)
|
|
||||||
self._add_internal_ports(ri.router, port_count=1)
|
|
||||||
self._add_internal_ports.assert_called_once_with(ri.router,
|
|
||||||
port_count=1)
|
|
||||||
|
|
||||||
def test_agent_remove_internal_network(self):
|
|
||||||
router = self._create_router()
|
|
||||||
self._del_internal_ports = mock.Mock()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
router._router_added(ri.router['id'], ri.router)
|
|
||||||
self._add_internal_ports(ri.router, port_count=2)
|
|
||||||
self._del_internal_ports(ri.router, 0)
|
|
||||||
self._del_internal_ports.assert_called_once_with(ri.router, 0)
|
|
||||||
|
|
||||||
def test_agent_add_floating_ips(self):
|
|
||||||
router = self._create_router()
|
|
||||||
self._add_floating_ips = mock.Mock()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
self._add_internal_ports(ri.router, port_count=1)
|
|
||||||
router._router_added(ri.router['id'], ri.router)
|
|
||||||
self._add_floating_ips(ri.router, port_count=1)
|
|
||||||
self._add_floating_ips.assert_called_once_with(ri.router, port_count=1)
|
|
||||||
|
|
||||||
def test_agent_remove_floating_ips(self):
|
|
||||||
router = self._create_router()
|
|
||||||
self._del_floating_ips = mock.Mock()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
self._add_internal_ports(ri.router, port_count=1)
|
|
||||||
self._add_floating_ips(ri.router, port_count=2)
|
|
||||||
router._router_added(ri.router['id'], ri.router)
|
|
||||||
self._del_floating_ips(ri.router, 0)
|
|
||||||
self._del_floating_ips.assert_called_once_with(ri.router, 0)
|
|
||||||
|
|
||||||
def test_agent_external_gateway(self):
|
|
||||||
router = self._create_router()
|
|
||||||
router._router_removed = mock.Mock()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
router._router_added(ri.router['id'], ri.router)
|
|
||||||
router._router_removed(ri.router['id'])
|
|
||||||
router._router_removed.assert_called_once_with(ri.router['id'])
|
|
||||||
|
|
||||||
def test_agent_snat_enable(self):
|
|
||||||
router = self._create_router()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
router._router_added(ri.router['id'], ri.router)
|
|
||||||
ri.router['enable_snat'] = False
|
|
||||||
self.assertFalse(ri.router['enable_snat'])
|
|
|
@ -1,220 +0,0 @@
|
||||||
# Copyright 2013 vArmour 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.agent.common import config as agent_config
|
|
||||||
from neutron.agent.l3 import config as l3_config
|
|
||||||
from neutron.agent.l3 import ha
|
|
||||||
from neutron.agent.l3 import router_info
|
|
||||||
from neutron.agent.linux import interface
|
|
||||||
from neutron.tests import base
|
|
||||||
from neutron_lib import constants as l3_constants
|
|
||||||
from oslo_utils import uuidutils
|
|
||||||
|
|
||||||
from neutron_fwaas.services.firewall.agents.varmour import varmour_router
|
|
||||||
from neutron_fwaas.services.firewall.drivers.varmour import varmour_fwaas
|
|
||||||
|
|
||||||
_uuid = uuidutils.generate_uuid
|
|
||||||
HOSTNAME = 'myhost'
|
|
||||||
FAKE_DIRECTOR = '1.1.1.1'
|
|
||||||
|
|
||||||
|
|
||||||
class TestBasicRouterOperations(base.BaseTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestBasicRouterOperations, self).setUp()
|
|
||||||
self.conf = agent_config.setup_conf()
|
|
||||||
self.conf.register_opts(l3_config.OPTS)
|
|
||||||
self.conf.register_opts(ha.OPTS)
|
|
||||||
agent_config.register_process_monitor_opts(self.conf)
|
|
||||||
agent_config.register_interface_driver_opts_helper(self.conf)
|
|
||||||
self.conf.register_opts(interface.OPTS)
|
|
||||||
self.conf.set_override('interface_driver',
|
|
||||||
'neutron.agent.linux.interface.NullDriver')
|
|
||||||
self.conf.state_path = ''
|
|
||||||
|
|
||||||
self.device_exists_p = mock.patch(
|
|
||||||
'neutron.agent.linux.ip_lib.device_exists')
|
|
||||||
self.device_exists = self.device_exists_p.start()
|
|
||||||
|
|
||||||
self.utils_exec_p = mock.patch(
|
|
||||||
'neutron.agent.linux.utils.execute')
|
|
||||||
self.utils_exec = self.utils_exec_p.start()
|
|
||||||
|
|
||||||
self.external_process_p = mock.patch(
|
|
||||||
'neutron.agent.linux.external_process.ProcessManager')
|
|
||||||
self.external_process = self.external_process_p.start()
|
|
||||||
|
|
||||||
self.makedirs_p = mock.patch('os.makedirs')
|
|
||||||
self.makedirs = self.makedirs_p.start()
|
|
||||||
|
|
||||||
self.dvr_cls_p = mock.patch('neutron.agent.linux.interface.NullDriver')
|
|
||||||
driver_cls = self.dvr_cls_p.start()
|
|
||||||
self.mock_driver = mock.MagicMock()
|
|
||||||
self.mock_driver.DEV_NAME_LEN = (
|
|
||||||
interface.LinuxInterfaceDriver.DEV_NAME_LEN)
|
|
||||||
driver_cls.return_value = self.mock_driver
|
|
||||||
|
|
||||||
self.ip_cls_p = mock.patch('neutron.agent.linux.ip_lib.IPWrapper')
|
|
||||||
ip_cls = self.ip_cls_p.start()
|
|
||||||
self.mock_ip = mock.MagicMock()
|
|
||||||
ip_cls.return_value = self.mock_ip
|
|
||||||
|
|
||||||
mock.patch('neutron.agent.l3.agent.L3PluginApi').start()
|
|
||||||
|
|
||||||
self.looping_call_p = mock.patch(
|
|
||||||
'oslo_service.loopingcall.FixedIntervalLoopingCall')
|
|
||||||
self.looping_call_p.start()
|
|
||||||
|
|
||||||
self.fake_agent_mode = None
|
|
||||||
self.ri_kwargs = {'agent_conf': self.conf,
|
|
||||||
'interface_driver': self.mock_driver}
|
|
||||||
|
|
||||||
def _create_router(self):
|
|
||||||
router = varmour_router.vArmourL3NATAgent(HOSTNAME, self.conf)
|
|
||||||
router.rest.server = FAKE_DIRECTOR
|
|
||||||
router.rest.user = 'varmour'
|
|
||||||
router.rest.passwd = 'varmour'
|
|
||||||
return router
|
|
||||||
|
|
||||||
def _create_fwaas(self):
|
|
||||||
fwaas = varmour_fwaas.vArmourFwaasDriver()
|
|
||||||
fwaas.rest.server = FAKE_DIRECTOR
|
|
||||||
fwaas.rest.user = 'varmour'
|
|
||||||
fwaas.rest.passwd = 'varmour'
|
|
||||||
return fwaas
|
|
||||||
|
|
||||||
def _del_all_internal_ports(self, router):
|
|
||||||
router[l3_constants.INTERFACE_KEY] = []
|
|
||||||
|
|
||||||
def _del_internal_ports(self, router, port_idx):
|
|
||||||
del router[l3_constants.INTERFACE_KEY][port_idx]
|
|
||||||
|
|
||||||
def _add_internal_ports(self, router, port_count=1):
|
|
||||||
self._del_all_internal_ports(router)
|
|
||||||
for i in range(port_count):
|
|
||||||
port = {'id': _uuid(),
|
|
||||||
'network_id': _uuid(),
|
|
||||||
'admin_state_up': True,
|
|
||||||
'fixed_ips': [{'ip_address': '10.0.%s.4' % i,
|
|
||||||
'subnet_id': _uuid()}],
|
|
||||||
'mac_address': 'ca:fe:de:ad:be:ef',
|
|
||||||
'subnet': {'cidr': '10.0.%s.0/24' % i,
|
|
||||||
'gateway_ip': '10.0.%s.1' % i}}
|
|
||||||
router[l3_constants.INTERFACE_KEY].append(port)
|
|
||||||
|
|
||||||
def _del_all_floating_ips(self, router):
|
|
||||||
router[l3_constants.FLOATINGIP_KEY] = []
|
|
||||||
|
|
||||||
def _del_floating_ips(self, router, port_idx):
|
|
||||||
del router[l3_constants.FLOATINGIP_KEY][port_idx]
|
|
||||||
|
|
||||||
def _add_floating_ips(self, router, port_count=1):
|
|
||||||
self._del_all_floating_ips(router)
|
|
||||||
for i in range(port_count):
|
|
||||||
fip = {'id': _uuid(),
|
|
||||||
'port_id': router['gw_port']['id'],
|
|
||||||
'floating_ip_address': '172.24.4.%s' % (100 + i),
|
|
||||||
'fixed_ip_address': '10.0.0.%s' % (100 + i)}
|
|
||||||
router[l3_constants.FLOATINGIP_KEY].append(fip)
|
|
||||||
|
|
||||||
def _prepare_router_data(self, enable_snat=None):
|
|
||||||
router_id = _uuid()
|
|
||||||
ex_gw_port = {'id': _uuid(),
|
|
||||||
'network_id': _uuid(),
|
|
||||||
'fixed_ips': [{'ip_address': '172.24.4.2',
|
|
||||||
'subnet_id': _uuid()}],
|
|
||||||
'subnet': {'cidr': '172.24.4.0/24',
|
|
||||||
'gateway_ip': '172.24.4.1'},
|
|
||||||
'ip_cidr': '172.24.4.226/28'}
|
|
||||||
int_ports = []
|
|
||||||
|
|
||||||
router = {
|
|
||||||
'id': router_id,
|
|
||||||
l3_constants.INTERFACE_KEY: int_ports,
|
|
||||||
'routes': [],
|
|
||||||
'gw_port': ex_gw_port}
|
|
||||||
if enable_snat is not None:
|
|
||||||
router['enable_snat'] = enable_snat
|
|
||||||
|
|
||||||
ri = router_info.RouterInfo(router_id=router['id'], router=router,
|
|
||||||
**self.ri_kwargs)
|
|
||||||
return ri
|
|
||||||
|
|
||||||
def _add_firewall_rules(self, fw, rule_count=1):
|
|
||||||
rules = []
|
|
||||||
for i in range(rule_count):
|
|
||||||
rule = {'id': _uuid(),
|
|
||||||
'enabled': True,
|
|
||||||
'action': 'deny' if (i % 2 == 0) else 'allow',
|
|
||||||
'ip_version': 4,
|
|
||||||
'protocol': 'tcp',
|
|
||||||
'source_ip_address': '10.0.0.%s/24' % (100 + i),
|
|
||||||
'destination_port': '%s' % (100 + i)}
|
|
||||||
rules.append(rule)
|
|
||||||
fw['firewall_rule_list'] = rules
|
|
||||||
|
|
||||||
def _prepare_firewall_data(self):
|
|
||||||
fw = {'id': _uuid(),
|
|
||||||
'admin_state_up': True,
|
|
||||||
'firewall_rule_list': []}
|
|
||||||
return fw
|
|
||||||
|
|
||||||
def test_firewall_without_rule(self):
|
|
||||||
fwaas = self._create_fwaas()
|
|
||||||
fwaas.create_firewall = mock.Mock()
|
|
||||||
fwaas.delete_firewall = mock.Mock()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
self._add_internal_ports(ri.router, port_count=1)
|
|
||||||
self._add_floating_ips(ri.router, port_count=1)
|
|
||||||
rl = [ri]
|
|
||||||
fw = self._prepare_firewall_data()
|
|
||||||
fwaas.create_firewall(self.fake_agent_mode, rl, fw)
|
|
||||||
fwaas.create_firewall.assert_called_once_with(self.fake_agent_mode,
|
|
||||||
rl, fw)
|
|
||||||
fwaas.delete_firewall(self.fake_agent_mode, rl, fw)
|
|
||||||
|
|
||||||
def test_firewall_with_rules(self):
|
|
||||||
fwaas = self._create_fwaas()
|
|
||||||
fwaas.create_firewall = mock.Mock()
|
|
||||||
fwaas.delete_firewall = mock.Mock()
|
|
||||||
fw = self._prepare_firewall_data()
|
|
||||||
self._add_firewall_rules(fw, 2)
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
self._add_internal_ports(ri.router, port_count=1)
|
|
||||||
self._add_floating_ips(ri.router, port_count=1)
|
|
||||||
rl = [ri]
|
|
||||||
fwaas.create_firewall(self.fake_agent_mode, rl, fw)
|
|
||||||
fwaas.create_firewall.assert_called_once_with(self.fake_agent_mode,
|
|
||||||
rl, fw)
|
|
||||||
fwaas.delete_firewall(self.fake_agent_mode, rl, fw)
|
|
||||||
|
|
||||||
def test_firewall_add_remove_rules(self):
|
|
||||||
fwaas = self._create_fwaas()
|
|
||||||
fwaas.create_firewall = mock.Mock()
|
|
||||||
fwaas.delete_firewall = mock.Mock()
|
|
||||||
fw = self._prepare_firewall_data()
|
|
||||||
ri = self._prepare_router_data(enable_snat=True)
|
|
||||||
self._add_internal_ports(ri.router, port_count=1)
|
|
||||||
self._add_floating_ips(ri.router, port_count=1)
|
|
||||||
rl = [ri]
|
|
||||||
self._add_firewall_rules(fw, 2)
|
|
||||||
fwaas.create_firewall(self.fake_agent_mode, rl, fw)
|
|
||||||
# 3x number of policies
|
|
||||||
self._add_firewall_rules(fw, 1)
|
|
||||||
fwaas.create_firewall(self.fake_agent_mode, rl, fw)
|
|
||||||
fwaas.delete_firewall(self.fake_agent_mode, rl, fw)
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
prelude: >
|
||||||
|
- The vArmour Firewall Driver is being removed from the FwaaS repo,
|
||||||
|
as per decision to remove vendor drivers from the community repo.
|
||||||
|
upgrade:
|
||||||
|
- The vArmour Firewall Driver will not be available for use in the
|
||||||
|
Newton release.
|
|
@ -30,10 +30,9 @@ setup-hooks =
|
||||||
console_scripts =
|
console_scripts =
|
||||||
neutron-l3-agent = neutron_fwaas.cmd.eventlet.agents.fw:main
|
neutron-l3-agent = neutron_fwaas.cmd.eventlet.agents.fw:main
|
||||||
firewall_drivers =
|
firewall_drivers =
|
||||||
# These are for backwards compat with Juno firewall service provider configuration values
|
# These are for backwards compat with Juno firewall service provider
|
||||||
|
# configuration values
|
||||||
neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
||||||
neutron.services.firewall.drivers.varmour.varmour_fwaas.vArmourFwaasDriver = neutron_fwaas.services.firewall.drivers.varmour.varmour_fwaas:vArmourFwaasDriver
|
|
||||||
varmor = neutron_fwaas.services.firewall.drivers.varmour.varmour_fwaas:vArmourFwaasDriver
|
|
||||||
iptables = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
iptables = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver
|
||||||
neutron.db.alembic_migrations =
|
neutron.db.alembic_migrations =
|
||||||
neutron-fwaas = neutron_fwaas.db.migration:alembic_migrations
|
neutron-fwaas = neutron_fwaas.db.migration:alembic_migrations
|
||||||
|
|
Loading…
Reference in New Issue