[libvirt] [PATCH v2 6/7] network: allow configuring firewalld zone for virtual network bridge device

Laine Stump laine at laine.org
Fri Feb 1 01:24:57 UTC 2019


Since we're setting the zone anyway, it will be useful to allow
setting a different (custom) zone for each network. This will be done
by adding a "zone" attribute to the "bridge" element, e.g.:

   ...
   <bridge name='virbr0' zone='myzone'/>
   ...

If a zone is specified in the config and it can't be honored, this
will be an error.

Signed-off-by: Laine Stump <laine at laine.org>
---

Change from V1: move news.xml additions to a separate patch, as requested.

 docs/firewall.html.in                      |  5 +++++
 docs/formatnetwork.html.in                 | 17 +++++++++++++++++
 docs/schemas/basictypes.rng                |  6 ++++++
 docs/schemas/network.rng                   |  6 ++++++
 src/conf/network_conf.c                    | 14 ++++++++++++--
 src/conf/network_conf.h                    |  1 +
 src/network/bridge_driver_linux.c          | 19 +++++++++++++++++++
 tests/networkxml2xmlin/routed-network.xml  |  2 +-
 tests/networkxml2xmlout/routed-network.xml |  2 +-
 9 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/docs/firewall.html.in b/docs/firewall.html.in
index 5d584e582e..e86ab0d974 100644
--- a/docs/firewall.html.in
+++ b/docs/firewall.html.in
@@ -151,6 +151,11 @@ MASQUERADE all  --  *      *       192.168.122.0/24    !192.168.122.0/24</pre>
       iptables rules regardless of which backend is in use by
       firewalld.
     </p>
+    <p>
+      NB: It is possible to manually set the firewalld zone for a
+      network's interface with the "zone" attribute of the network's
+      "bridge" element.
+    </p>
     <p>
       NB: Prior to libvirt 5.1.0, the firewalld "libvirt" zone did not
       exist, and prior to firewalld 0.7.0 a feature crucial to making
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 156cfae4ec..509cca9e8b 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -152,6 +152,23 @@
           <span class="since">Since 1.2.11, requires kernel 3.17 or
           newer</span>
         </p>
+
+        <p>
+          The optional <code>zone</code> attribute of
+          the <code>bridge</code> element is used to specify
+          the <a href="https://firewalld.org">firewalld</a>
+          zone for the bridge of a network with <code>forward</code>
+          mode of "nat", "route", "open", or one with
+          no <code>forward</code> specified. By default, the bridges
+          of all virtual networks with these forward modes are placed
+          in the firewalld zone named "libvirt", which permits
+          incoming DNS, DHCP, TFTP, and SSH to the host from guests on
+          the network. This behavior can be changed either by
+          modifying the libvirt zone (using firewalld management
+          tools), or by placing the network in a different zone (which
+          will also be managed using firewalld tools).
+          <span class="since">Since 5.1.0</span>
+        </p>
       </dd>
 
       <dt><code>mtu</code></dt>
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 9a63720ff7..9b3dcad4a5 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -279,6 +279,12 @@
     </data>
   </define>
 
+  <define name="zoneName">
+    <data type="string">
+      <param name="pattern">[a-zA-Z0-9_\-]+</param>
+    </data>
+  </define>
+
   <define name="filePath">
     <data type="string">
       <param name="pattern">.+</param>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index f37c422bf3..2a6e3358fd 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -58,6 +58,12 @@
               </attribute>
             </optional>
 
+            <optional>
+              <attribute name="zone">
+                <ref name="zoneName"/>
+              </attribute>
+            </optional>
+
             <optional>
               <attribute name="stp">
                 <ref name="virOnOff"/>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index e035d8aba7..b09cb1dae2 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -203,6 +203,7 @@ virNetworkDefFree(virNetworkDefPtr def)
 
     VIR_FREE(def->name);
     VIR_FREE(def->bridge);
+    VIR_FREE(def->bridgeZone);
     VIR_FREE(def->domain);
 
     virNetworkForwardDefClear(&def->forward);
@@ -1684,6 +1685,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
 
     /* Parse bridge information */
     def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt);
+    def->bridgeZone = virXPathString("string(./bridge[1]/@zone)", ctxt);
     stp = virXPathString("string(./bridge[1]/@stp)", ctxt);
     def->stp = (stp && STREQ(stp, "off")) ? false : true;
 
@@ -1920,6 +1922,13 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                            def->name);
             goto error;
         }
