Esempio n. 1
0
    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(
                _LE("Firewall Driver Error for create_firewall "
                    "for firewall: %(fwid)s"), {'fwid': 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(
                _LE("FWaaS RPC failure in create_firewall "
                    "for firewall: %(fwid)s"), {'fwid': firewall['id']})
            self.services_sync_needed = True
Esempio n. 2
0
    def get(self, path, etag=None, raw=False):
        json_result = None
        etag_out = None
        headers = {'accept': 'application/json',
                   'content-type': 'application/json'}
        if etag:
            headers['ETag'] = etag

        try:
            result = self.session_op("get", path, raw, headers=headers)

            if 'etag' in result.headers:
                etag_out = result.headers['etag']

            json_result = result.json()

            if result.status_code == "404":
                LOG.error(_LE("%(msg)s %(detail)s"),
                          {'msg': json_result["message"],
                           'detail': json_result["details"]})

        except Exception:
            LOG.error(_LE("exception when GET operation"))
            raise

        r = [json_result]
        if etag_out:
            r.append(etag_out)

        return [json_result]
Esempio n. 3
0
    def get(self, path, etag=None, raw=False):
        json_result = None
        etag_out = None
        headers = {
            'accept': 'application/json',
            'content-type': 'application/json'
        }
        if etag:
            headers['ETag'] = etag

        try:
            result = self.session_op("get", path, raw, headers=headers)

            if 'etag' in result.headers:
                etag_out = result.headers['etag']

            json_result = result.json()

            if result.status_code == "404":
                LOG.error(
                    _LE("%(msg)s %(detail)s"), {
                        'msg': json_result["message"],
                        'detail': json_result["details"]
                    })

        except Exception:
            LOG.error(_LE("exception when GET operation"))
            raise

        r = [json_result]
        if etag_out:
            r.append(etag_out)

        return [json_result]
Esempio n. 4
0
    def _validate_firewall_rule_data(self, firewall):
        if 'firewall_rule_list' not in firewall:
            LOG.error(_LE("no rule list"))
            return False
        for rule in firewall['firewall_rule_list']:
            if 'name' not in rule:
                LOG.error(_LE("CsrAcl: no rule name"))
                return False
            ip_version = rule.get('ip_version')
            if ip_version != 4:
                LOG.error(
                    _LE("invalid ip version %(ip_version)s in "
                        "rule %(rule)s"), {
                            'ip_version': ip_version,
                            'rule': rule['name']
                        })
                return False
            if 'protocol' not in rule:
                LOG.error(_LE("no protocol in rule [%s]"), rule['name'])
                return False
            if rule.get('action', '').lower() not in ('allow', 'deny'):
                LOG.error(_LE("invalid action in rule [%s]"), rule['name'])
                return False

        return True
    def delete_firewall_group(self, context, firewall_group, host):
        """Handles RPC from plugin to delete a firewall group.
        """

        ports_for_fwg = self._get_firewall_group_ports(context,
                                                       firewall_group,
                                                       to_delete=True)

        if not ports_for_fwg:
            return

        fw_ports = [p for ri_ports in ports_for_fwg for p in ri_ports[1]]
        LOG.debug("Delete firewall group %(fwg_id)s on ports: %(ports)s" % {
            'fwg_id': firewall_group['id'],
            'ports': ', '.join(fw_ports)
        })

        # Set the firewall group's status to return to plugin; status may be
        # overwritten if call to driver fails.
        if firewall_group['admin_state_up']:
            status = n_const.ACTIVE
        else:
            status = n_const.DOWN
        try:
            self.fwaas_driver.delete_firewall_group(self.conf.agent_mode,
                                                    ports_for_fwg,
                                                    firewall_group)
        # Call the driver.
        except fw_ext.FirewallInternalDriverError:
            LOG.exception(
                _LE("FWaaS driver error in delete_firewall_group "
                    "for firewall group: %(fwg_id)s"),
                {'fwg_id': firewall_group['id']})
            status = n_const.ERROR

        # Notify plugin of deletion or return firewall group's status to
        # plugin, as appopriate.
        try:
            if status in [n_const.ACTIVE, n_const.DOWN]:
                self.fwplugin_rpc.firewall_group_deleted(
                    context, firewall_group['id'])
            else:
                self.fwplugin_rpc.set_firewall_group_status(
                    context, firewall_group['id'], status)
        except Exception:
            LOG.exception(
                _LE("FWaaS RPC failure in delete_firewall_group "
                    "for firewall group: %(fwg_id)s"),
                {'fwg_id': firewall_group['id']})
            self.services_sync_needed = True
Esempio n. 6
0
    def _invoke_driver_for_sync_from_plugin(self, ctx, port, firewall_group):
        """Calls the FWaaS driver's delete_firewall_group method if firewall
           group has status of PENDING_DELETE; calls driver's
           update_firewall_group method for all other statuses. Both of these
           methods are idempotent.
        """
        port_list = self._get_in_ns_ports([port['id']])
        if firewall_group['status'] == nl_constants.PENDING_DELETE:
            try:
                self.fwaas_driver.delete_firewall_group(
                    self.conf.agent_mode, port_list, firewall_group)
                self.fwplugin_rpc.firewall_group_deleted(
                    ctx, firewall_group['id'])
            except fw_ext.FirewallInternalDriverError:
                msg = _LE("FWaaS driver error on %(status)s "
                          "for firewall group: %(fwg_id)s")
                LOG.exception(
                    msg, {
                        'status': firewall_group['status'],
                        'fwg_id': firewall_group['id']
                    })
                self.fwplugin_rpc.set_firewall_group_status(
                    ctx, firewall_group['id'], nl_constants.ERROR)
        else:  # PENDING_UPDATE, PENDING_CREATE, ...

            # Prepare firewall group status to return to plugin; may be
            # overwritten if call to driver fails.
            if firewall_group['admin_state_up']:
                status = nl_constants.ACTIVE
            else:
                status = nl_constants.DOWN

            # Call the driver.
            try:
                self.fwaas_driver.update_firewall_group(
                    self.conf.agent_mode, port_list, firewall_group)
            except fw_ext.FirewallInternalDriverError:
                msg = _LE("FWaaS driver error on %(status)s for firewall "
                          "group: "
                          "%(fwg_id)s")
                LOG.exception(
                    msg, {
                        'status': firewall_group['status'],
                        'fwg_id': firewall_group['id']
                    })
                status = nl_constants.ERROR

            # Notify the plugin of firewall group's status.
            self.fwplugin_rpc.set_firewall_group_status(
                ctx, firewall_group['id'], status)
    def process_services_sync(self, ctx):
        """Syncs with plugin and applies the sync data.
        """

        if not self.services_sync_needed or not self.fwaas_enabled:
            return

        try:
            # Fetch from the plugin the list of projects with firewall groups.
            project_ids = \
                    self.fwplugin_rpc.get_projects_with_firewall_groups(ctx)
            LOG.debug("Projects with firewall groups: %s",
                      ', '.join(project_ids))
            for project_id in project_ids:
                ctx = context.Context('', project_id)
                fwg_list = \
                    self.fwplugin_rpc.get_firewall_groups_for_project(ctx)
                for firewall_group in fwg_list:
                    if firewall_group['status'] == n_const.PENDING_DELETE:
                        self.delete_firewall_group(ctx, firewall_group,
                                                   self.host)
                    # No need to apply sync data for ACTIVE firewall group.
                    elif firewall_group['status'] != n_const.ACTIVE:
                        self.update_firewall_group(ctx, firewall_group,
                                                   self.host)
            self.services_sync_needed = False
        except Exception:
            LOG.exception(_LE("Failed FWaaS process services sync."))
            self.services_sync_needed = True
    def _process_event_q(self):
        while True:
            try:
                event_data = self.event_q.dequeue(CSR_FW_EVENT_Q_NAME)
                if not event_data:
                    return
            except ValueError:
                LOG.debug("_process_event_q: no queue yet")
                return

            LOG.debug("_process_event_q: event_data %s", event_data)
            event = event_data['event']
            context = event_data['context']
            firewall = event_data['firewall']
            if event == CSR_FW_EVENT_CREATE:
                self._invoke_firewall_driver(context, firewall,
                                             'create_firewall')
            elif event == CSR_FW_EVENT_UPDATE:
                self._invoke_firewall_driver(context, firewall,
                                             'update_firewall')
            elif event == CSR_FW_EVENT_DELETE:
                self._invoke_firewall_driver(context, firewall,
                                             'delete_firewall')
            else:
                LOG.error(_LE("invalid event %s"), event)
Esempio n. 9
0
    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(
                _LE("Failed to apply default policy on firewall: %s"), fwid)
            raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
Esempio n. 10
0
    def _post_acl(self, csr, acl_data):
        response = csr.post_request(ACL_API, acl_data)
        if csr.status == requests.codes.CREATED:
            return response[response.rfind('/') + 1:]

        LOG.error(_LE("status %s"), csr.status)
        return ''
    def _process_event_q(self):
        while True:
            try:
                event_data = self.event_q.dequeue(CSR_FW_EVENT_Q_NAME)
                if not event_data:
                    return
            except ValueError:
                LOG.debug("_process_event_q: no queue yet")
                return

            LOG.debug("_process_event_q: event_data %s", event_data)
            event = event_data['event']
            context = event_data['context']
            firewall = event_data['firewall']
            if event == CSR_FW_EVENT_CREATE:
                self._invoke_firewall_driver(
                    context, firewall, 'create_firewall')
            elif event == CSR_FW_EVENT_UPDATE:
                self._invoke_firewall_driver(
                    context, firewall, 'update_firewall')
            elif event == CSR_FW_EVENT_DELETE:
                self._invoke_firewall_driver(
                    context, firewall, 'delete_firewall')
            else:
                LOG.error(_LE("invalid event %s"), event)
Esempio n. 12
0
 def _post_acl_to_interfaces(self, firewall, csr, acl_id, status_data):
     acl_interface_url = ACL_API_ACLID_IF % acl_id
     for firewall_interface in firewall['vendor_ext']['if_list']:
         if_name = self._get_interface_name_from_hosting_port(
             firewall_interface['port'])
         acl_interface_req = {
             'if-id': if_name,
             'direction': firewall_interface['direction']
         }
         LOG.debug("acl_interface_url %s", acl_interface_url)
         csr.post_request(acl_interface_url, acl_interface_req)
         if csr.status == requests.codes.CREATED:
             status_data['if_list'].append({
                 'port_id':
                 firewall_interface['port']['id'],
                 'status':
                 'OK'
             })
         else:
             LOG.error(_LE("status %s"), csr.status)
             status_data['if_list'].append({
                 'port_id':
                 firewall_interface['port']['id'],
                 'status':
                 'ERROR'
             })
Esempio n. 13
0
    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'] == n_const.PENDING_DELETE:
                        self.delete_firewall(ctx, fw, self.host)
                    # no need to apply sync data for ACTIVE fw
                    elif fw['status'] != n_const.ACTIVE:
                        self.update_firewall(ctx, fw, self.host)
            self.services_sync_needed = False
        except Exception:
            LOG.exception(_LE("Failed fwaas process services sync"))
            self.services_sync_needed = True
Esempio n. 14
0
 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(_LE("Failed fwaas process services sync"))
         self.services_sync_needed = True
Esempio n. 15
0
    def _post_acl(self, csr, acl_data):
        response = csr.post_request(ACL_API, acl_data)
        if csr.status == requests.codes.CREATED:
            return response[response.rfind('/') + 1:]

        LOG.error(_LE("status %s"), csr.status)
        return ''
Esempio n. 16
0
    def _get_acl_interface(self, csr, acl_id):
        my_api = ACL_API_ACLID_IF % acl_id
        response = csr.get_request(my_api)
        if csr.status == requests.codes.OK:
            return response['items']

        LOG.error(_LE("status %s"), csr.status)
        return ''
Esempio n. 17
0
    def _put_acl(self, csr, acl_id, acl_data):
        my_api = ACL_API_ACLID % acl_id
        csr.put_request(my_api, acl_data)
        if csr.status == requests.codes.NO_CONTENT:
            return True

        LOG.error(_LE("status %s"), csr.status)
        return False
Esempio n. 18
0
    def _delete_acl(self, csr, acl_id):
        my_api = ACL_API_ACLID % acl_id
        csr.delete_request(my_api)
        if csr.status == requests.codes.NO_CONTENT:
            return True

        LOG.error(_LE("status %s"), csr.status)
        return False
Esempio n. 19
0
 def _delete_acl_on_interface(self, csr, acl_id,
                              csr_firewall_interface_list):
     for interface in csr_firewall_interface_list:
         my_api = ACL_API_ACLID_IFID_DIR % (
             acl_id, interface['if-id'], interface['direction'])
         csr.delete_request(my_api)
         if csr.status != requests.codes.NO_CONTENT:
             LOG.error(_LE("status %s"), csr.status)
Esempio n. 20
0
    def _put_acl(self, csr, acl_id, acl_data):
        my_api = ACL_API_ACLID % acl_id
        csr.put_request(my_api, acl_data)
        if csr.status == requests.codes.NO_CONTENT:
            return True

        LOG.error(_LE("status %s"), csr.status)
        return False
Esempio n. 21
0
    def _delete_acl(self, csr, acl_id):
        my_api = ACL_API_ACLID % acl_id
        csr.delete_request(my_api)
        if csr.status == requests.codes.NO_CONTENT:
            return True

        LOG.error(_LE("status %s"), csr.status)
        return False
Esempio n. 22
0
    def _get_acl_interface(self, csr, acl_id):
        my_api = ACL_API_ACLID_IF % acl_id
        response = csr.get_request(my_api)
        if csr.status == requests.codes.OK:
            return response['items']

        LOG.error(_LE("status %s"), csr.status)
        return ''
Esempio n. 23
0
 def _delete_acl_on_interface(self, csr, acl_id,
                              csr_firewall_interface_list):
     for interface in csr_firewall_interface_list:
         my_api = ACL_API_ACLID_IFID_DIR % (acl_id, interface['if-id'],
                                            interface['direction'])
         csr.delete_request(my_api)
         if csr.status != requests.codes.NO_CONTENT:
             LOG.error(_LE("status %s"), csr.status)
    def create_firewall_group(self, context, firewall_group, host):
        """Handles RPC from plugin to create a firewall group.
        """

        # Get the in-namespace ports to which to add the firewall group.
        ports_for_fwg = self._get_firewall_group_ports(context, firewall_group)
        if not ports_for_fwg:
            return

        LOG.debug(
            "Create firewall group %(fwg_id)s on ports: %(ports)s" % {
                'fwg_id':
                firewall_group['id'],
                'ports':
                ', '.join(
                    [p for ri_ports in ports_for_fwg for p in ri_ports[1]])
            })

        # Set firewall group status; will be overwritten if call to driver
        # fails.
        if firewall_group['admin_state_up']:
            status = n_const.ACTIVE
        else:
            status = n_const.DOWN

        # Call the driver.
        try:
            self.fwaas_driver.create_firewall_group(self.conf.agent_mode,
                                                    ports_for_fwg,
                                                    firewall_group)
        except fw_ext.FirewallInternalDriverError:
            msg = _LE("FWaaS driver error in create_firewall_group "
                      "for firewall group: %(fwg_id)s")
            LOG.exception(msg, {'fwg_id': firewall_group['id']})
            status = n_const.ERROR

        # Send firewall group's status to plugin.
        try:
            self.fwplugin_rpc.set_firewall_group_status(
                context, firewall_group['id'], status)
        except Exception:
            msg = _LE("FWaaS RPC failure in create_firewall_group "
                      "for firewall group: %(fwg_id)s")
            LOG.exception(msg, {'fwg_id': firewall_group['id']})
            self.services_sync_needed = True
Esempio n. 25
0
 def _remove_conntrack_by_cmd(self, cmd):
     if cmd:
         try:
             linux_utils.execute(cmd, run_as_root=True,
                          check_exit_code=True,
                          extra_ok_codes=[1])
         except RuntimeError:
             LOG.exception(
                     _LE("Failed execute conntrack command %s"), str(cmd))
Esempio n. 26
0
    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 = n_const.ACTIVE
                else:
                    status = n_const.DOWN
            except fw_ext.FirewallInternalDriverError:
                LOG.error(_LE("Firewall Driver Error for delete_firewall "
                              "for firewall: %(fwid)s"),
                    {'fwid': firewall['id']})
                status = n_const.ERROR

            try:
                # send status back to plugin
                if status in [n_const.ACTIVE, n_const.DOWN]:
                    self.fwplugin_rpc.firewall_deleted(context, firewall['id'])
                else:
                    self.fwplugin_rpc.set_firewall_status(
                        context,
                        firewall['id'],
                        status)
            except Exception:
                LOG.exception(
                    _LE("FWaaS RPC failure in delete_firewall "
                        "for firewall: %(fwid)s"),
                    {'fwid': firewall['id']})
                self.services_sync_needed = True
    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 = n_const.ACTIVE
                else:
                    status = n_const.DOWN
            except fw_ext.FirewallInternalDriverError:
                LOG.error(_LE("Firewall Driver Error for delete_firewall "
                              "for firewall: %(fwid)s"),
                    {'fwid': firewall['id']})
                status = n_const.ERROR

            try:
                # send status back to plugin
                if status in [n_const.ACTIVE, n_const.DOWN]:
                    self.fwplugin_rpc.firewall_deleted(context, firewall['id'])
                else:
                    self.fwplugin_rpc.set_firewall_status(
                        context,
                        firewall['id'],
                        status)
            except Exception:
                LOG.exception(
                    _LE("FWaaS RPC failure in delete_firewall "
                        "for firewall: %(fwid)s"),
                    {'fwid': firewall['id']})
                self.services_sync_needed = True
    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'] == n_const.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(_LE("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'],
                    n_const.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 = n_const.ACTIVE
                else:
                    status = n_const.DOWN
            except fw_ext.FirewallInternalDriverError:
                LOG.error(_LE("Firewall Driver Error on fw state %(fwmsg)s "
                              "for fw: %(fwid)s"),
                          {'fwmsg': fw['status'], 'fwid': fw['id']})
                status = n_const.ERROR

            self.fwplugin_rpc.set_firewall_status(
                ctx,
                fw['id'],
                status)
Esempio n. 29
0
    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'] == n_const.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(_LE("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'],
                    n_const.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 = n_const.ACTIVE
                else:
                    status = n_const.DOWN
            except fw_ext.FirewallInternalDriverError:
                LOG.error(_LE("Firewall Driver Error on fw state %(fwmsg)s "
                              "for fw: %(fwid)s"),
                          {'fwmsg': fw['status'], 'fwid': fw['id']})
                status = n_const.ERROR

            self.fwplugin_rpc.set_firewall_status(
                ctx,
                fw['id'],
                status)
