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='tls' usage='tlsexample'/>
Signed-off-by: John Ferlan <jferlan(a)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 | 51 ++++++++++++++++++++++
...ml2xmlout-serial-tcp-tlsx509-secret-chardev.xml | 1 +
tests/qemuxml2xmltest.c | 1 +
7 files changed, 141 insertions(+)
create mode 100644
tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml
create mode 120000
tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index fa88839..b1d9741 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6097,6 +6097,35 @@ qemu-kvm -net nic,model=? /dev/null
</devices>
...</pre>
+ <p>
+ <span class="since">Since 2.2.0,</span> some hypervisors
support using
+ a TLS X.509 certificate environment in order to encrypt the TCP
+ connection. 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 cb9f134..5702e3b 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3264,6 +3264,9 @@
<ref name="qemucdevTgtDef"/>
</optional>
<optional>
+ <ref name="qemucdevSecret"/>
+ </optional>
+ <optional>
<ref name="alias"/>
</optional>
<optional>
@@ -3315,6 +3318,24 @@
</element>
</define>
+ <define name="qemucdevSecret">
+ <element name='secret'>
+ <attribute name='type'>
+ <choice>
+ <value>tls</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 e58046b..53e5bae 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1899,6 +1899,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:
@@ -1955,6 +1956,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:
@@ -9867,6 +9872,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) {
@@ -9956,6 +9963,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++;
}
@@ -10059,6 +10068,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_TLS) {
+ 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:
@@ -10133,6 +10161,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
VIR_FREE(append);
VIR_FREE(logappend);
VIR_FREE(logfile);
+ VIR_FREE(sectypestr);
return remaining;
@@ -21157,6 +21186,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, "<protocol type='%s'/>\n",
virDomainChrTcpProtocolTypeToString(
def->data.tcp.protocol));
+ if (def->data.tcp.sectype == VIR_SECRET_USAGE_TYPE_TLS) {
+ 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 b25e219..0b48b8e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -53,6 +53,7 @@
# include "virprocess.h"
# include "virgic.h"
# include "virperf.h"
+# include "virsecret.h"
# include "virtypedparam.h"
/* forward declarations of all device types, required by
@@ -1092,6 +1093,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..62bc151
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-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='tls' 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/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml
new file mode 120000
index 0000000..974d3fb
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-secret-chardev.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 85241b9..67e5857 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -541,6 +541,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.7.4