+        if (def->bridgeZone) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("bridge zone not allowed in %s mode (network '%s')"),
+                           virNetworkForwardTypeToString(def->forward.type),
+                           def->name);
+            goto error;
+        }
         if (def->macTableManager) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("bridge macTableManager setting not allowed "
@@ -1931,9 +1940,9 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         ATTRIBUTE_FALLTHROUGH;
 
     case VIR_NETWORK_FORWARD_BRIDGE:
-        if (def->delay || stp) {
+        if (def->delay || stp || def->bridgeZone) {
             virReportError(VIR_ERR_XML_ERROR,
-                           _("bridge delay/stp options only allowed in "
+                           _("bridge delay/stp/zone options only allowed in "
                              "route, nat, and isolated mode, not in %s "
                              "(network '%s')"),
                            virNetworkForwardTypeToString(def->forward.type),
@@ -2508,6 +2517,7 @@ virNetworkDefFormatBuf(virBufferPtr buf,
     if (hasbridge || def->bridge || def->macTableManager) {
         virBufferAddLit(buf, "<bridge");
         virBufferEscapeString(buf, " name='%s'", def->bridge);
+        virBufferEscapeString(buf, " zone='%s'", def->bridgeZone);
         if (hasbridge)
             virBufferAsprintf(buf, " stp='%s' delay='%ld'",
                               def->stp ? "on" : "off", def->delay);
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index c630674300..673f70cc68 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -235,6 +235,7 @@ struct _virNetworkDef {
     int   connections; /* # of guest interfaces connected to this network */
 
     char *bridge;       /* Name of bridge device */
+    char *bridgeZone;  /* name of firewalld zone for bridge */
     int  macTableManager; /* enum virNetworkBridgeMACTableManager */
     char *domain;
     int domainLocalOnly; /* enum virTristateBool: yes disables dns forwarding */
diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
index 9d2e6877ae..b10d0a6c4d 100644
--- a/src/network/bridge_driver_linux.c
+++ b/src/network/bridge_driver_linux.c
@@ -671,6 +671,24 @@ int networkAddFirewallRules(virNetworkDefPtr def)
     virFirewallPtr fw = NULL;
     int ret = -1;
 
+    if (def->bridgeZone) {
+
+        /* if a firewalld zone has been specified, fail/log an error
+         * if we can't honor it
+         */
+        if (virFirewallDIsRegistered() < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("zone %s requested for network %s "
+                             "but firewalld is not active"),
+                           def->bridgeZone, def->name);
+            goto cleanup;
+        }
+
+        if (virFirewallDInterfaceSetZone(def->bridge, def->bridgeZone) < 0)
+            goto cleanup;
+
+    } else {
+
         /* if firewalld is active, try to set the "libvirt" zone. This is
          * desirable (for consistency) if firewalld is using the iptables
          * backend, but is necessary (for basic network connectivity) if
@@ -717,6 +735,7 @@ int networkAddFirewallRules(virNetworkDefPtr def)
                 }
             }
         }
+    }
 
     fw = virFirewallNew();
 
diff --git a/tests/networkxml2xmlin/routed-network.xml b/tests/networkxml2xmlin/routed-network.xml
index ab5e15b1f6..fce01df132 100644
--- a/tests/networkxml2xmlin/routed-network.xml
+++ b/tests/networkxml2xmlin/routed-network.xml
@@ -1,7 +1,7 @@
 <network>
   <name>local</name>
   <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
-  <bridge name="virbr1"/>
+  <bridge name="virbr1" zone="myzone"/>
   <mac address='12:34:56:78:9A:BC'/>
   <forward mode="route" dev="eth1"/>
   <ip address="192.168.122.1" netmask="255.255.255.0">
diff --git a/tests/networkxml2xmlout/routed-network.xml b/tests/networkxml2xmlout/routed-network.xml
index 81abf06e9f..2e13cf4ffa 100644
--- a/tests/networkxml2xmlout/routed-network.xml
+++ b/tests/networkxml2xmlout/routed-network.xml
@@ -4,7 +4,7 @@
   <forward dev='eth1' mode='route'>
     <interface dev='eth1'/>
   </forward>
-  <bridge name='virbr1' stp='on' delay='0'/>
+  <bridge name='virbr1' zone='myzone' stp='on' delay='0'/>
   <mac address='12:34:56:78:9a:bc'/>
   <ip address='192.168.122.1' netmask='255.255.255.0'>
   </ip>
-- 
2.20.1




More information about the libvir-list mailing list