Esempio n. 30
0
    def get_initial_contact_data(self):
        """Get the element's configuration data used to contact to SMC server.

        Contact data is a configuration string including the SMC server's IP,
        interfaces defined and special one-time password.
        eg. first create the L3 element on behalf of sg-engine in SMC server
        and generate the contact data, then boot the sg-engine with it and
        engine will init properly and connect to SMC server finally.
        """

        data = None
        result = self.get_element("%s/%s/node" %
                                  (self.element_type, self.element_id))
        LOG.debug("resule = %s", result)

        node_ref = result[0]['result'][0]['href'].replace(
            self.smc_api_connection.host_api_url + "/elements/", "")

        LOG.debug("Node ref is %s", node_ref)

        extra_options = []
        if self.keyboard:
            extra_options.append("keyboard=%s" % (self.keyboard))
        if self.timezone:
            extra_options.append("time_zone=%s" % (self.timezone))

        if extra_options:
            extra_options = "&" + extra_options
        else:
            extra_options = ""

        result = self.smc_api_connection.post_element(
            "%s/initial_contact?enable_ssh=true%s" % (node_ref, extra_options),
            "")
        if result.is_text():
            d1 = str(result).split("\n")
            idx = 0
            for l in d1:
                if l.find("ssh/enabled") != -1:
                    l = l.replace("false", "true")
                    d1[idx] = l
                idx += 1
            result.result = "\n".join(d1)
            data = result

        result = self.smc_api_connection.post_element(
            "%s/bind_license" % (node_ref), "")

        if result.code != 200:
            LOG.error(
                _LE("Could not bind license. "
                    "Maybe SMC license pool is empty. "
                    "SMC API details: %s"), result)
        return data
