[libvirt] [PATCH v4 11/14] conf: Add new secret element for tcp chardev

John Ferlan jferlan at redhat.com
Thu Jun 23 18:06:36 UTC 2016


Define, parse, and format a key secret element for a chardev tcp backend.
This secret will be used in conjunction with the chartcp_tls_x509_cert_dir
in order to provide the secret to the TLS encrypted TCP chardev.

    <secret type='passphrase' usage='keyexample'/>

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 docs/formatdomain.html.in                          | 29 ++++++++++++
 docs/schemas/domaincommon.rng                      | 21 +++++++++
 src/conf/domain_conf.c                             | 35 +++++++++++++++
 src/conf/domain_conf.h                             |  3 ++
 ...uxml2argv-serial-tcp-tlsx509-secret-chardev.xml | 42 ++++++++++++++++++
 ...ml2xmlout-serial-tcp-tlsx509-secret-chardev.xml | 51 ++++++++++++++++++++++
 tests/qemuxml2xmltest.c                            |  1 +
 7 files changed, 182 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml
 create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f660aa6..5803c40 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6031,6 +6031,35 @@ qemu-kvm -net nic,model=? /dev/null
   </devices>
   ...</pre>
 
+    <p>
+      <span class="since">Since 2.0.0,</span> some hypervisors support using
+      a TLS X.509 certificate environment in order to encrypt the TCP. In
+      order to provide the passphrase for the certificates, provide a
+      <code>secret</code> element. The <code>secret</code> element takes
+      two required attributes <code>type</code> and either <code>UUID</code>
+      or <code>usage</code>.  The supported <code>type</code> is a "passphrase"
+      secret referenced via either attribute <code>uuid</code> or
+      <code>usage</code>.
+    </p>
+<pre>
+  ...
+  <devices>
+    <serial type="tcp">
+      <source mode="connect" host="0.0.0.0" service="2445"/>
+      <protocol type="raw"/>
+      <secret type='passphrase' usage='keyexample'/>
+      <target port="1"/>
+    </serial>
+    ...
+    <serial type="tcp">
+      <source mode="bind" host="127.0.0.1" service="2445"/>
+      <protocol type="raw"/>
+      <target port="1"/>
+      <secret type='passphrase' usage='keyexample'/>
+    </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 162c2e0..eb08f3d 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3221,6 +3221,9 @@
         <ref name="qemucdevTgtDef"/>
       </optional>
       <optional>
+        <ref name="qemucdevSecret"/>
+      </optional>
+      <optional>
         <ref name="alias"/>
       </optional>
       <optional>
@@ -3272,6 +3275,24 @@
     </element>
   </define>
 
+  <define  name="qemucdevSecret">
+    <element name='secret'>
+      <attribute name='type'>
+        <choice>
+          <value>passphrase</value>
+        </choice>
+      </attribute>
+      <choice>
+        <attribute name='uuid'>
+          <ref name="UUID"/>
+        </attribute>
+        <attribute name='usage'>
+          <ref name='genericName'/>
+        </attribute>
+      </choice>
+    </element>
+  </define>
+
   <define name="qemucdevSrcTypeChoice">
     <choice>
       <value>dev</value>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9443281..f614ff9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1843,6 +1843,7 @@ virDomainChrSourceDefClear(virDomainChrSourceDefPtr def)
     case VIR_DOMAIN_CHR_TYPE_TCP:
         VIR_FREE(def->data.tcp.host);
         VIR_FREE(def->data.tcp.service);
+        virSecretLookupDefClear(&def->data.tcp.seclookupdef);
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UNIX:
@@ -1899,6 +1900,10 @@ virDomainChrSourceDefCopy(virDomainChrSourceDefPtr dest,
 
         if (VIR_STRDUP(dest->data.tcp.service, src->data.tcp.service) < 0)
             return -1;
+
+        if (virSecretLookupDefCopy(&dest->data.tcp.seclookupdef,
+                                   &src->data.tcp.seclookupdef) < 0)
+            return -1;
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UNIX:
@@ -9900,6 +9905,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
     char *master = NULL;
     char *slave = NULL;
     char *append = NULL;
+    xmlNodePtr secret = NULL;
+    char *sectypestr = NULL;
     int remaining = 0;
 
     while (cur != NULL) {
@@ -9989,6 +9996,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
             } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
                 if (!protocol)
                     protocol = virXMLPropString(cur, "type");
+            } else if (xmlStrEqual(cur->name, BAD_CAST "secret")) {
+                secret = cur;
             } else {
                 remaining++;
             }
@@ -10092,6 +10101,25 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
             goto error;
         }
 
+        if (secret) {
+
+            if (!(sectypestr = virXMLPropString(secret, "type"))) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("missing TCP chardev secret type"));
+                goto error;
+            }
+            if ((def->data.tcp.sectype =
+                 virSecretUsageTypeFromString(sectypestr)) !=
+                VIR_SECRET_USAGE_TYPE_PASSPHRASE) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("invalid TCP chardev secret type '%s'"),
+                               sectypestr);
+                goto error;
+            }
+            if (virSecretLookupParseSecret(secret,
+                                           &def->data.tcp.seclookupdef) < 0)
+                goto error;
+        }
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UDP:
@@ -10166,6 +10194,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
     VIR_FREE(append);
     VIR_FREE(logappend);
     VIR_FREE(logfile);
+    VIR_FREE(sectypestr);
 
     return remaining;
 
@@ -21065,6 +21094,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
         virBufferAsprintf(buf, "<protocol type='%s'/>\n",
                           virDomainChrTcpProtocolTypeToString(
                               def->data.tcp.protocol));
+        if (def->data.tcp.sectype == VIR_SECRET_USAGE_TYPE_PASSPHRASE) {
+            const char *typestr =
+                virSecretUsageTypeToString(def->data.tcp.sectype);
+            virSecretLookupFormatSecret(buf, typestr,
+                                        &def->data.tcp.seclookupdef);
+        }
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UNIX:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a06281c..8d4a9ec 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -52,6 +52,7 @@
 # include "virprocess.h"
 # include "virgic.h"
 # include "virperf.h"
+# include "virsecret.h"
 # include "virtypedparam.h"
 
 /* forward declarations of all device types, required by
@@ -1098,6 +1099,8 @@ struct _virDomainChrSourceDef {
             bool listen;
             int protocol;
             bool tlscreds;
+            int sectype;  /* virSecretUsage */
+            virSecretLookupTypeDef seclookupdef;
         } tcp;
         struct {
             char *bindHost;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml
new file mode 100644
index 0000000..e889072
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml
@@ -0,0 +1,42 @@
+<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'/>
+    <controller type='ide' index='0'/>
+    <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'/>
+      <protocol type='raw'/>
+      <target port='0'/>
+      <secret type='passphrase' usage='mycluster_myname'/>
+    </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>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml
new file mode 100644
index 0000000..0a6cdbb
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml
@@ -0,0 +1,51 @@
+<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'/>
+      <protocol type='raw'/>
+      <secret type='passphrase' usage='mycluster_myname'/>
+      <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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 3064458..cef459e 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -484,6 +484,7 @@ mymain(void)
     DO_TEST("serial-udp");
     DO_TEST("serial-tcp-telnet");
     DO_TEST("serial-tcp-tlsx509-chardev");
+    DO_TEST("serial-tcp-tlsx509-secret-chardev");
     DO_TEST("serial-many");
     DO_TEST("serial-spiceport");
     DO_TEST("serial-spiceport-nospice");
-- 
2.5.5




More information about the libvir-list mailing list