[libvirt] [PATCH v7 1/5] domain: Add optional 'tls' attribute for TCP chardev

John Ferlan jferlan at redhat.com
Mon Sep 19 14:39:20 UTC 2016


Add an optional "tls='yes'" option for a TCP chardev for the
express purpose to enable setting up TLS for the chardev. This
will assume that the qemu.conf settings have been adjusted as
well as the environment configured properly.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 docs/formatdomain.html.in                          | 21 +++++++++
 docs/schemas/domaincommon.rng                      |  5 +++
 src/conf/domain_conf.c                             | 22 +++++++++-
 src/conf/domain_conf.h                             |  1 +
 src/qemu/qemu_command.c                            |  3 +-
 src/qemu/qemu_hotplug.c                            |  3 +-
 ...emuxml2argv-serial-tcp-tlsx509-chardev-tls.args | 30 +++++++++++++
 ...qemuxml2argv-serial-tcp-tlsx509-chardev-tls.xml | 50 ++++++++++++++++++++++
 .../qemuxml2argv-serial-tcp-tlsx509-chardev.xml    |  2 +-
 tests/qemuxml2argvtest.c                           |  3 ++
 ...muxml2xmlout-serial-tcp-tlsx509-chardev-tls.xml |  1 +
 .../qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml  |  2 +-
 tests/qemuxml2xmltest.c                            |  1 +
 13 files changed, 139 insertions(+), 5 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.xml
 create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev-tls.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f48a4d8..8f2b981 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6192,6 +6192,27 @@ qemu-kvm -net nic,model=? /dev/null
   </devices>
   ...</pre>
 
+    <p>
+      <span class="since">Since 2.3.0,</span> some hypervisors support using
+      a TLS X.509 certificate environment in order to encrypt all serial TCP
+      connections via a hypervisor configuration option. In order to enable
+      TLS for the domain an optional attribute <code>tls</code> can be set to
+      "yes". Combined with the hypervisor's capability to utilize the TLS
+      environment allows for the character device to use the encrypted
+      communication. If the attribute is not present, then the default
+      setting is "no".
+    </p>
+<pre>
+  ...
+  <devices>
+    <serial type="tcp">
+      <source mode='connect' host="127.0.0.1" service="5555" tls="yes"/>
+      <protocol type="raw"/>
+      <target port="0"/>
+    </serial>
+  </devices>
+  ...</pre>
+
     <h6><a name="elementsCharUDP">UDP network console</a></h6>
 
     <p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 751d914..da869b2 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3452,6 +3452,11 @@
             <ref name="virOnOff"/>
           </attribute>
         </optional>