Esempio n. 31
0
 def _get_routers_in_project(self, project_id):
     if self.agent_api is None:
         LOG.exception(_LE("FWaaS RPC call failed; L3 agent_api failure"))
     router_info = self.agent_api._router_info
     if project_id:
         return [
             ri for ri in router_info.values()
             if ri.router['tenant_id'] == project_id
         ]
     else:
         return []
Esempio n. 32
0
    def get_initial_contact_data(self):
        """Get the element's configuration data used to contact to SMC server.

        Contact data is a configuration string including the SMC server's IP,
        interfaces defined and special one-time password.
        eg. first create the L3 element on behalf of sg-engine in SMC server
        and generate the contact data, then boot the sg-engine with it and
        engine will init properly and connect to SMC server finally.
        """

        data = None
        result = self.get_element("%s/%s/node" %
                                  (self.element_type, self.element_id))
        LOG.debug("resule = %s", result)

        node_ref = result[0]['result'][0]['href'].replace(
            self.smc_api_connection.host_api_url + "/elements/", "")

        LOG.debug("Node ref is %s", node_ref)

        extra_options = []
        if self.keyboard:
            extra_options.append("keyboard=%s" % (self.keyboard))
        if self.timezone:
            extra_options.append("time_zone=%s" % (self.timezone))

        if extra_options:
            extra_options = "&" + extra_options
        else:
            extra_options = ""

        result = self.smc_api_connection.post_element(
            "%s/initial_contact?enable_ssh=true%s" %
            (node_ref, extra_options), "")
        if result.is_text():
            d1 = str(result).split("\n")
            idx = 0
            for l in d1:
                if l.find("ssh/enabled") != -1:
                    l = l.replace("false", "true")
                    d1[idx] = l
                idx += 1
            result.result = "\n".join(d1)
            data = result

        result = self.smc_api_connection.post_element(
            "%s/bind_license" % (node_ref), "")

        if result.code != 200:
            LOG.error(_LE("Could not bind license. "
                          "Maybe SMC license pool is empty. "
                          "SMC API details: %s"), result)
        return data
