fa546dd022
Change-Id: I41286e0b8f74c90b7078c3d3fb041b6586d95ab0 Closes-Bug: #1229324
206 lines
7.1 KiB
Python
Executable File
206 lines
7.1 KiB
Python
Executable File
# 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.
|
|
#
|
|
# @author: Gary Duan, gduan@varmour.com, vArmour Networks
|
|
|
|
from neutron.openstack.common import log as logging
|
|
from neutron.services.firewall.agents.varmour import varmour_api
|
|
from neutron.services.firewall.agents.varmour import varmour_utils as va_utils
|
|
from neutron.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.rest = varmour_api.vArmourRestAPI()
|
|
|
|
def create_firewall(self, apply_list, firewall):
|
|
LOG.debug(_('create_firewall (%s)'), firewall['id'])
|
|
|
|
return self.update_firewall(apply_list, firewall)
|
|
|
|
def update_firewall(self, 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, apply_list, firewall):
|
|
LOG.debug(_("delete_firewall (%s)"), firewall['id'])
|
|
|
|
return self.apply_default_policy(apply_list, firewall)
|
|
|
|
def apply_default_policy(self, 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.warn(_("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
|