LCOV - code coverage report
Current view: top level - pkg/networkmanager - firewall-client.js Coverage Total Hit
Test: cockpit Lines: 56.3 % 446 251
Test Date: 2026-07-02 14:11:36

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2018 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5              : 
       6            2 : import cockpit from 'cockpit';
       7              : import * as service from 'service';
       8              : import { debounce } from 'throttle-debounce';
       9              : import * as utils from './utils.js';
      10              : 
      11            2 : const firewall = {
      12            2 :     owner: undefined,
      13            2 :     installed: true,
      14            2 :     enabled: false,
      15            2 :     readonly: true,
      16            2 :     services: {},
      17            2 :     enabledServices: new Set(),
      18              :     /* Dictionary where zone ID is the key and zone information, as fetched by
      19              :      * fetchZoneInfos, the value */
      20            2 :     zones: {},
      21            2 :     activeZones: new Set(),
      22              :     /* Zones predefined by firewalld, from untrusted to trusted */
      23            2 :     predefinedZones: ['drop', 'block', 'public', 'external',
      24            2 :         'dmz', 'work', 'home', 'internal', 'trusted'],
      25            2 :     defaultZone: null,
      26            2 :     availableInterfaces: [],
      27            2 :     ready: false
      28            2 : };
      29              : 
      30            2 : cockpit.event_target(firewall);
      31              : 
      32            2 : utils.list_interfaces().then(interfaces => {
      33            2 :     firewall.availableInterfaces = interfaces;
      34            2 : });
      35              : 
      36            2 : const firewalld_service = service.proxy('firewalld');
      37            2 : let firewalld_dbus = null;
      38              : 
      39            2 : function debug() {
      40            0 :     if (window.debugging == "all" || window.debugging?.includes("firewalld")) // not-covered: debugging
      41            0 :         console.debug("firewalld:", ...arguments); // not-covered: debugging
      42            2 : }
      43              : 
      44            2 : firewall.debouncedGetZones = debounce(300, () => {
      45            2 :     if (firewalld_dbus)
      46            2 :         getZones()
      47            2 :                 .then(() => getServices())
      48            2 :                 .then(() => firewall.debouncedEvent('changed'))
      49            0 :                 .catch(error => console.warn(error));
      50            2 : });
      51              : 
      52              : /* As certain dbus signal callbacks might change the firewall frequently
      53              :  * in a short period of time, prevent rapid succession of renders by
      54              :  * debouncing the ('changed') event */
      55            2 : firewall.debouncedEvent = debounce(300, event => firewall.dispatchEvent(event));
      56              : 
      57              : /* As a service might be removed from multiple zones at the same time,
      58              :  * prevent rapid succession of GetServices call */
      59            1 : firewall.debouncedGetServices = debounce(300, () => {
      60            1 :     getServices().then(() => firewall.debouncedEvent('changed'));
      61            1 : });
      62              : 
      63            2 : function initFirewalldDbus(owner) {
      64            2 :     debug("initializing D-Bus connection", owner);
      65            2 :     firewall.owner = owner;
      66            2 :     firewall.enabled = !!owner;
      67              : 
      68            2 :     firewall.zones = {};
      69            2 :     firewall.activeZones = new Set();
      70            2 :     firewall.services = {};
      71            2 :     firewall.enabledServices = new Set();
      72              : 
      73            0 :     if (!firewall.enabled) {
      74            0 :         firewall.ready = true;
      75            0 :         firewall.dispatchEvent('changed');
      76            0 :         return;
      77            0 :     }
      78              : 
      79            2 :     firewalld_dbus = cockpit.dbus(owner, { superuser: "try", track: true });
      80              : 
      81            2 :     firewalld_dbus.subscribe({
      82            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
      83            2 :         path: '/org/fedoraproject/FirewallD1',
      84            2 :         member: 'ServiceAdded'
      85            1 :     }, (path, iface, signal, args) => {
      86            1 :         const zone = args[0];
      87            1 :         const service = args[1];
      88            1 :         fetchZoneInfos([zone])
      89            1 :                 .then(() => fetchServiceInfos([service]))
      90            1 :                 .then(info => firewall.enabledServices.add(info[0].id))
      91            1 :                 .then(() => firewall.debouncedEvent('changed'))
      92            0 :                 .catch(error => console.warn(error));
      93            1 :     });
      94              : 
      95            2 :     firewalld_dbus.subscribe({
      96            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
      97            2 :         path: '/org/fedoraproject/FirewallD1',
      98            2 :         member: 'ServiceRemoved'
      99            1 :     }, (path, iface, signal, args) => {
     100            1 :         const zone = args[0];
     101            1 :         const service = args[1];
     102              : 
     103            1 :         firewall.zones[zone].services = firewall.zones[zone].services.filter(s => s !== service);
     104            1 :         firewall.enabledServices.delete(service);
     105            1 :         firewall.debouncedGetServices();
     106            1 :     });
     107              : 
     108            2 :     firewalld_dbus.subscribe({
     109            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     110            2 :         path: '/org/fedoraproject/FirewallD1',
     111            2 :         member: 'PortAdded'
     112            0 :     }, (path, iface, signal, args) => {
     113            0 :         const zone = args[0];
     114            0 :         const port = args[1];
     115            0 :         const protocol = args[2];
     116            0 :         if (!firewall.zones[zone].ports.some(p => p.port === port && p.protocol === protocol)) {
     117            0 :             firewall.zones[zone].ports.push({ port, protocol });
     118            0 :             firewall.debouncedEvent('changed');
     119            0 :         }
     120            0 :     });
     121              : 
     122            2 :     firewalld_dbus.subscribe({
     123            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     124            2 :         path: '/org/fedoraproject/FirewallD1',
     125            2 :         member: 'PortRemoved'
     126            0 :     }, (path, iface, signal, args) => {
     127            0 :         const zone = args[0];
     128            0 :         const port = args[1];
     129            0 :         const protocol = args[2];
     130            0 :         firewall.zones[zone].ports = firewall.zones[zone].ports
     131            0 :                 .filter(p => p.port !== port || p.protocol !== protocol);
     132            0 :         firewall.debouncedEvent('changed');
     133            0 :     });
     134              : 
     135            2 :     firewalld_dbus.subscribe({
     136            2 :         interface: 'org.fedoraproject.FirewallD1',
     137            2 :         path: '/org/fedoraproject/FirewallD1',
     138            2 :         member: 'Reloaded'
     139            1 :     }, () => firewall.debouncedGetZones());
     140              : 
     141              :     /* There are two APIs available, changeZoneOf(Interface|Source) and
     142              :      * add(Interface|Source). Listen to both of them for any background changes
     143              :      * to zones. */
     144            2 :     firewalld_dbus.subscribe({
     145            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     146            2 :         path: '/org/fedoraproject/FirewallD1',
     147            2 :         member: 'ZoneOfInterfaceChanged'
     148            1 :     }, () => firewall.debouncedGetZones());
     149            2 :     firewalld_dbus.subscribe({
     150            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     151            2 :         path: '/org/fedoraproject/FirewallD1',
     152            2 :         member: 'ZoneOfSourceChanged'
     153            0 :     }, () => firewall.debouncedGetZones());
     154              : 
     155            2 :     firewalld_dbus.subscribe({
     156            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     157            2 :         path: '/org/fedoraproject/FirewallD1',
     158            2 :         member: 'InterfaceAdded'
     159            0 :     }, () => firewall.debouncedGetZones());
     160            2 :     firewalld_dbus.subscribe({
     161            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     162            2 :         path: '/org/fedoraproject/FirewallD1',
     163            2 :         member: 'SourceAdded'
     164            0 :     }, () => firewall.debouncedGetZones());
     165            2 :     firewalld_dbus.subscribe({
     166            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     167            2 :         path: '/org/fedoraproject/FirewallD1',
     168            2 :         member: 'InterfaceRemoved'
     169            0 :     }, () => firewall.debouncedGetZones());
     170            2 :     firewalld_dbus.subscribe({
     171            2 :         interface: 'org.fedoraproject.FirewallD1.zone',
     172            2 :         path: '/org/fedoraproject/FirewallD1',
     173            2 :         member: 'SourceRemoved'
     174            0 :     }, () => firewall.debouncedGetZones());
     175              : 
     176            2 :     getZones()
     177            2 :             .then(() => getServices())
     178            0 :             .catch(error => console.warn(error))
     179            2 :             .then(() => { firewall.ready = true })
     180            2 :             .then(() => firewall.debouncedEvent('changed'));
     181            2 : }
     182              : 
     183            2 : firewalld_service.addEventListener('changed', () => {
     184            2 :     const installed = !!firewalld_service.exists;
     185            2 :     const is_running = firewalld_service.state === 'running';
     186              : 
     187              :     // we get lots of these events, for internal property changes; filter interesting changes
     188            2 :     if (is_running === firewalld_service.prev_running && firewall.installed === installed)
     189            2 :         return;
     190            2 :     firewall.installed = installed;
     191            2 :     firewalld_service.prev_running = is_running;
     192              : 
     193            2 :     debug("systemd service changed: exists", firewalld_service.exists, "state", firewalld_service.state,
     194            2 :           "firewall.enabled:", JSON.stringify(firewall.enabled));
     195              : 
     196            2 :     firewall.dispatchEvent('changed');
     197            2 : });
     198              : 
     199            2 : function getZones() {
     200            2 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     201            2 :                                'org.fedoraproject.FirewallD1.zone',
     202            2 :                                'getActiveZones', [])
     203            2 :             .then(reply => fetchZoneInfos(Object.keys(reply[0])))
     204            2 :             .then(zones => {
     205            2 :                 firewall.activeZones = new Set(zones.map(z => z.id));
     206            2 :                 debug("getActiveZones succeeded:", JSON.stringify([...firewall.activeZones]));
     207            2 :             })
     208            2 :             .then(() => firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     209            2 :                                             'org.fedoraproject.FirewallD1',
     210            2 :                                             'getDefaultZone', []))
     211            2 :             .then(reply => {
     212            2 :                 firewall.defaultZone = reply[0];
     213            2 :             })
     214            2 :             .then(() => firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     215            2 :                                             'org.fedoraproject.FirewallD1.zone',
     216            2 :                                             'getZones', []))
     217            2 :             .then(reply => fetchZoneInfos(reply[0]));
     218            2 : }
     219              : 
     220            2 : function getServices() {
     221            2 :     if (firewall.readonly)
     222            0 :         return Promise.resolve();
     223            2 :     firewall.enabledServices = new Set();
     224            2 :     return Promise.all([...firewall.activeZones].map(z => {
     225            2 :         return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     226            2 :                                    'org.fedoraproject.FirewallD1.zone',
     227            2 :                                    'getServices', [z])
     228            2 :                 .then(reply => fetchServiceInfos(reply[0]))
     229            2 :                 .then(services => {
     230            2 :                     const promises = [];
     231            2 :                     for (const s of services) {
     232            2 :                         firewall.enabledServices.add(s.id);
     233            2 :                         if (s.includes.length)
     234            0 :                             promises.push(fetchServiceInfos(s.includes));
     235            2 :                     }
     236            2 :                     return Promise.all(promises);
     237            2 :                 });
     238            2 :     }));
     239            2 : }
     240              : 
     241            2 : function fetchServiceInfos(services) {
     242            2 :     return Promise.all(services.map(service => {
     243            2 :         if (firewall.services[service])
     244            2 :             return firewall.services[service];
     245              : 
     246            2 :         let info;
     247            2 :         return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     248            2 :                                    'org.fedoraproject.FirewallD1',
     249            2 :                                    'getServiceSettings2', [service])
     250            2 :                 .then(([{ short, description, ports }]) => {
     251            0 :                     short = short ? short.v : "";
     252            0 :                     description = description ? description.v : "";
     253            0 :                     ports = ports ? ports.v : [];
     254            2 :                     info = {
     255            2 :                         id: service,
     256            2 :                         name: short,
     257            2 :                         description,
     258            2 :                         ports: ports.map(p => ({ port: p[0], protocol: p[1] })),
     259            2 :                         includes: [],
     260            2 :                     };
     261              : 
     262            2 :                     firewall.services[service] = info;
     263            2 :                     return firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     264            2 :                                                'org.fedoraproject.FirewallD1.config',
     265            2 :                                                'getServiceByName', [service]);
     266            2 :                 })
     267            2 :                 .then(path => firewalld_dbus.call(path[0],
     268            2 :                                                   'org.fedoraproject.FirewallD1.config.service',
     269            2 :                                                   'getSettings2', []))
     270            2 :                 .then(reply => {
     271            0 :                     if (reply[0].includes) {
     272            0 :                         info.includes = reply[0].includes.v;
     273            0 :                         firewall.services[service] = info;
     274            0 :                     }
     275            2 :                     return info;
     276            2 :                 })
     277            0 :                 .catch(error => {
     278            0 :                     if (error.name === 'org.freedesktop.DBus.Error.UnknownMethod')
     279            0 :                         return info;
     280            0 :                     return Promise.reject(error);
     281            0 :                 });
     282            2 :     }));
     283            2 : }
     284              : 
     285            2 : function fetchZoneInfos(zones) {
     286            2 :     return Promise.all(zones.map(zone => {
     287            1 :         if (firewall.readonly) {
     288            1 :             const info = {
     289            1 :                 id: zone,
     290            1 :                 name: zone,
     291            1 :                 description: null,
     292            1 :                 target: null,
     293            1 :                 services: [],
     294            1 :                 ports: [],
     295            1 :                 interfaces: [],
     296            1 :                 source: [],
     297            1 :             };
     298            1 :             firewall.zones[zone] = info;
     299            1 :             return info;
     300            1 :         }
     301            2 :         return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     302            2 :                                    'org.fedoraproject.FirewallD1.zone',
     303            2 :                                    'getZoneSettings2', [zone])
     304            2 :                 .then(([zoneInfo]) => {
     305            2 :                     const info = {
     306            2 :                         id: zone,
     307            1 :                         name: (zoneInfo.short || {}).v,
     308            1 :                         description: (zoneInfo.description || {}).v,
     309            0 :                         target: (zoneInfo.target || {}).v,
     310            2 :                         services: ((zoneInfo.services || {}).v || []),
     311            2 :                         ports: ((zoneInfo.ports || {}).v || []).map(p => ({ port: p[0], protocol: p[1] })),
     312            2 :                         interfaces: ((zoneInfo.interfaces || {}).v || []),
     313            2 :                         source: ((zoneInfo.sources || {}).v || []),
     314            2 :                     };
     315            2 :                     firewall.zones[zone] = info;
     316            2 :                     return info;
     317            2 :                 });
     318            2 :     }));
     319            2 : }
     320              : 
     321              : /* We watch the name owner explicitly.
     322              : 
     323              :    The org.fedoraproject.FirewallD service might appear on D-Bus only
     324              :    some time after the firewalld.service is active and thus we want to
     325              :    only try connecting to it once we know that it is definitely there.
     326              :    However, while cockpit.dbus() does work with services that
     327              :    disappear and then reappear on the bus while the channel is open,
     328              :    it doesn't work with names that are not present when the channel is
     329              :    initially opened (see
     330              :    https://github.com/cockpit-project/cockpit/pull/9125).
     331              : 
     332              :    Thus, we track the name explicitly via the org.freedesktop.DBus
     333              :    API.
     334              :  */
     335              : 
     336            2 : function dbus_watch_name_owner(name, owner_callback) {
     337            2 :     const bus = cockpit.dbus('org.freedesktop.DBus', { superuser: "try" });
     338            2 :     let owner = null;
     339              : 
     340            2 :     function owner_changed(new_owner) {
     341            2 :         if (new_owner != owner) {
     342            2 :             owner = new_owner;
     343            2 :             owner_callback(owner);
     344            2 :         }
     345            2 :     }
     346              : 
     347            2 :     bus.subscribe({
     348            2 :         path: "/org/freedesktop/DBus",
     349            2 :         interface: "org.freedesktop.DBus",
     350            2 :         member: "NameOwnerChanged",
     351            2 :         arg0: name,
     352            0 :     }, (_path, _iface, _member, [_name, _old_owner, new_owner]) => {
     353            0 :         owner_changed(new_owner);
     354            0 :     });
     355              : 
     356            2 :     bus.call(
     357            2 :         "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetNameOwner",
     358            2 :         [name]
     359            2 :     )
     360            2 :             .then(([owner]) => {
     361            2 :                 owner_changed(owner);
     362            2 :             })
     363            0 :             .catch(ex => {
     364            0 :                 if (ex.name == "org.freedesktop.DBus.Error.NameHasNoOwner")
     365            0 :                     owner_changed("");
     366              :                 else
     367            0 :                     throw ex;
     368            0 :             });
     369            2 : }
     370              : 
     371            2 : dbus_watch_name_owner('org.fedoraproject.FirewallD1', initFirewalldDbus);
     372              : 
     373            2 : cockpit.spawn(['sh', '-c', 'pkcheck --action-id org.fedoraproject.FirewallD1.all --process $$ --allow-user-interaction 2>&1'], { superuser: "try" })
     374            2 :         .then(() => {
     375            2 :             firewall.readonly = false;
     376            2 :             firewall.debouncedEvent('changed');
     377            2 :             firewall.debouncedGetZones();
     378            2 :         })
     379            0 :         .catch(error => {
     380            0 :             console.log("pkcheck failed", error);
     381              : 
     382              :             // Fall back to cockpit.permissions, "pkcheck" might not be available,
     383              :             // always allow edits by admins
     384            0 :             const permission = cockpit.permission({ admin: true });
     385            0 :             const update_permissions = () => {
     386            0 :                 firewall.readonly = !permission.allowed;
     387            0 :                 firewall.debouncedEvent('changed');
     388            0 :                 firewall.debouncedGetZones();
     389            0 :             };
     390            0 :             permission.addEventListener("changed", update_permissions);
     391            0 :         });
     392              : 
     393            0 : firewall.enable = () => firewalld_service.enable().then(() => firewalld_service.start());
     394            0 : firewall.disable = () => firewalld_service.disable().then(() => firewalld_service.stop());
     395              : 
     396            0 : firewall.getAvailableServices = () => {
     397            0 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     398            0 :                                'org.fedoraproject.FirewallD1',
     399            0 :                                'listServices', [])
     400            0 :             .then(reply => fetchServiceInfos(reply[0]))
     401            0 :             .catch(error => console.warn(error));
     402            0 : };
     403              : 
     404              : /*
     405              :  * Only call this after defining a new service, as it will remove existing
     406              :  * non-permanent configurations.
     407              :  */
     408            0 : firewall.reload = () => {
     409            0 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     410            0 :                                'org.fedoraproject.FirewallD1',
     411            0 :                                'reload', [])
     412            0 :             .catch(error => console.warn(error));
     413            0 : };
     414              : 
     415              : /*
     416              :  * Remove a service from the specified zone (i.e., close its ports).
     417              :  *
     418              :  * Returns a promise that resolves when the service is removed.
     419              :  */
     420            0 : firewall.removeService = (zone, service) => {
     421            0 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     422            0 :                                'org.fedoraproject.FirewallD1.zone',
     423            0 :                                'removeService', [zone, service])
     424            0 :             .then(reply => firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     425            0 :                                                'org.fedoraproject.FirewallD1.config',
     426            0 :                                                'getZoneByName', [zone]))
     427            0 :             .then(path => firewalld_dbus.call(path[0], 'org.fedoraproject.FirewallD1.config.zone',
     428            0 :                                               'removeService', [service]));
     429            0 : };
     430              : 
     431            0 : firewall.removePort = (zone, port, protocol) => {
     432            0 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     433            0 :                                'org.fedoraproject.FirewallD1.zone',
     434            0 :                                'removePort', [zone, port, protocol])
     435            0 :             .then(reply => firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     436            0 :                                                'org.fedoraproject.FirewallD1.config',
     437            0 :                                                'getZoneByName', [zone]))
     438            0 :             .then(path => firewalld_dbus.call(path[0], 'org.fedoraproject.FirewallD1.config.zone',
     439            0 :                                               'removePort', [port, protocol]));
     440            0 : };
     441              : 
     442              : /*
     443              :  * Create new firewalld service.
     444              :  *
     445              :  * Returns a promise that resolves when the service is created.
     446              :  * It will also reload firewalld and enable the new service.
     447              :  */
     448            0 : firewall.createService = (service, ports, zones, desc = "") => {
     449            0 :     const subscription = firewalld_dbus.subscribe({
     450            0 :         interface: 'org.fedoraproject.FirewallD1',
     451            0 :         path: '/org/fedoraproject/FirewallD1',
     452            0 :         member: 'Reloaded'
     453            0 :     }, () => {
     454            0 :         firewall.addServices(zones, [service]);
     455            0 :         subscription.remove();
     456            0 :     });
     457            0 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     458            0 :                                'org.fedoraproject.FirewallD1.config',
     459            0 :                                'addService2', [service, { description: { t: 's', v: desc }, ports: { t: 'a(ss)', v: ports } }])
     460            0 :             .then(() => firewall.reload());
     461            0 : };
     462              : 
     463              : /*
     464              :  * Edit firewalld service.
     465              :  *
     466              :  * Returns a promise that resolves when the service is edited.
     467              :  */
     468            0 : firewall.editService = (service, ports, desc = "") => {
     469            0 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     470            0 :                                'org.fedoraproject.FirewallD1.config',
     471            0 :                                'getServiceByName', [service])
     472            0 :             .then(path => firewalld_dbus.call(path[0],
     473            0 :                                               'org.fedoraproject.FirewallD1.config.service',
     474            0 :                                               'update2', [{ description: { t: 's', v: desc }, ports: { t: 'a(ss)', v: ports } }])
     475            0 :                     .then(() => {
     476              :                         // No signal for updated service so we need to manually update it
     477            0 :                         firewall.services[service].description = desc;
     478            0 :                         firewall.services[service].ports = ports.map(port => ({ port: port[0], protocol: port[1] }));
     479            0 :                         firewall.debouncedEvent('changed');
     480            0 :                         return firewall.reload();
     481            0 :                     })
     482            0 :             );
     483            0 : };
     484              : 
     485              : /*
     486              :  * Add a predefined firewalld service to the specified zone (i.e., open its
     487              :  * ports).
     488              :  *
     489              :  * Returns a promise that resolves when the service is added.
     490              :  */
     491            0 : firewall.addService = (zone, service) => {
     492            0 :     return firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     493            0 :                                'org.fedoraproject.FirewallD1.zone',
     494            0 :                                'addService', [zone, service, 0])
     495            0 :             .then(reply => firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     496            0 :                                                'org.fedoraproject.FirewallD1.config',
     497            0 :                                                'getZoneByName', [zone]))
     498            0 :             .then(path => firewalld_dbus.call(path[0], 'org.fedoraproject.FirewallD1.config.zone',
     499            0 :                                               'addService', [service]));
     500            0 : };
     501              : 
     502              : /*
     503              :  * Like addService(), but adds multiple predefined firewalld services at once
     504              :  * to the specified zones.
     505              :  *
     506              :  * Returns a promise that resolves when all services are added.
     507              :  */
     508            0 : firewall.addServices = (zone, services) =>
     509            0 :     Promise.all(services.map(s => firewall.addService(zone, s)));
     510              : 
     511            0 : firewall.removeServiceFromZones = (zones, service) =>
     512            0 :     Promise.all(zones.map(z => firewall.removeService(z, service)));
     513              : 
     514            0 : firewall.activateZone = (zone, interfaces, sources) => {
     515            0 :     let promises = interfaces.map(i => firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     516            0 :                                                            'org.fedoraproject.FirewallD1.zone',
     517            0 :                                                            'addInterface', [zone, i]));
     518              : 
     519            0 :     promises = promises.concat(sources.map(s => firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     520            0 :                                                                     'org.fedoraproject.FirewallD1.zone',
     521            0 :                                                                     'addSource', [zone, s])));
     522            0 :     let p = Promise.all(promises).then(() => firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     523            0 :                                                                  'org.fedoraproject.FirewallD1.config',
     524            0 :                                                                  'getZoneByName', [zone]));
     525            0 :     p = p.then(path => {
     526              :         /* Once this signal is received, it's safe to actually emit the changed
     527              :          * signal and thus update the UI */
     528            0 :         const subscription = firewalld_dbus.subscribe({
     529            0 :             interface: 'org.fedoraproject.FirewallD1.config.zone',
     530            0 :             path: path[0],
     531            0 :             member: 'Updated'
     532            0 :         }, (path, iface, signal, args) => {
     533            0 :             getZones().then(() => getServices());
     534            0 :             subscription.remove();
     535            0 :         });
     536              : 
     537            0 :         return firewalld_dbus.call(path[0],
     538            0 :                                    'org.fedoraproject.FirewallD1.config.zone',
     539            0 :                                    'update2', [{ interfaces: { t: 'as', v: interfaces }, sources: { t: 'as', v: sources } }]);
     540            0 :     });
     541            0 :     return p;
     542            0 : };
     543              : 
     544              : /*
     545              :  * A zone is considered deactivated when it has no interfaces or sources.
     546              :  */
     547            0 : firewall.deactiveateZone = (zone) => {
     548            0 :     const zoneObject = firewall.zones[zone];
     549            0 :     let promises = zoneObject.interfaces.map(i => firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     550            0 :                                                                       'org.fedoraproject.FirewallD1.zone',
     551            0 :                                                                       'removeInterface', [zone, i]));
     552            0 :     promises = promises.concat(zoneObject.source.map(s => firewalld_dbus.call('/org/fedoraproject/FirewallD1',
     553            0 :                                                                               'org.fedoraproject.FirewallD1.zone',
     554            0 :                                                                               'removeSource', [zone, s])));
     555            0 :     let p = Promise.all(promises).then(() => firewalld_dbus.call('/org/fedoraproject/FirewallD1/config',
     556            0 :                                                                  'org.fedoraproject.FirewallD1.config',
     557            0 :                                                                  'getZoneByName', [zone]));
     558            0 :     p = p.then(path => {
     559              :         /* Once this signal is received, it's safe to actually emit the changed
     560              :          * signal and thus update the UI */
     561            0 :         const subscription = firewalld_dbus.subscribe({
     562            0 :             interface: 'org.fedoraproject.FirewallD1.config.zone',
     563            0 :             path: path[0],
     564            0 :             member: 'Updated'
     565            0 :         }, (path, iface, signal, args) => {
     566            0 :             firewall.activeZones.delete(args[0]);
     567            0 :             getZones().then(() => getServices());
     568            0 :             subscription.remove();
     569            0 :         });
     570              : 
     571            0 :         return firewalld_dbus.call(path[0],
     572            0 :                                    'org.fedoraproject.FirewallD1.config.zone',
     573            0 :                                    'update2', [{ interfaces: { t: 'as', v: [] }, sources: { t: 'as', v: [] } }]);
     574            0 :     });
     575              : 
     576            0 :     return p.catch(error => console.warn(error));
     577            0 : };
     578              : 
     579            2 : export default firewall;
        

Generated by: LCOV version 2.0-1