Esempio n. 33
0
    def delete(self, path, raw=False):
        del_result = SMCAPIResult("text")

        try:
            result = self.session_op("delete", path, raw)
            self.check_ret("DELETE", path, result, del_result)

        except Exception:
            LOG.error(_LE("exception when DELETE operation"))
            raise

        return del_result
Esempio n. 34
0
 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)
         else:
             self.apply_default_policy(agent_mode, apply_list, firewall)
     except (LookupError, RuntimeError):
         # catch known library exceptions and raise Fwaas generic exception
         LOG.exception(_LE("Failed to create firewall: %s"), firewall['id'])
         raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
Esempio n. 35
0
    def delete(self, path, raw=False):
        del_result = SMCAPIResult("text")

        try:
            result = self.session_op("delete", path, raw)
            self.check_ret("DELETE", path, result, del_result)

        except Exception:
            LOG.error(_LE("exception when DELETE operation"))
            raise

        return del_result
    def _load_firewall_extension_driver(namespace, driver):
        """Loads driver using alias or class name
        :param namespace: namespace where alias is defined
        :param driver: driver alias or class name
        :returns driver that is loaded
        :raises ImportError if fails to load driver
        """

        try:
            return utils.load_class_by_alias_or_classname(namespace, driver)
        except ImportError:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("Driver '%s' not found."), driver)
