[libvirt] [PATCH 1/6] docs: split TLS certificate setup into its own file

Daniel P. Berrangé berrange at redhat.com
Fri Nov 8 11:21:07 UTC 2019


The generation and deployment of x509 certificates for TLS is complex
and verbose and thus deserves its own standalone page.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 docs/docs.html.in     |   3 +
 docs/remote.html.in   | 408 +----------------------------------------
 docs/tlscerts.html.in | 413 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 417 insertions(+), 407 deletions(-)
 create mode 100644 docs/tlscerts.html.in

diff --git a/docs/docs.html.in b/docs/docs.html.in
index 6cf09f51bc..4b59162e0f 100644
--- a/docs/docs.html.in
+++ b/docs/docs.html.in
@@ -18,6 +18,9 @@
         <dt><a href="remote.html">Remote access</a></dt>
         <dd>Enable remote access over TCP</dd>
 
+        <dt><a href="tlscerts.html">TLS certs</a></dt>
+        <dd>Generate and deploy x509 certificates for TLS</dd>
+
         <dt><a href="auth.html">Authentication</a></dt>
         <dd>Configure authentication for the libvirt daemon</dd>
 
diff --git a/docs/remote.html.in b/docs/remote.html.in
index 78e071a898..5a0ebe4790 100644
--- a/docs/remote.html.in
+++ b/docs/remote.html.in
@@ -61,7 +61,7 @@ Remote libvirt supports a range of transports:
       <dd><a href="http://en.wikipedia.org/wiki/Transport_Layer_Security" title="Transport Layer Security">TLS</a>
  1.0 (SSL 3.1) authenticated and encrypted TCP/IP socket, usually
  listening on a public port number.  To use this you will need to
- <a href="#Remote_certificates" title="Generating TLS certificates">generate client and
+ <a href="tlscerts.html" title="Generating TLS certificates">generate client and
  server certificates</a>.
  The standard port is 16514.
  </dd>
@@ -382,412 +382,6 @@ Note that parameter values must be
         <td> Example: <code>sshauth=privkey,agent</code> </td>
       </tr>
     </table>
