neutron-fwaas/neutron_fwaas/services/firewall/drivers/vyatta/vyatta_fwaas.py

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)