Esempio n. 37
0
    def session_op(self, attr, path, raw=False, data=None, headers=None):
        op = getattr(self.session, attr)

        if raw:
            result = op(path, headers=headers, data=data)
        else:
            result = op("%s/%s" %
                        (self.host_api_url, path), headers=headers, data=data)

        if result.status_code == "404":
            LOG.error(_LE("SMC Error 404 %s"), result.reason)

        return result
    def add_router(self, context, new_router):
        """Handles agent restart and router add. Fetches firewall groups from
        plugin and updates driver.
        """
        if not self.fwaas_enabled:
            return

        try:
            self._process_router_update(new_router)
        except Exception:
            LOG.exception(_LE("FWaaS router add RPC info call failed for %s"),
                          new_router['id'])
            self.services_sync_needed = True
Esempio n. 39
0
    def _validate_firewall_rule_data(self, firewall):
        if 'firewall_rule_list' not in firewall:
            LOG.error(_LE("no rule list"))
            return False
        for rule in firewall['firewall_rule_list']:
            if 'name' not in rule:
                LOG.error(_LE("CsrAcl: no rule name"))
                return False
            ip_version = rule.get('ip_version')
            if ip_version != 4:
                LOG.error(_LE("invalid ip version %(ip_version)s in "
                    "rule %(rule)s"),
                    {'ip_version': ip_version, 'rule': rule['name']})
                return False
            if 'protocol' not in rule:
                LOG.error(_LE("no protocol in rule [%s]"), rule['name'])
                return False
            if rule.get('action', '').lower() not in ('allow', 'deny'):
                LOG.error(_LE("invalid action in rule [%s]"), rule['name'])
                return False

        return True