-    <h2>
-      <a id="Remote_certificates">Generating TLS certificates</a>
-    </h2>
-    <h3>
-      <a id="Remote_PKI">Public Key Infrastructure set up</a>
-    </h3>
-    <p>
-If you are unsure how to create TLS certificates, skip to the
-next section.
-</p>
-    <table class="top_table">
-      <tr>
-        <th> Location </th>
-        <th> Machine </th>
-        <th> Description </th>
-        <th> Required fields </th>
-      </tr>
-      <tr>
-        <td>
-          <code>/etc/pki/CA/cacert.pem</code>
-        </td>
-        <td> Installed on the client and server </td>
-        <td> CA's certificate (<a href="#Remote_TLS_CA">more info</a>)</td>
-        <td> n/a </td>
-      </tr>
-      <tr>
-        <td>
-          <code>$HOME/.pki/cacert.pem</code>
-        </td>
-        <td> Installed on the client </td>
-        <td> CA's certificate (<a href="#Remote_TLS_CA">more info</a>)</td>
-        <td> n/a </td>
-      </tr>
-      <tr>
-        <td>
-          <code>/etc/pki/libvirt/private/serverkey.pem</code>
-        </td>
-        <td> Installed on the server </td>
-        <td> Server's private key (<a href="#Remote_TLS_server_certificates">more info</a>)</td>
-        <td> n/a </td>
-      </tr>
-      <tr>
-        <td>
-          <code>/etc/pki/libvirt/servercert.pem</code>
-        </td>
-        <td> Installed on the server </td>
-        <td> Server's certificate signed by the CA.
- (<a href="#Remote_TLS_server_certificates">more info</a>) </td>
-        <td> CommonName (CN) must be the hostname of the server as it
-          is seen by clients. All hostname and IP address variants that might
-          be used to reach the server should be listed in Subject Alt Name
-          fields.</td>
-      </tr>
-      <tr>
-        <td>
-          <code>/etc/pki/libvirt/private/clientkey.pem</code>
-        </td>
-        <td> Installed on the client </td>
-        <td> Client's private key. (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
-        <td> n/a </td>
-      </tr>
-      <tr>
-        <td>
-          <code>/etc/pki/libvirt/clientcert.pem</code>
-        </td>
-        <td> Installed on the client </td>
-        <td> Client's certificate signed by the CA
-  (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
-        <td> Distinguished Name (DN) can be checked against an access
-  control list (<code>tls_allowed_dn_list</code>).
-  </td>
-      </tr>
-      <tr>
-        <td>
-          <code>$HOME/.pki/libvirt/clientkey.pem</code>
-        </td>
-        <td> Installed on the client </td>
-        <td> Client's private key. (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
-        <td> n/a </td>
-      </tr>
-      <tr>
-        <td>
-          <code>$HOME/.pki/libvirt/clientcert.pem</code>
-        </td>
-        <td> Installed on the client </td>
-        <td> Client's certificate signed by the CA
-  (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
-        <td> Distinguished Name (DN) can be checked against an access
-  control list (<code>tls_allowed_dn_list</code>).
-  </td>
-      </tr>
-    </table>
-    <p>
-      If 'pkipath' is specified in URI, then all the client
-      certificates must be found in the path specified, otherwise the
-      connection will fail with a fatal error. If 'pkipath' is not
-      specified:
-    </p>
-    <ul>
-      <li> For a non-root user, libvirt tries to find the certificates
-        in $HOME/.pki/libvirt first. If the required CA certificate cannot
-        be found, then the global default location
-        (/etc/pki/CA/cacert.pem) will be used.
-        Likewise, if either the client certificate
-        or the client key cannot be found, then the global default
-        locations (/etc/pki/libvirt/clientcert.pem,
-        /etc/pki/libvirt/private/clientkey.pem) will be used.
-      </li>
-      <li> For the root user, the global default locations will always be used.</li>
-    </ul>
-    <h3>
-      <a id="Remote_TLS_background">Background to TLS certificates</a>
-    </h3>
-    <p>
-Libvirt supports TLS certificates for verifying the identity
-of the server and clients.  There are two distinct checks involved:
-</p>
-    <ul>
-      <li> The client should know that it is connecting to the right
-server.  Checking done by client by matching the certificate that
-the server sends to the server's hostname.  May be disabled by adding
-<code>?no_verify=1</code> to the
-<a href="#Remote_URI_parameters">remote URI</a>.
-</li>
-      <li> The server should know that only permitted clients are
-connecting.  This can be done based on client's IP address, or on
-client's IP address and client's certificate.  Checking done by the
-server.  May be enabled and disabled in the <a href="#Remote_libvirtd_configuration">libvirtd.conf file</a>.
-</li>
-    </ul>
-    <p>
-For full certificate checking you will need to have certificates
-issued by a recognised <a href="http://en.wikipedia.org/wiki/Certificate_authority">Certificate
-Authority (CA)</a> for your server(s) and all clients.  To avoid the
-expense of getting certificates from a commercial CA, you can set up
-your own CA and tell your server(s) and clients to trust certificates
-issues by your own CA.  Follow the instructions in the next section.
-</p>
-    <p>
-Be aware that the <a href="#Remote_libvirtd_configuration">default
-configuration for libvirtd</a> allows any client to connect provided
-they have a valid certificate issued by the CA for their own IP
-address.  You may want to change this to make it less (or more)
-permissive, depending on your needs.
-</p>
-    <h3>
-      <a id="Remote_TLS_CA">Setting up a Certificate Authority (CA)</a>
-    </h3>
-    <p>
-You will need the <a href="http://www.gnu.org/software/gnutls/manual/html_node/Invoking-certtool.html">GnuTLS
-certtool program documented here</a>.  In Fedora, it is in the
-<code>gnutls-utils</code> package.
-</p>
-    <p>
-Create a private key for your CA:
-</p>
-    <pre>
-certtool --generate-privkey > cakey.pem
-</pre>
-    <p>
-and self-sign it by creating a file with the
-signature details called
-<code>ca.info</code> containing:
-</p>
-    <pre>
-cn = <i>Name of your organization</i>
-ca
-cert_signing_key
-</pre>
-    <pre>
-certtool --generate-self-signed --load-privkey cakey.pem \
-  --template ca.info --outfile cacert.pem
-</pre>
-    <p>
-(You can delete <code>ca.info</code> file now if you
-want).
-</p>
-    <p>
-Now you have two files which matter:
-</p>
-    <ul>
-      <li><code>cakey.pem</code> - Your CA's private key (keep this very secret!)
-</li>
-      <li><code>cacert.pem</code> - Your CA's certificate (this is public).
-</li>
-    </ul>
-    <p><code>cacert.pem</code> has to be installed on clients and
-server(s) to let them know that they can trust certificates issued by
-your CA.
-</p>
-    <p>
-The normal installation directory for <code>cacert.pem</code>
-is <code>/etc/pki/CA/cacert.pem</code> on all clients and servers.
-</p>
-    <p>
-To see the contents of this file, do:
-</p>
-    <pre><b>certtool -i --infile cacert.pem</b>
-
-X.509 certificate info:
-
-Version: 3
-Serial Number (hex): 00
-Subject: CN=Libvirt Project
-Issuer: CN=Libvirt Project
-Signature Algorithm: RSA-SHA
-Validity:
-        Not Before: Mon Jun 18 16:22:18 2007
-        Not After: Tue Jun 17 16:22:18 2008
-<i>[etc]</i>
-</pre>
-    <p>
-This is all that is required to set up your CA.  Keep the CA's private
-key carefully as you will need it when you come to issue certificates
-for your clients and servers.
-</p>
-    <h3>
-      <a id="Remote_TLS_server_certificates">Issuing server certificates</a>
-    </h3>
-    <p>
-For each server (libvirtd) you need to issue a certificate
-containing one or more hostnames and/or IP addresses.
-Historically the CommonName (CN) field would contain the
-hostname of the server and would match the hostname used
-in the URI that clients pass to libvirt. In most TLS implementations
-the CN field is considered legacy data. The preferential mechanism
-is to use Subject Alt Name (SAN) extension fields to validate
-against. In the future use of the CN field for validation may be
-discontinued entirely, so it is strongly recommended to
-include the SAN fields.
-</p>
-    <p>
-In the example below, clients will be connecting to the
-server using a <a href="#Remote_URI_reference">URI</a> of
-<code>qemu://compute1.libvirt.org/system</code>, so the CN
-must be "<code>compute1.libvirt.org</code>".
-</p>
-    <p>
-Make a private key for the server:
-</p>
-    <pre>
-certtool --generate-privkey > serverkey.pem
-</pre>
-    <p>
-and sign that key with the CA's private key by first
-creating a template file called <code>server.info</code>.
-The template file will contain a number of fields to define
-the server as follows:
-</p>
-    <pre>
-organization = <i>Name of your organization</i>
-cn = compute1.libvirt.org
-dns_name = compute1
-dns_name = compute1.libvirt.org
-ip_address = 10.0.0.74
-ip_address = 192.168.1.24
-ip_address = 2001:cafe::74
-ip_address = fe20::24
-tls_www_server
-encryption_key
-signing_key
-</pre>
-<p>
-The 'cn' field should refer to the fully qualified public
-hostname of the server. For the SAN extension data, there
-must also be one or more 'dns_name' fields that contain all
-possible hostnames that can be reasonably used by clients
-to reach the server, both with and without domain name
-qualifiers. If clients are likely to connect to the server
-by IP address, then one or more 'ip_address' fields should
-also be added.
-</p>
-    <p>
-Use the template file as input to a <code>certtool</code>
-command to sign the server certificate:
-</p>
-    <pre>
-certtool --generate-certificate --load-privkey serverkey.pem \
-  --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem \
-  --template server.info --outfile servercert.pem
-</pre>
-    <p>
-This gives two files:
-</p>
-    <ul>
-      <li><code>serverkey.pem</code> - The server's private key.
-</li>
-      <li><code>servercert.pem</code> - The server's public key.
-</li>
-    </ul>
-    <p>
-We can examine this certificate and its signature:
-</p>
-    <pre><b>certtool -i --infile servercert.pem</b>
-X.509 certificate info:
-
-Version: 3
-Serial Number (hex): 00
-Subject: O=Libvirt Project,CN=compute1.libvirt.org
-Issuer: CN=Libvirt Project
-Signature Algorithm: RSA-SHA
-Validity:
-        Not Before: Wed Oct 04 09:09:44 UTC 2017
-        Not After: Thu Oct 04 09:09:44 UTC 2018
-Extensions:
-        Basic Constraints (critical):
-                Certificate Authority (CA): FALSE
-        Subject Alternative Name (not critical):
-                DNSname: compute1
-                DNSname: compute1.libvirt.org
-                IPAddress: 10.0.0.74
-                IPAddress: 192.168.1.24
-                IPAddress: 2001:cafe::74
-                IPAddress: fe20::24
-</pre>
-    <p>
-Note the "Issuer" CN is "Libvirt Project" (the CA) and
-the "Subject" CN is "compute1.libvirt.org" (the server).
-Notice that the hostname listed in the CN must also
-be duplicated as a DNSname entry
-</p>
-    <p>
-Finally we have two files to install:
-</p>
-    <ul>
-      <li><code>serverkey.pem</code> is
-the server's private key which should be copied to the
-server <i>only</i> as
-<code>/etc/pki/libvirt/private/serverkey.pem</code>.
-</li>
-      <li><code>servercert.pem</code> is the server's certificate
-which can be installed on the server as
-<code>/etc/pki/libvirt/servercert.pem</code>.
-</li>
-    </ul>
-    <h3>
-      <a id="Remote_TLS_client_certificates">Issuing client certificates</a>
-    </h3>
-    <p>
-For each client (ie. any program linked with libvirt, such as
-<a href="http://virt-manager.org/">virt-manager</a>)
-you need to issue a certificate with the X.509 Distinguished Name (DN)
-set to a suitable name.  You can decide this on a company / organisation
-policy.  For example:
-</p>
-    <pre>
-C=GB,ST=London,L=London,O=Libvirt Project,CN=<i>name_of_client</i>
-</pre>
-    <p>
-The process is the same as for
-<a href="#Remote_TLS_server_certificates">setting up the
-server certificate</a> so here we just briefly cover the
-steps.
-</p>
-    <ol>
-      <li>
-Make a private key:
-<pre>
-certtool --generate-privkey > clientkey.pem
-</pre>
-</li>
-      <li>
-Act as CA and sign the certificate.  Create client.info containing:
-<pre>
-country = GB
-state = London
-locality = London
-organization = Libvirt Project
-cn = client1
-tls_www_client
-encryption_key
-signing_key
-</pre>
-and sign by doing:
-<pre>
-certtool --generate-certificate --load-privkey clientkey.pem \
-  --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem \
-  --template client.info --outfile clientcert.pem
-</pre>
-</li>
-      <li>
-Install the certificates on the client machine:
-<pre>
-cp clientkey.pem /etc/pki/libvirt/private/clientkey.pem
-cp clientcert.pem /etc/pki/libvirt/clientcert.pem
-</pre>
-</li>
-    </ol>
-    <h3>
-      <a id="Remote_TLS_troubleshooting">Troubleshooting TLS certificate problems</a>
-    </h3>
-    <dl>
-      <dt> failed to verify client's certificate </dt>
-      <dd>
-        <p>
-On the server side, run the libvirtd server with
-the '--listen' and '--verbose' options while the
-client is connecting.  The verbose log messages should
-tell you enough to diagnose the problem.
-</p>
-      </dd>
-    </dl>
-    <p> You can use the virt-pki-validate shell script
-to analyze the setup on the client or server machines, preferably as root.
-It will try to point out the possible problems and provide solutions to
-fix the set up up to a point where you have secure remote access.</p>
     <h2>
       <a id="Remote_libvirtd_configuration">libvirtd configuration file</a>
     </h2>
diff --git a/docs/tlscerts.html.in b/docs/tlscerts.html.in
new file mode 100644
index 0000000000..3eea686daa
--- /dev/null
+++ b/docs/tlscerts.html.in
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <body>
+    <h1>TLS x509 certificate setup</h1>
+
+    <ul id="toc"></ul>
+
+    <h2>
+      <a id="Remote_PKI">Public Key Infrastructure set up</a>
+    </h2>
+    <p>
+If you are unsure how to create TLS certificates, skip to the
+next section.
+</p>
+    <table class="top_table">
+      <tr>
+        <th> Location </th>
+        <th> Machine </th>
+        <th> Description </th>
+        <th> Required fields </th>
+      </tr>
+      <tr>
+        <td>
+          <code>/etc/pki/CA/cacert.pem</code>
+        </td>
+        <td> Installed on the client and server </td>
+        <td> CA's certificate (<a href="#Remote_TLS_CA">more info</a>)</td>
+        <td> n/a </td>
+      </tr>
+      <tr>
+        <td>
+          <code>$HOME/.pki/cacert.pem</code>
+        </td>
+        <td> Installed on the client </td>
+        <td> CA's certificate (<a href="#Remote_TLS_CA">more info</a>)</td>
+        <td> n/a </td>
+      </tr>
+      <tr>
+        <td>
+          <code>/etc/pki/libvirt/private/serverkey.pem</code>
+        </td>
+        <td> Installed on the server </td>
+        <td> Server's private key (<a href="#Remote_TLS_server_certificates">more info</a>)</td>
+        <td> n/a </td>
+      </tr>
+      <tr>
+        <td>
+          <code>/etc/pki/libvirt/servercert.pem</code>
+        </td>
+        <td> Installed on the server </td>
+        <td> Server's certificate signed by the CA.
+ (<a href="#Remote_TLS_server_certificates">more info</a>) </td>
+        <td> CommonName (CN) must be the hostname of the server as it
+          is seen by clients. All hostname and IP address variants that might
+          be used to reach the server should be listed in Subject Alt Name
+          fields.</td>
+      </tr>
+      <tr>
+        <td>
+          <code>/etc/pki/libvirt/private/clientkey.pem</code>
+        </td>
+        <td> Installed on the client </td>
+        <td> Client's private key. (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
+        <td> n/a </td>
+      </tr>
+      <tr>
+        <td>
+          <code>/etc/pki/libvirt/clientcert.pem</code>
+        </td>
+        <td> Installed on the client </td>
+        <td> Client's certificate signed by the CA
+  (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
+        <td> Distinguished Name (DN) can be checked against an access
+  control list (<code>tls_allowed_dn_list</code>).
+  </td>
+      </tr>
+      <tr>
+        <td>
+          <code>$HOME/.pki/libvirt/clientkey.pem</code>
+        </td>
+        <td> Installed on the client </td>
+        <td> Client's private key. (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
+        <td> n/a </td>
+      </tr>
+      <tr>
+        <td>
+          <code>$HOME/.pki/libvirt/clientcert.pem</code>
+        </td>
+        <td> Installed on the client </td>
+        <td> Client's certificate signed by the CA
+  (<a href="#Remote_TLS_client_certificates">more info</a>) </td>
+        <td> Distinguished Name (DN) can be checked against an access
+  control list (<code>tls_allowed_dn_list</code>).
+  </td>
+      </tr>
+    </table>
+    <p>
+      If 'pkipath' is specified in URI, then all the client
+      certificates must be found in the path specified, otherwise the
+      connection will fail with a fatal error. If 'pkipath' is not
+      specified:
+    </p>
+    <ul>
+      <li> For a non-root user, libvirt tries to find the certificates
+        in $HOME/.pki/libvirt first. If the required CA certificate cannot
+        be found, then the global default location
+        (/etc/pki/CA/cacert.pem) will be used.
+        Likewise, if either the client certificate
+        or the client key cannot be found, then the global default
+        locations (/etc/pki/libvirt/clientcert.pem,
+        /etc/pki/libvirt/private/clientkey.pem) will be used.
+      </li>
+      <li> For the root user, the global default locations will always be used.</li>
+    </ul>
+    <h2>
+      <a id="Remote_TLS_background">Background to TLS certificates</a>
+    </h2>
+    <p>
+Libvirt supports TLS certificates for verifying the identity
+of the server and clients.  There are two distinct checks involved:
+</p>
+    <ul>
+      <li> The client should know that it is connecting to the right
+server.  Checking done by client by matching the certificate that
+the server sends to the server's hostname.  May be disabled by adding
+<code>?no_verify=1</code> to the
+<a href="#Remote_URI_parameters">remote URI</a>.
+</li>
+      <li> The server should know that only permitted clients are
+connecting.  This can be done based on client's IP address, or on
+client's IP address and client's certificate.  Checking done by the
+server.  May be enabled and disabled in the <a href="#Remote_libvirtd_configuration">libvirtd.conf file</a>.
+</li>
+    </ul>
+    <p>
+For full certificate checking you will need to have certificates
+issued by a recognised <a href="http://en.wikipedia.org/wiki/Certificate_authority">Certificate
+Authority (CA)</a> for your server(s) and all clients.  To avoid the
+expense of getting certificates from a commercial CA, you can set up
+your own CA and tell your server(s) and clients to trust certificates
+issues by your own CA.  Follow the instructions in the next section.
+</p>
+    <p>
+Be aware that the <a href="#Remote_libvirtd_configuration">default
+configuration for libvirtd</a> allows any client to connect provided
+they have a valid certificate issued by the CA for their own IP
+address.  You may want to change this to make it less (or more)
+permissive, depending on your needs.
+</p>
+    <h2>
+      <a id="Remote_TLS_CA">Setting up a Certificate Authority (CA)</a>
+    </h2>
+    <p>
+You will need the <a href="http://www.gnu.org/software/gnutls/manual/html_node/Invoking-certtool.html">GnuTLS
+certtool program documented here</a>.  In Fedora, it is in the
+<code>gnutls-utils</code> package.
+</p>
+    <p>
+Create a private key for your CA:
+</p>
+    <pre>
+certtool --generate-privkey > cakey.pem
+</pre>
+    <p>
+and self-sign it by creating a file with the
+signature details called
+<code>ca.info</code> containing:
+</p>
+    <pre>
+cn = <i>Name of your organization</i>
+ca
+cert_signing_key
+</pre>
+    <pre>
+certtool --generate-self-signed --load-privkey cakey.pem \
+  --template ca.info --outfile cacert.pem
+</pre>
+    <p>
+(You can delete <code>ca.info</code> file now if you
+want).
+</p>
+    <p>
+Now you have two files which matter:
+</p>
+    <ul>
+      <li><code>cakey.pem</code> - Your CA's private key (keep this very secret!)
+</li>
+      <li><code>cacert.pem</code> - Your CA's certificate (this is public).
+</li>
+    </ul>
+    <p><code>cacert.pem</code> has to be installed on clients and
+server(s) to let them know that they can trust certificates issued by
+your CA.
+</p>
+    <p>
+The normal installation directory for <code>cacert.pem</code>
+is <code>/etc/pki/CA/cacert.pem</code> on all clients and servers.
+</p>
+    <p>
+To see the contents of this file, do:
+</p>
+    <pre><b>certtool -i --infile cacert.pem</b>
+
+X.509 certificate info:
+
+Version: 3
+Serial Number (hex): 00
+Subject: CN=Libvirt Project
+Issuer: CN=Libvirt Project
+Signature Algorithm: RSA-SHA
+Validity:
+        Not Before: Mon Jun 18 16:22:18 2007
+        Not After: Tue Jun 17 16:22:18 2008
+<i>[etc]</i>
+</pre>
+    <p>
+This is all that is required to set up your CA.  Keep the CA's private
+key carefully as you will need it when you come to issue certificates
+for your clients and servers.
+</p>
+    <h2>
+      <a id="Remote_TLS_server_certificates">Issuing server certificates</a>
+    </h2>
+    <p>
+For each server (libvirtd) you need to issue a certificate
+containing one or more hostnames and/or IP addresses.
+Historically the CommonName (CN) field would contain the
+hostname of the server and would match the hostname used
+in the URI that clients pass to libvirt. In most TLS implementations
+the CN field is considered legacy data. The preferential mechanism
+is to use Subject Alt Name (SAN) extension fields to validate
+against. In the future use of the CN field for validation may be
+discontinued entirely, so it is strongly recommended to
+include the SAN fields.
+</p>
+    <p>
+In the example below, clients will be connecting to the
+server using a <a href="#Remote_URI_reference">URI</a> of
+<code>qemu://compute1.libvirt.org/system</code>, so the CN
+must be "<code>compute1.libvirt.org</code>".
+</p>
+    <p>
+Make a private key for the server:
+</p>
+    <pre>
+certtool --generate-privkey > serverkey.pem
+</pre>
+    <p>
+and sign that key with the CA's private key by first
+creating a template file called <code>server.info</code>.
+The template file will contain a number of fields to define
+the server as follows:
+</p>
+    <pre>
+organization = <i>Name of your organization</i>
+cn = compute1.libvirt.org
+dns_name = compute1
+dns_name = compute1.libvirt.org
+ip_address = 10.0.0.74
+ip_address = 192.168.1.24
+ip_address = 2001:cafe::74
+ip_address = fe20::24
+tls_www_server
+encryption_key
+signing_key
+</pre>
+<p>
+The 'cn' field should refer to the fully qualified public
+hostname of the server. For the SAN extension data, there
+must also be one or more 'dns_name' fields that contain all
+possible hostnames that can be reasonably used by clients
+to reach the server, both with and without domain name
+qualifiers. If clients are likely to connect to the server
+by IP address, then one or more 'ip_address' fields should
+also be added.
+</p>
+    <p>
+Use the template file as input to a <code>certtool</code>
+command to sign the server certificate:
+</p>
+    <pre>
+certtool --generate-certificate --load-privkey serverkey.pem \
+  --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem \
+  --template server.info --outfile servercert.pem
+</pre>
+    <p>
+This gives two files:
+</p>
+    <ul>
+      <li><code>serverkey.pem</code> - The server's private key.
+</li>
+      <li><code>servercert.pem</code> - The server's public key.
+</li>
+    </ul>
+    <p>
+We can examine this certificate and its signature:
+</p>
+    <pre><b>certtool -i --infile servercert.pem</b>
+X.509 certificate info:
+
+Version: 3
+Serial Number (hex): 00
+Subject: O=Libvirt Project,CN=compute1.libvirt.org
+Issuer: CN=Libvirt Project
+Signature Algorithm: RSA-SHA
+Validity:
+        Not Before: Wed Oct 04 09:09:44 UTC 2017
+        Not After: Thu Oct 04 09:09:44 UTC 2018
+Extensions:
+        Basic Constraints (critical):
+                Certificate Authority (CA): FALSE
+        Subject Alternative Name (not critical):
+                DNSname: compute1
+                DNSname: compute1.libvirt.org
+                IPAddress: 10.0.0.74
+                IPAddress: 192.168.1.24
+                IPAddress: 2001:cafe::74
+                IPAddress: fe20::24
+</pre>
+    <p>
+Note the "Issuer" CN is "Libvirt Project" (the CA) and
+the "Subject" CN is "compute1.libvirt.org" (the server).
+Notice that the hostname listed in the CN must also
+be duplicated as a DNSname entry
+</p>
+    <p>
+Finally we have two files to install:
+</p>
+    <ul>
+      <li><code>serverkey.pem</code> is
+the server's private key which should be copied to the
+server <i>only</i> as
+<code>/etc/pki/libvirt/private/serverkey.pem</code>.
+</li>
+      <li><code>servercert.pem</code> is the server's certificate
+which can be installed on the server as
+<code>/etc/pki/libvirt/servercert.pem</code>.
+</li>
+    </ul>
+    <h2>
+      <a id="Remote_TLS_client_certificates">Issuing client certificates</a>
+    </h2>
+    <p>
+For each client (ie. any program linked with libvirt, such as
+<a href="http://virt-manager.org/">virt-manager</a>)
+you need to issue a certificate with the X.509 Distinguished Name (DN)
+set to a suitable name.  You can decide this on a company / organisation
+policy.  For example:
+</p>
+    <pre>
+C=GB,ST=London,L=London,O=Libvirt Project,CN=<i>name_of_client</i>
+</pre>
+    <p>
+The process is the same as for
+<a href="#Remote_TLS_server_certificates">setting up the
+server certificate</a> so here we just briefly cover the
+steps.
+</p>
+    <ol>
+      <li>
+Make a private key:
+<pre>
+certtool --generate-privkey > clientkey.pem
+</pre>
+</li>
+      <li>
+Act as CA and sign the certificate.  Create client.info containing:
+<pre>
+country = GB
+state = London
+locality = London
+organization = Libvirt Project
+cn = client1
+tls_www_client
+encryption_key
+signing_key
+</pre>
+and sign by doing:
+<pre>
+certtool --generate-certificate --load-privkey clientkey.pem \
+  --load-ca-certificate cacert.pem --load-ca-privkey cakey.pem \
+  --template client.info --outfile clientcert.pem
+</pre>
+</li>
+      <li>
+Install the certificates on the client machine:
+<pre>
+cp clientkey.pem /etc/pki/libvirt/private/clientkey.pem
+cp clientcert.pem /etc/pki/libvirt/clientcert.pem
+</pre>
+</li>
+    </ol>
+    <h2>
+      <a id="Remote_TLS_troubleshooting">Troubleshooting TLS certificate problems</a>
+    </h2>
+    <dl>
+      <dt> failed to verify client's certificate </dt>
+      <dd>
+        <p>
+On the server side, run the libvirtd server with
+the '--listen' and '--verbose' options while the
+client is connecting.  The verbose log messages should
+tell you enough to diagnose the problem.
+</p>
+      </dd>
+    </dl>
+    <p> You can use the virt-pki-validate shell script
+to analyze the setup on the client or server machines, preferably as root.
+It will try to point out the possible problems and provide solutions to
+fix the set up up to a point where you have secure remote access.</p>
+  </body>
+</html>
-- 
2.23.0




More information about the libvir-list mailing list