+        <optional>
+          <attribute name="tls">
+            <ref name="virYesNo"/>
+          </attribute>
+        </optional>
         <zeroOrMore>
           <ref name='devSeclabel'/>
         </zeroOrMore>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b4a3e92..d2de15b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1960,6 +1960,8 @@ virDomainChrSourceDefCopy(virDomainChrSourceDefPtr dest,
 
         if (VIR_STRDUP(dest->data.tcp.service, src->data.tcp.service) < 0)
             return -1;
+
+        dest->data.tcp.haveTLS = src->data.tcp.haveTLS;
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UNIX:
@@ -9955,6 +9957,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
     char *master = NULL;
     char *slave = NULL;
     char *append = NULL;
+    char *haveTLS = NULL;
     int remaining = 0;
 
     while (cur != NULL) {
@@ -9962,6 +9965,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
             if (xmlStrEqual(cur->name, BAD_CAST "source")) {
                 if (!mode)
                     mode = virXMLPropString(cur, "mode");
+                if (!haveTLS)
+                    haveTLS = virXMLPropString(cur, "tls");
 
                 switch ((virDomainChrType) def->type) {
                 case VIR_DOMAIN_CHR_TYPE_FILE:
@@ -10138,6 +10143,15 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
             def->data.tcp.listen = true;
         }
 
+        if (haveTLS &&
+            (def->data.tcp.haveTLS =
+             virTristateBoolTypeFromString(haveTLS)) <= 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("unknown chardev 'tls' setting '%s'"),
+                           haveTLS);
+            goto error;
+        }
+
         if (!protocol)
             def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW;
         else if ((def->data.tcp.protocol =
@@ -10221,6 +10235,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
     VIR_FREE(append);
     VIR_FREE(logappend);
     VIR_FREE(logfile);
+    VIR_FREE(haveTLS);
 
     return remaining;
 
@@ -21340,7 +21355,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
         virBufferAsprintf(buf, "<source mode='%s' ",
                           def->data.tcp.listen ? "bind" : "connect");
         virBufferEscapeString(buf, "host='%s' ", def->data.tcp.host);
-        virBufferEscapeString(buf, "service='%s'/>\n", def->data.tcp.service);
+        virBufferEscapeString(buf, "service='%s'", def->data.tcp.service);
+        if (def->data.tcp.haveTLS != VIR_TRISTATE_BOOL_ABSENT)
+            virBufferAsprintf(buf, " tls='%s'",
+                    virTristateBoolTypeToString(def->data.tcp.haveTLS));
+        virBufferAddLit(buf, "/>\n");
+
         virBufferAsprintf(buf, "<protocol type='%s'/>\n",
                           virDomainChrTcpProtocolTypeToString(
                               def->data.tcp.protocol));
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c14a39c..25d0787 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1093,6 +1093,7 @@ struct _virDomainChrSourceDef {
             bool listen;
             int protocol;
             bool tlscreds;
+            int haveTLS; /* enum virTristateBool */
         } tcp;
         struct {
             char *bindHost;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 051a0bc..9683c9e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5041,7 +5041,8 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager,
                           telnet ? ",telnet" : "",
                           dev->data.tcp.listen ? ",server,nowait" : "");
 
-            if (cfg->chardevTLS) {
+            if (cfg->chardevTLS &&
+                dev->data.tcp.haveTLS == VIR_TRISTATE_BOOL_YES) {
                 char *objalias = NULL;
 
                 if (qemuBuildTLSx509CommandLine(cmd, cfg->chardevTLSx509certdir,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 72dd93b..419296e 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1677,7 +1677,8 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
     if (qemuDomainChrPreInsert(vmdef, chr) < 0)
         goto cleanup;
 
-    if (cfg->chardevTLS) {
+    if (cfg->chardevTLS &&
+        dev->data.tcp.haveTLS == VIR_TRISTATE_BOOL_YES) {
         if (qemuBuildTLSx509BackendProps(cfg->chardevTLSx509certdir,
                                          dev->data.tcp.listen,
                                          cfg->chardevTLSx509verify,
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.args
new file mode 100644
index 0000000..cac0d85
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.args
@@ -0,0 +1,30 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefconfig \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-chardev udp,id=charserial0,host=127.0.0.1,port=2222,localaddr=127.0.0.1,\
+localport=1111 \
+-device isa-serial,chardev=charserial0,id=serial0 \
+-chardev socket,id=charserial1,host=127.0.0.1,port=5555 \
+-device isa-serial,chardev=charserial1,id=serial1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.xml
new file mode 100644
index 0000000..debc69b
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.xml
@@ -0,0 +1,50 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <serial type='udp'>
+      <source mode='bind' host='127.0.0.1' service='1111'/>
+      <source mode='connect' host='127.0.0.1' service='2222'/>
+      <target port='0'/>
+    </serial>
+    <serial type='tcp'>
+      <source mode='connect' host='127.0.0.1' service='5555' tls='no'/>
+      <protocol type='raw'/>
+      <target port='0'/>
+    </serial>
+    <console type='udp'>
+      <source mode='bind' host='127.0.0.1' service='1111'/>
+      <source mode='connect' host='127.0.0.1' service='2222'/>
+      <target type='serial' port='0'/>
+    </console>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </memballoon>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml
index 1618b02..1d7896d 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml
@@ -27,7 +27,7 @@
       <target port='0'/>
     </serial>
     <serial type='tcp'>
-      <source mode='connect' host='127.0.0.1' service='5555'/>
+      <source mode='connect' host='127.0.0.1' service='5555' tls='yes'/>
       <protocol type='raw'/>
       <target port='0'/>
     </serial>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index e854077..7df76c1 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1125,6 +1125,9 @@ mymain(void)
     DO_TEST("serial-tcp-tlsx509-chardev",
             QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG,
             QEMU_CAPS_OBJECT_TLS_CREDS_X509);
+    DO_TEST("serial-tcp-tlsx509-chardev-tls",
+            QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG,
+            QEMU_CAPS_OBJECT_TLS_CREDS_X509);
     driver.config->chardevTLS = 0;
     VIR_FREE(driver.config->chardevTLSx509certdir);
     DO_TEST("serial-many-chardev",
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev-tls.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev-tls.xml
new file mode 120000
index 0000000..3453497
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev-tls.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev-tls.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml
index 832e2a2..23c244b 100644
--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml
@@ -32,7 +32,7 @@
       <target port='0'/>
     </serial>
     <serial type='tcp'>
-      <source mode='connect' host='127.0.0.1' service='5555'/>
+      <source mode='connect' host='127.0.0.1' service='5555' tls='yes'/>
       <protocol type='raw'/>
       <target port='0'/>
     </serial>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index fb05c85..a035ccf 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -534,6 +534,7 @@ mymain(void)
     DO_TEST("serial-udp", NONE);
     DO_TEST("serial-tcp-telnet", NONE);
     DO_TEST("serial-tcp-tlsx509-chardev", NONE);
+    DO_TEST("serial-tcp-tlsx509-chardev-tls", NONE);
     DO_TEST("serial-many", NONE);
     DO_TEST("serial-spiceport", NONE);
     DO_TEST("serial-spiceport-nospice", NONE);
-- 
2.7.4




More information about the libvir-list mailing list