Esempio n. 40
0
    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 = n_const.ACTIVE
            else:
                status = n_const.DOWN
        except fw_ext.FirewallInternalDriverError:
            LOG.error(_LE("Firewall Driver Error for create_firewall "
                          "for firewall: %(fwid)s"),
                {'fwid': firewall['id']})
            status = n_const.ERROR

        try:
            # send status back to plugin
            self.fwplugin_rpc.set_firewall_status(
                context,
                firewall['id'],
                status)
        except Exception:
            LOG.exception(
                _LE("FWaaS RPC failure in create_firewall "
                    "for firewall: %(fwid)s"),
                {'fwid': firewall['id']})
            self.services_sync_needed = True
Esempio n. 41
0
    def session_op(self, attr, path, raw=False, data=None, headers=None):
        op = getattr(self.session, attr)

        if raw:
            result = op(path, headers=headers, data=data)
        else:
            result = op("%s/%s" % (self.host_api_url, path),
                        headers=headers,
                        data=data)

        if result.status_code == "404":
            LOG.error(_LE("SMC Error 404 %s"), result.reason)

        return result
Esempio n. 42
0
    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'))
Esempio n. 43
0
 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(_LE("Failed to create firewall: %s"), firewall['id'])
         raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
Esempio n. 44
0
    def _validate_firewall_data(self, firewall):
        data = ('admin_state_up', 'vendor_ext')
        is_valid = all(x in firewall for x in data)
        if not is_valid:
            LOG.error(_LE("missing data in firewall"))
            return is_valid

        data = ('host_mngt_ip', 'host_usr_nm', 'host_usr_pw', 'if_list')
        is_valid = all(x in firewall['vendor_ext'] for x in data)
        if not is_valid:
            LOG.error(_LE("missing data in firewall vendor_ext"))
            return is_valid

        for firewall_interface in firewall['vendor_ext']['if_list']:
            if firewall_interface.get('direction', '') not in (
                'inside', 'outside', 'both'):
                LOG.error(_LE("invalid direction"))
                return False
            if 'port' not in firewall_interface:
                LOG.error(_LE("no port"))
                return False
            port = firewall_interface['port']
            if 'id' not in port:
                LOG.error(_LE("no port id"))
                return False
            if 'hosting_info' not in port:
                LOG.error(_LE("no hosting_info"))
                return False
            if 'segmentation_id' not in port['hosting_info']:
                LOG.error(_LE("no segmentation_id"))
                return False
            if 'hosting_port_name' not in port['hosting_info']:
                LOG.error(_LE("hosting_port_name"))
                return False
            interface_type = port['hosting_info'][
                'hosting_port_name'].split(':')[0] + ':'
            if interface_type not in ('t1_p:', 't2_p:'):
                LOG.error(_LE("invalide interface type %s"), interface_type)
                return False

        return True
    def update_router(self, context, updated_router):
        """Handles agent restart and router add. Fetches firewall groups from
        plugin and updates driver.
        """
        if not self.fwaas_enabled:
            return

        try:
            self._process_router_update(updated_router)
        except Exception:
            #TODO(njohnston): This repr should be replaced.
            LOG.exception(
                _LE("FWaaS router update RPC info call failed for %s"),
                repr(updated_router))
            self.services_sync_needed = True
