192 lines
7.0 KiB
Python
192 lines
7.0 KiB
Python
# Copyright 2015 Brocade Communications System, 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 networking_brocade.vyatta.common import config as vyatta_config
|
|
from networking_brocade.vyatta.vrouter import client as vyatta_client
|
|
from neutron import context as neutron_context
|
|
from novaclient import client as nova_client
|
|
from oslo_log import log as logging
|
|
from six.moves.urllib import parse
|
|
|
|
from neutron_fwaas._i18n import _LW
|
|
from neutron_fwaas.services.firewall.agents.vyatta import vyatta_utils
|
|
from neutron_fwaas.services.firewall.drivers import fwaas_base
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
FW_NAME = 'firewall/name/{0}'
|
|
FW_DESCRIPTION = 'firewall/name/{0}/description/{1}'
|
|
|
|
FW_ESTABLISHED_ACCEPT = 'firewall/state-policy/established/action/accept'
|
|
FW_RELATED_ACCEPT = 'firewall/state-policy/related/action/accept'
|
|
|
|
FW_RULE_DESCRIPTION = 'firewall/name/{0}/rule/{1}/description/{2}'
|
|
FW_RULE_PROTOCOL = 'firewall/name/{0}/rule/{1}/protocol/{2}'
|
|
FW_RULE_SRC_PORT = 'firewall/name/{0}/rule/{1}/source/port/{2}'
|
|
FW_RULE_DEST_PORT = 'firewall/name/{0}/rule/{1}/destination/port/{2}'
|
|
FW_RULE_SRC_ADDR = 'firewall/name/{0}/rule/{1}/source/address/{2}'
|
|
FW_RULE_DEST_ADDR = 'firewall/name/{0}/rule/{1}/destination/address/{2}'
|
|
FW_RULE_ACTION = 'firewall/name/{0}/rule/{1}/action/{2}'
|
|
|
|
NOVACLIENT_VERSION = '2'
|
|
|
|
|
|
class VyattaFirewallDriver(fwaas_base.FwaasDriverBase):
|
|
def __init__(self):
|
|
LOG.debug("Vyatta vRouter Fwaas:: Initializing fwaas driver")
|
|
compute_client = nova_client.Client(
|
|
NOVACLIENT_VERSION,
|
|
vyatta_config.VROUTER.tenant_admin_name,
|
|
vyatta_config.VROUTER.tenant_admin_password,
|
|
auth_url=vyatta_config.CONF.nova_admin_auth_url,
|
|
service_type="compute",
|
|
tenant_id=vyatta_config.VROUTER.tenant_id)
|
|
self._vyatta_clients_pool = vyatta_client.ClientsPool(compute_client)
|
|
|
|
def create_firewall(self, agent_mode, apply_list, firewall):
|
|
LOG.debug('Vyatta vRouter Fwaas::Create_firewall (%s)', firewall)
|
|
|
|
return self.update_firewall(agent_mode, apply_list, firewall)
|
|
|
|
def update_firewall(self, agent_mode, apply_list, firewall):
|
|
LOG.debug('Vyatta vRouter Fwaas::Update_firewall (%s)', firewall)
|
|
|
|
if firewall['admin_state_up']:
|
|
return self._update_firewall(apply_list, firewall)
|
|
else:
|
|
return self.apply_default_policy(agent_mode, apply_list, firewall)
|
|
|
|
def delete_firewall(self, agent_mode, apply_list, firewall):
|
|
LOG.debug('Vyatta vRouter Fwaas::Delete_firewall (%s)', firewall)
|
|
|
|
return self.apply_default_policy(agent_mode, apply_list, firewall)
|
|
|
|
def apply_default_policy(self, agent_mode, apply_list, firewall):
|
|
LOG.debug('Vyatta vRouter Fwaas::apply_default_policy (%s)',
|
|
firewall)
|
|
|
|
for ri in apply_list:
|
|
self._delete_firewall(ri, firewall)
|
|
|
|
return True
|
|
|
|
def _update_firewall(self, apply_list, firewall):
|
|
LOG.debug("Updating firewall (%s)", firewall['id'])
|
|
|
|
for ri in apply_list:
|
|
self._delete_firewall(ri, firewall)
|
|
self._setup_firewall(ri, firewall)
|
|
|
|
return True
|
|
|
|
def _setup_firewall(self, ri, fw):
|
|
client = self._get_vyatta_client(ri.router)
|
|
|
|
fw_cmd_list = []
|
|
|
|
# Create firewall
|
|
fw_name = vyatta_utils.get_firewall_name(ri, fw)
|
|
fw_cmd_list.append(
|
|
vyatta_client.SetCmd(
|
|
FW_NAME.format(parse.quote_plus(fw_name))))
|
|
|
|
if fw.get('description'):
|
|
fw_cmd_list.append(vyatta_client.SetCmd(
|
|
FW_DESCRIPTION.format(
|
|
parse.quote_plus(fw_name),
|
|
parse.quote_plus(fw['description']))))
|
|
|
|
# Set firewall state policy
|
|
fw_cmd_list.append(vyatta_client.SetCmd(FW_ESTABLISHED_ACCEPT))
|
|
fw_cmd_list.append(vyatta_client.SetCmd(FW_RELATED_ACCEPT))
|
|
|
|
# Create firewall rules
|
|
rule_num = 0
|
|
for rule in fw['firewall_rule_list']:
|
|
if not rule['enabled']:
|
|
continue
|
|
if rule['ip_version'] == 4:
|
|
rule_num += 1
|
|
fw_cmd_list += self._set_firewall_rule(fw_name, rule_num, rule)
|
|
else:
|
|
LOG.warning(_LW("IPv6 rules are not supported."))
|
|
|
|
# Configure router zones
|
|
zone_cmd_list = vyatta_utils.get_zone_cmds(client, ri, fw_name)
|
|
client.exec_cmd_batch(fw_cmd_list + zone_cmd_list)
|
|
|
|
def _delete_firewall(self, ri, fw):
|
|
client = self._get_vyatta_client(ri.router)
|
|
|
|
cmd_list = []
|
|
|
|
# Delete zones
|
|
cmd_list.append(vyatta_client.DeleteCmd("zone-policy"))
|
|
|
|
# Delete firewall
|
|
fw_name = vyatta_utils.get_firewall_name(ri, fw)
|
|
cmd_list.append(vyatta_client.DeleteCmd(
|
|
FW_NAME.format(parse.quote_plus(fw_name))))
|
|
|
|
# Delete firewall state policy
|
|
cmd_list.append(vyatta_client.DeleteCmd("firewall/state-policy"))
|
|
|
|
client.exec_cmd_batch(cmd_list)
|
|
|
|
def _set_firewall_rule(self, fw_name, rule_num, rule):
|
|
cmd_list = []
|
|
|
|
if 'description' in rule and len(rule['description']) > 0:
|
|
cmd_list.append(vyatta_client.SetCmd(
|
|
FW_RULE_DESCRIPTION.format(
|
|
parse.quote_plus(fw_name), rule_num,
|
|
parse.quote_plus(rule['description']))))
|
|
|
|
rules = [
|
|
('protocol', FW_RULE_PROTOCOL),
|
|
('source_port', FW_RULE_SRC_PORT),
|
|
('destination_port', FW_RULE_DEST_PORT),
|
|
('source_ip_address', FW_RULE_SRC_ADDR),
|
|
('destination_ip_address', FW_RULE_DEST_ADDR),
|
|
]
|
|
|
|
for key, url in rules:
|
|
field = rule.get(key)
|
|
if field is None:
|
|
continue
|
|
|
|
# For safety and extensibility we need to use quote_plus
|
|
# for all data retrieved from external sources.
|
|
cmd_list.append(vyatta_client.SetCmd(
|
|
url.format(
|
|
parse.quote_plus(fw_name), rule_num,
|
|
parse.quote_plus(field))))
|
|
|
|
if 'action' in rule:
|
|
if rule['action'] == 'allow':
|
|
action = 'accept'
|
|
else:
|
|
action = 'drop'
|
|
cmd_list.append(vyatta_client.SetCmd(
|
|
FW_RULE_ACTION.format(
|
|
parse.quote_plus(fw_name), rule_num,
|
|
action)))
|
|
return cmd_list
|
|
|
|
def _get_vyatta_client(self, router):
|
|
ctx = neutron_context.Context(None, router['tenant_id'])
|
|
return self._vyatta_clients_pool.get_by_db_lookup(router['id'], ctx)
|