Esempio n. 46
0
    def _validate_firewall_data(self, firewall):
        data = ('admin_state_up', 'vendor_ext')
        is_valid = all(x in firewall for x in data)
        if not is_valid:
            LOG.error(_LE("missing data in firewall"))
            return is_valid

        data = ('host_mngt_ip', 'host_usr_nm', 'host_usr_pw', 'if_list')
        is_valid = all(x in firewall['vendor_ext'] for x in data)
        if not is_valid:
            LOG.error(_LE("missing data in firewall vendor_ext"))
            return is_valid

        for firewall_interface in firewall['vendor_ext']['if_list']:
            if firewall_interface.get('direction',
                                      '') not in ('inside', 'outside', 'both'):
                LOG.error(_LE("invalid direction"))
                return False
            if 'port' not in firewall_interface:
                LOG.error(_LE("no port"))
                return False
            port = firewall_interface['port']
            if 'id' not in port:
                LOG.error(_LE("no port id"))
                return False
            if 'hosting_info' not in port:
                LOG.error(_LE("no hosting_info"))
                return False
            if 'segmentation_id' not in port['hosting_info']:
                LOG.error(_LE("no segmentation_id"))
                return False
            if 'hosting_port_name' not in port['hosting_info']:
                LOG.error(_LE("hosting_port_name"))
                return False
            interface_type = port['hosting_info']['hosting_port_name'].split(
                ':')[0] + ':'
            if interface_type not in ('t1_p:', 't2_p:'):
                LOG.error(_LE("invalide interface type %s"), interface_type)
                return False

        return True
Esempio n. 47
0
    def post(self, path, json_element, raw=False):
        headers = {'accept': '*/*',
                   'content-type': 'application/json'}
        post_result = SMCAPIResult("text")

        try:
            result = self.session_op(
                "post", path, raw, headers=headers, data=json_element)
            self.check_ret("POST", path, result, post_result)
            post_result.headers = result.headers
        except Exception:
            LOG.error(_LE("exception when POST operation"))
            raise

        return post_result
Esempio n. 48
0
    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(_LE("FWaaS RPC info call failed for '%s'."),
                          new_router['id'])
            self.services_sync_needed = True
Esempio n. 49
0
    def login(self):
        self.session = requests.session()

        post_addr = ("%s/login?authenticationkey=%s&beta=true" %
                     (self.host_api_url, self.auth_key))
        res = self.session.post(post_addr)

        if res.status_code == 200:
            return True

        LOG.error(_LE("connect to %(host)s failed"
                      " (%(msg)s/ code %(code)s)"),
                  {'host': post_addr,
                   'msg': res.reason,
                   'code': res.status_code})

        return False
Esempio n. 50
0
 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()
     except (LookupError, RuntimeError):
         # catch known library exceptions and raise Fwaas generic exception
         LOG.exception(_LE("Failed to delete firewall: %s"), fwid)
         raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
Esempio n. 51
0
    def _delete_firewall(self, firewall):
        """Delete ACL.

        :param firewall: firewall dictionary
        :return: True if OK
        :return: False if there is an error
        """

        if not self._validate_firewall_data(firewall):
            return False

        acl_id = firewall['vendor_ext'].get('acl_id')
        if not acl_id:
            LOG.error(_LE("firewall (%s) has no acl_id"), firewall['id'])
            return False

        csr = self._get_csr_host(firewall['vendor_ext'])
        return self._delete_acl(csr, acl_id)
    def process_service(self, device_ids=None, removed_devices_info=None):
        try:
            if self.fullsync:
                self.fullsync = False
                self._process_fullsync()

            else:
                if device_ids:
                    self._process_devices(device_ids)

                if removed_devices_info:
                    LOG.debug("process_service: removed_devices_info %s",
                              removed_devices_info)
                    # do nothing for now
                else:
                    self._process_event_q()

        except Exception:
            LOG.exception(_LE('process_service exception ERROR'))
Esempio n. 53
0
    def _update_firewall(self, firewall):
        """Update ACL and associated interfaces.

        :param firewall: firewall dictionary
        :return: True and status_data if OK
        :return: False and {} if there is an error
        """

        if not self._validate_firewall_data(firewall):
            return False, {}
        if not self._validate_firewall_rule_data(firewall):
            return False, {}

        acl_id = firewall['vendor_ext'].get('acl_id')
        if not acl_id:
            LOG.error(_LE("firewall (%s) has no acl_id"), firewall['id'])
            return False, {}

        csr = self._get_csr_host(firewall['vendor_ext'])
        rest_acl_rules = self._get_acl_rule_data(firewall)
        rest_acl_rules['acl-id'] = acl_id

        # update ACL rules
        response = self._put_acl(csr, acl_id, rest_acl_rules)
        if not response:
            return False, {}

        status_data = {
            'fw_id': firewall['id'],
            'acl_id': acl_id,
            'if_list': []
        }

        # update ACL interface
        # get all interfaces with this acl_id
        csr_fw_interface_list = self._get_acl_interface(csr, acl_id)
        self._delete_acl_on_interface(csr, acl_id, csr_fw_interface_list)

        if not firewall['admin_state_up']:
            return True, status_data

        self._post_acl_to_interfaces(firewall, csr, acl_id, status_data)
        return True, status_data
Esempio n. 54
0
    def process_router_add(self, ri):
        """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:
            # TODO(sridar): as per discussion with pc_m, we may want to hook
            # this up to the l3 agent observer notification
            self._process_router_add(ri)
        except Exception:
            LOG.exception(
                _LE("FWaaS RPC info call failed for '%s'."),
                ri.router['id'])
            self.services_sync_needed = True
Esempio n. 55
0
 def _post_acl_to_interfaces(self, firewall, csr, acl_id, status_data):
     acl_interface_url = ACL_API_ACLID_IF % acl_id
     for firewall_interface in firewall['vendor_ext']['if_list']:
         if_name = self._get_interface_name_from_hosting_port(
             firewall_interface['port'])
         acl_interface_req = {
             'if-id': if_name,
             'direction': firewall_interface['direction']
         }
         LOG.debug("acl_interface_url %s", acl_interface_url)
         csr.post_request(acl_interface_url, acl_interface_req)
         if csr.status == requests.codes.CREATED:
             status_data['if_list'].append(
                 {'port_id': firewall_interface['port']['id'],
                  'status': 'OK'})
         else:
             LOG.error(_LE("status %s"), csr.status)
             status_data['if_list'].append(
                 {'port_id': firewall_interface['port']['id'],
                  'status': 'ERROR'})
Esempio n. 56
0
 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:
         # we are in a upgrade and msg from older version of plugin
         try:
             routers = self.plugin_rpc.get_routers(context)
         except Exception:
             LOG.exception(
                 _LE("FWaaS RPC failure in _get_router_ids_for_fw "
                     "for firewall: %(fwid)s"),
                 {'fwid': fw['id']})
             self.services_sync_needed = True
         return [
             router['id']
             for router in routers
             if router['tenant_id'] == fw['tenant_id']]
Esempio n. 57
0
    def login_server(self):
        if self.session:
            yield
        else:
            ret = self.login()
            LOG.debug("SMC server LOGIN successfully.")

            if ret:
                try:
                    yield
                except Exception:
                    LOG.exception(_LE("exception while connect to server!"))
                    raise n_exc.ServiceUnavailable(resource='SMC server',
                                                   msg=_("OPERATION failed"))

                finally:
                    self.logout()

            else:
                raise n_exc.BadRequest(resource='SMC server',
                                       msg=_("LOGIN failed!"))
Esempio n. 58
0
    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'))