首页 > 代码库 > Setting up libvirt for TLS (Encryption & Authentication)
Setting up libvirt for TLS (Encryption & Authentication)
Setting up libvirt for TLS (Encryption & Authentication)
Setting up your virtualisation infrastructure for Transport Layer Security (TLS) isn‘t very difficult. However, it can be a bit involved for someone not already familiar with the details.
These next pages take you through the four main steps involved with setting up TLS for libvirt, from the high level concepts, through to the exact steps with examples.
You should be able to follow through, adapting the examples directly for your own virtualisation infrastructure.
The central concept
At its heart, Transport Layer Security is a way of encrypting communication between two computers. The encryption is done using an approach called PKI, which stands for Public Key Infrastructure.
核心内容是,传输层安全是计算机之间加密通讯的一种方式。被叫做PKI的基于公共密钥设施被用做加密的方法。
It is fairly simple in concept, always involving one computer, "the client", establishing a connection with a receiving computer, "the server".
这在概念上相当简单,总是涉及到计算机"the client"与接收机"the server"建立连接。
TLS uses files called Certificates for this communication, with the client computer starting the connection always having a Client Certificate, and the receiving computer always having a Server Certificate.
TLS将证书文件应用于通信过程,发起连接的客户端“始终”拥有“客户端证书”,接收端,“始终”拥有“服务端证书”。
If you have the situation where two computers need to communicate with each other using TLS, then they both need a Client Certificate and a Server Certificate.
如果两台计算机之间互相使用TLS,那么两台机器上都需要有“服务端证书”和“客户端证书”。
This is also the example scenario we‘ll be using in these pages.
Our example scenario
In our example scenario, we have two virtualisation host servers. The first, Host System 1, is named host1. The second, Host System 2, is named host2.
在我们的示例方案中,有两台虚拟主机服务器。第一个主机Host System 1简称host1,第二个主机Host System 2简称host2。
In our example environment, these host servers will occasionally need to communicate with each other. For example, when moving a virtualised guest from host1 to host2, or vice versa. For this to work, they both need their own Client Certificate, and Server Certificate.
在我们的示例环境中,这些服务器偶尔需要互相通信。例如,从host1移动虚拟guest主机到host2,反之亦然。在这种情况,它们都需要客户端证书和服务端证书。
In our example scenario, we also have an administrative desktop used to manage the virtualisation hosts. With it we can connect to either of the virtualisation hosts and perform administrative functions like creating new guests, moving guests between the hosts, and reconfiguring or deleting guests.
在我们的示例方案中,也有用于管理虚拟化主机的管理桌面。我们可以连接任意一个虚拟化主机并在两个主机间执行创建、移动guest的管理操作,也能重新配置或删除guest。
This administrative desktop is named admindesktop. It will exclusively connect to the virtualisation hosts, never receiving new connections from them. This means it only needs a Client Certificate, and does not need it‘s own Server Certificate.
管理桌面叫做admindesktop。它跟虚拟化主机建立独占的连接,不再接受其他主机发起的新的连接。这意味着仅需要客户端证书,不需要服务端证书。
Private Key files
Part of the PKI approach used in TLS, means that for every Certificate file a computer wants to use fully, it must also have a matching Private Key file.
Private Key files are critically important, and must be kept very secure. They allow any computer with a matching certificate to represent itself as what is in the certificate.
私钥文件极其重要,必须保证非常安全。
For example, Host System 1 has both Client and Server Certificates. These certificates contain information stating they are for the system host1.
比如,Host System 1拥有客户端证书和服务端证书。这些证书包含了它们是用于host1的信息说明。
Because only Host System 1 has the private key files for these certificates, it is the only one that can say "I am host1".
因为只有Host System 1拥有这些证书的私钥文件,表明"I am host1"。
If an unauthorised person was to obtain one of these key files, they could make their own certificates claiming one of their systems is host1 instead. This could potentially give them access to your virtualisation servers, which is not what you want.
如果有人未经授权拿到了密钥文件,就能用他们自己的证书声明他们的系统替代了 host1。
Signing other Certificates
Possessing both a Certificate and its Private Key also gives an additional benefit, being able to sign other Certificates. This adds a small, cryptographically secure piece of information to the certificate file being signed, indicating it is authentic.
This is important, because it allows us to establish a web of trust, where we have all of our certificates signed either by each other, or by a central certificate we know to be good.
Certificate Authority
This approach, of having a central certificate to sign many others is regarded as good security practice. It also allows for reasonably simple certificate management when compared to other alternatives, and is the approach used in libvirt.
This central Certificate is referred to as a Certificate Authority Certificate. We create one in the very first step of our TLS set up on the next page, then use it for signing every Client and Server Certificate we create.
Steps to create a TLS Certificate Authority Certificate file for libvirt
The very first step in setting up libvirt for TLS is creating a central Certificate Authority Certificate, used for signing every other certificate we create.
Follow these instructions to create this Certificate Authority Certificate, then continue on with the next pages for the rest of the libvirt TLS set up.
Create a Certificate Authority Template file using a text editor
This is a plain text file, with the following fields:
cn = Name of your organization ca cert_signing_key
The Name of your organization value should be adjusted to suit your organisation.
For example:
# cat certificate_authority_template.info cn = libvirt.org ca cert_signing_key
Note that by default, the CA certificate created is valid for only 1 year.
This can be changed by including the field "expiration_days" in the template file before generating the certificate:
cn = Name of your organization ca cert_signing_key expiration_days = 700
Create a Certificate Authority Private Key file using certtool
Generate a private key, to be used with the Certificate Authority Certificate.
This key is used create your Certificate Authority Certificate, and to sign the individual client and server TLS certificates.
# (umask 277 && certtool --generate-privkey > certificate_authority_key.pem) Generating a 2048 bit RSA private key...
# ls -la certificate_authority_key.pem -r--------. 1 root root 1675 Aug 25 04:37 certificate_authority_key.pem
NOTE - The security of this private key is extremely important.
If an unauthorised person obtains this key, it can be used with the CA certificate to sign any other certificate, including certificates they generate. Such bogus certificates could potentially allow them to perform administrative commands on your virtualized guests.
Combine the template file with the private key file to create the Certificate Authority Certificate file
Generate the CA Certificate using the template file, along with the CA private key:
# certtool --generate-self-signed --template certificate_authority_template.info --load-privkey certificate_authority_key.pem --outfile certificate_authority_certificate.pem Generating a self signed certificate... X.509 Certificate Information: Version: 3 Serial Number (hex): 4c741265 Validity: Not Before: Tue Aug 24 18:41:41 UTC 2010 Not After: Wed Aug 24 18:41:41 UTC 2011 Subject: CN=libvirt.org Subject Public Key Algorithm: RSA Modulus (bits 2048): d8:77:8b:59:97:7f:cc:cf:ff:71:4b:e6:ec:b2:0c:90 3d:42:5b:1c:fc:4a:44:b8:25:78:3b:e0:58:17:ae:7c a7:5c:08:98:6b:47:57:ba:b5:b4:89:73:8a:41:ec:f4 6b:10:ed:ee:3f:41:b7:89:33:4f:a4:37:a7:ee:3b:73 2b:9f:6f:26:75:99:62:90:48:84:be:e1:de:61:25:bd cc:7c:92:eb:c1:da:69:a7:9a:ae:38:95:e7:7c:64:a0 d5:9f:e3:3a:35:ae:1c:da:1e:87:a4:62:36:37:e1:11 96:e9:98:16:b8:72:82:30:dc:92:ac:16:e1:0a:af:da 34:d8:d0:aa:73:f7:7e:05:53:bc:ef:c6:d7:cb:a5:97 ec:b5:af:f9:7c:34:cb:cf:e7:b0:ce:fa:bf:ca:60:ea 4f:91:56:6c:a9:4f:f8:4a:45:20:c6:35:1b:68:02:9b cc:9a:5f:d0:8a:62:de:ba:00:37:74:63:b2:a2:2c:e5 30:6b:69:ae:b2:30:be:39:09:1b:bb:6d:37:1c:a2:70 07:42:72:0e:35:5f:1e:c9:27:86:e8:b6:03:24:2c:e1 30:c3:94:60:6b:8b:ac:fa:fc:79:d8:40:88:1e:91:7f 30:e8:7e:2d:c1:23:41:97:02:57:33:02:30:4f:3d:a3 Exponent (bits 24): 01:00:01 Extensions: Basic Constraints (critical): Certificate Authority (CA): TRUE Key Usage (critical): Certificate signing. Subject Key Identifier (not critical): 9512006c97dbdedbb3232a22cfea6b1341d72d76 Other Information: Public Key Id: 9512006c97dbdedbb3232a22cfea6b1341d72d76 Signing certificate...
# ls -la certificate_authority_certificate.pem -rw-r--r--. 1 root root 1070 Aug 25 04:41 certificate_authority_certificate.pem
The name of the CA Certificate file is certificate_authority_certificate.pem.
This file is not as security sensitive as the private key file. It will be copied to each virtualisation host and administrative computer later in the TLS setup process.
Note the period of time the certificate is valid for, displayed by the range Not Before to Not After. If you included the "expiration_days" field in your template file, please ensure the range displayed is what you want.
The template file is no longer needed, so can be discarded
# rm certificate_authority_template.info
Moving the Certificate into place
Now the Certificate has been created, it needs to be copied to both virtualisation hosts and the administration desktop.
The default location for the Certificate file on each host is /etc/pki/CA/cacert.pem.
Note - The security of the Private Key file is very important. It should NOT be copied to the other computers along with the Certificate.
Ownership and permissions
Reasonable ownership and permissions for the certificate are for it be owned by root (root:root), be world readable (444), and have an SELinux label of "system_u:object_r:cert_t:s0". The SELinux label is only relevant if the computer the certificate is installed on has SELinux enabled.
You should also take into account your site security practices and requirements, as they may require things to be done differently.
Transferring the certificate and setting it up
In the example below, we use the utility scp to transfer the certificate to each virtualisation client. We then log in directly to each virtualisation client to move the certificate into place and set its permissions accordingly.
Transferring to host1
Notice the filename is being changed in the transfer
# scp -p certificate_authority_certificate.pem someuser@host1:cacert.pem someuser@host1‘s password: certificate_authority_certificate.pem 100% 1164 1.4KB/s 00:00
Logged into host1
We move the certificate into place and set its permissions:
# mv cacert.pem /etc/pki/CA
# chmod 444 /etc/pki/CA/cacert.pem
If the server has SELinux enabled, we also update the SELinux label:
# restorecon /etc/pki/CA/cacert.pem
Transferring the certificate to host2
Notice the filename is being changed in the transfer
# scp -p certificate_authority_certificate.pem someuser@host2:cacert.pem someuser@host2‘s password: certificate_authority_certificate.pem 100% 1164 1.5KB/s 00:00
Logged into host2
We move the certificate into place and set its permissions:
# mv cacert.pem /etc/pki/CA
# chmod 444 /etc/pki/CA/cacert.pem
If the server has SELinux enabled, we also update the SELinux label:
# restorecon /etc/pki/CA/cacert.pem
Transferring the files to the administrative desktop
Notice the filename is being changed in the transfer
# scp -p certificate_authority_certificate.pem someuser@admindesktop:cacert.pem someuser@admindesktop‘s password: certificate_authority_certificate.pem 100% 1164 1.5KB/s 00:00
Logged into the administrative desktop
We move the certificate into place and set its permissions:
# mv cacert.pem /etc/pki/CA
# chmod 444 /etc/pki/CA/cacert.pem
If the desktop has SELinux enabled, we also update the SELinux label:
# restorecon /etc/pki/CA/cacert.pem
The Certificate Authority Certificate setup part is now complete
Creating Transport Layer Security Server Certificates for libvirt
In our example scenario we have two Virtualisation Servers being set up for TLS communication. We also have the Certificate Authority Certificate and its private key created in the previous step.
In this step we create the TLS Server Certificates our hosts need, then move them into place on the hosts.
When these Server Certificates are in place, and with libvirt properly configured, TLS clients will be able to communicate with them.
Create the Server Certificates
This can be done wherever you have both the Certificate Authority Certificate file, and its private key.
We use the utility certtool, from the gnutls-utils package for many parts of this.
Create the Server Certificate Template files using a text editor
These are plain text files, one for each virtualisation host server, containing the following fields:
organization = Name of your organization cn = Host Name tls_www_server encryption_key signing_key
The Name of your organization field should be adjusted to suit your organization, and the Host Name field must be changed to match the host name of the virtualisation host the template is for.
For our example scenario, this gives:
# cat host1_server_template.info organization = libvirt.org cn = host1 tls_www_server encryption_key signing_key
# cat host2_server_template.info organization = libvirt.org cn = host2 tls_www_server encryption_key signing_key
# ls -al *server_template.info -rw-r--r--. 1 root root 82 Aug 25 13:26 host1_server_template.info -rw-r--r--. 1 root root 82 Aug 25 13:26 host2_server_template.info
Create the Server Certificate Private Key files using certtool
Generate the private key files, to be used with the Server Certificates.
These keys are used to create the TLS Server Certificates, and by each virtualisation host when the virtualisation system starts up.
We create a unique private key per virtualisation host, also ensuring the permissions only allow very restricted access to these files:
# (umask 277 && certtool --generate-privkey > host1_server_key.pem) Generating a 2048 bit RSA private key...
# (umask 277 && certtool --generate-privkey > host2_server_key.pem) Generating a 2048 bit RSA private key...
# ls -al *_server_key.pem -r--------. 1 root root 1675 Aug 25 13:33 host1_server_key.pem -r--------. 1 root root 1675 Aug 25 13:33 host2_server_key.pem
NOTE - The security of these private key files is very important.
If an unauthorised person obtains a server private key file, they could use it with a Server Certificate to impersonate one of your virtualisation hosts. Use good unix security to restrict access to the key files appropriately.
Combine the template files with the private key files, to create the Server Certificate files
We generate the Server Certificates using the template files, along with the corresponding private key files. Also, the Certificate Authority Certificate file is added along with its private key, to ensure each new server certificate is signed properly.
For our two virtualisation hosts, this means:
# certtool --generate-certificate --template host1_server_template.info --load-privkey host1_server_key.pem --load-ca-certificate certificate_authority_certificate.pem --load-ca-privkey certificate_authority_key.pem --outfile host1_server_certificate.pem Generating a signed certificate... X.509 Certificate Information: Version: 3 Serial Number (hex): 4c749699 Validity: Not Before: Wed Aug 25 04:05:45 UTC 2010 Not After: Thu Aug 25 04:05:45 UTC 2011 Subject: O=libvirt.org,CN=host1 Subject Public Key Algorithm: RSA Modulus (bits 2048): da:75:bd:37:ac:30:4a:6c:fe:8c:8b:d9:d8:f4:94:80 5e:48:68:31:e7:de:85:d3:d7:54:13:da:8d:d1:f1:21 3b:d9:f1:eb:86:0a:4e:59:39:2c:53:ee:3e:81:29:7d e5:83:6b:bd:e9:86:93:7c:ce:a4:5b:37:b3:b6:6d:7a 7e:60:14:99:4a:23:18:e3:0f:ff:58:68:09:08:f3:0f ca:76:0d:bc:76:e0:8b:38:93:42:f6:8f:b9:d6:4c:21 2a:0e:d9:cd:1c:33:04:36:a3:eb:97:6b:84:bc:88:16 8e:0b:80:46:ed:ce:c5:56:fe:3b:f7:32:a7:91:c3:1f 86:b7:49:77:7b:35:e7:f4:a6:7a:3c:c9:0d:60:fd:b2 b7:e7:d9:02:02:a5:ef:e9:0c:43:14:15:3b:ef:96:52 a6:f9:ca:d5:fc:c0:fb:a0:5a:1f:69:6f:ce:66:0c:fc d5:42:86:85:7e:ab:24:15:3e:5b:a3:85:a1:3b:41:ec 11:7c:6c:3d:14:8b:a5:14:7a:7b:79:15:a0:f6:79:2f 30:a9:a1:6e:8c:5e:3a:97:af:8e:7c:c0:a4:1f:2a:32 8b:4f:6b:53:e4:f0:28:48:db:2b:4c:0d:94:95:56:f0 53:e8:0f:ad:1a:a5:cf:35:e4:e3:0c:a6:ba:85:8a:33 Exponent (bits 24): 01:00:01 Extensions: Basic Constraints (critical): Certificate Authority (CA): FALSE Key Purpose (not critical): TLS WWW Server. Key Usage (critical): Digital signature. Key encipherment. Subject Key Identifier (not critical): 6ddcfcc00a5ffe064a756d2623ea90fa20ff782c Authority Key Identifier (not critical): 9512006c97dbdedbb3232a22cfea6b1341d72d76 Other Information: Public Key Id: 6ddcfcc00a5ffe064a756d2623ea90fa20ff782c Signing certificate...
This will have created the TLS Server Certificate file, host1_server_certificate.pem, for host1:
# ls -la host1_server_certificate.pem -rw-r--r--. 1 root root 1164 Aug 25 14:05 host1_server_certificate.pem
We do the same thing for host2, after adjusting the input and output files names:
# certtool --generate-certificate --template host2_server_template.info --load-privkey host2_server_key.pem --load-ca-certificate certificate_authority_certificate.pem --load-ca-privkey certificate_authority_key.pem --outfile host2_server_certificate.pem Generating a signed certificate... X.509 Certificate Information: Version: 3 Serial Number (hex): 4c7496d0 Validity: Not Before: Wed Aug 25 04:06:40 UTC 2010 Not After: Thu Aug 25 04:06:40 UTC 2011 Subject: O=libvirt.org,CN=host2 Subject Public Key Algorithm: RSA Modulus (bits 2048): d3:5d:8f:b6:6f:12:22:ac:4a:e8:d8:37:f6:f7:63:3d 47:26:c6:0d:10:be:ad:12:52:22:26:9f:2f:12:29:57 b8:bf:2b:97:70:88:1d:12:e5:df:05:65:8b:ee:a6:18 30:60:2d:70:bc:dd:99:bf:61:42:9e:55:9c:a1:a7:75 b1:02:68:52:22:57:e0:d6:e4:8b:4b:26:77:56:36:b8 9f:b8:fe:d8:cd:af:04:c2:17:76:9c:f3:48:19:45:63 b5:8d:21:a3:8e:3d:d5:5b:63:9e:3e:e9:86:51:2a:ad 18:27:a1:e5:09:73:7a:c5:34:14:8a:d7:c6:c6:a2:d8 91:96:36:c3:87:3e:45:56:a5:bb:77:d4:10:04:d0:68 68:f8:60:e2:d4:4f:c6:27:cf:e5:e9:47:79:11:c3:95 6d:53:f2:dd:43:c1:ec:80:ac:ac:0c:d9:3d:94:54:41 60:03:01:07:b2:e8:c7:4c:6b:52:c1:38:d1:6d:0a:70 86:e9:be:64:21:73:b8:51:a3:2e:01:9b:7e:fd:9d:37 5c:ad:47:8e:c3:bc:1f:a2:35:bb:84:f3:98:d3:9c:c2 9a:57:1c:c2:be:84:fe:3e:d1:af:25:21:6e:67:60:bb e3:29:0f:d0:70:d7:b0:f7:8e:ed:7d:e1:b3:ad:1d:3b Exponent (bits 24): 01:00:01 Extensions: Basic Constraints (critical): Certificate Authority (CA): FALSE Key Purpose (not critical): TLS WWW Server. Key Usage (critical): Digital signature. Key encipherment. Subject Key Identifier (not critical): 3df1e4ef69e23976a829700f28f5cbb1685364d9 Authority Key Identifier (not critical): 9512006c97dbdedbb3232a22cfea6b1341d72d76 Other Information: Public Key Id: 3df1e4ef69e23976a829700f28f5cbb1685364d9 Signing certificate...
This will have created the TLS Server Certificate file, host2_server_certificate.pem, for host2:
# ls -la *server_certificate.pem -rw-r--r--. 1 root root 1164 Aug 25 14:05 host1_server_certificate.pem -rw-r--r--. 1 root root 1164 Aug 25 14:06 host2_server_certificate.pem
The template files are no longer needed, so can be discarded
# rm host1_server_template.info host2_server_template.info
Moving the Certificates into place
Now the Server Certificates have been created, it is time to move them into place on the hosts.
The default location the libvirt daemon looks for the Server Certificate file is /etc/pki/libvirt/servercert.pem. The private key to match this needs to be in /etc/pki/libvirt/private/serverkey.pem. You will likely have to create the directories to hold these files.
The private key file should be kept secure, with only the root user able to access it in any way. The server certificate file is not as sensitive.
Ownership, Permissions, and SELinux labels
Reasonable ownership and permissions for these two files, and the directories containing them, are:
Directory: /etc/pki/libvirt/ Ownership: root:qemu Permissions: u=rwx,g=rx,o=rx (755) SELinux label: system_u:object_r:cert_t:s0
Server Certificate path: /etc/pki/libvirt/servercert.pem Ownership: root:qemu Permissions: u=r,g=r,o= (440) SELinux label: system_u:object_r:cert_t:s0
Directory: /etc/pki/libvirt/private/ Ownership: root:qemu Permissions: u=rwx,g=rx,o= (750) SELinux label: system_u:object_r:cert_t:s0
Private Key for Server Certificate: /etc/pki/libvirt/private/serverkey.pem Ownership: root:qemu Permissions: u=r,g=r,o= (440) SELinux label: system_u:object_r:cert_t:s0
The SELinux labels are only relevant if your servers have SELinux enabled. They can be ignored if SELinux is disabled.
Also take into account your site security practices and requirements, as they may require things to be done differently.
Transferring the files and setting them up
In the example below, we use the utility scp to transfer the certificate and key to each host. We then log in directly to each host to move the files into place and set their permissions accordingly.
Transferring the files to host1
Notice the filenames are being changed in the transfer
# scp -p host1_server_certificate.pem someuser@host1:servercert.pem someuser@host1‘s password: host1_server_certificate.pem 100% 1164 1.1KB/s 00:00
# scp -p host1_server_key.pem someuser@host1:serverkey.pem someuser@host1‘s password: host1_server_key.pem 100% 1675 1.6KB/s 00:00
Logged into host1
First we create the directories and set their permissions:
# mkdir -p /etc/pki/libvirt/private
# chmod 755 /etc/pki/libvirt
# chmod 750 /etc/pki/libvirt/private
Then we move the files into place and set their permissions:
# mv servercert.pem /etc/pki/libvirt
# mv serverkey.pem /etc/pki/libvirt/private
# chgrp qemu /etc/pki/libvirt /etc/pki/libvirt/servercert.pem /etc/pki/libvirt/private /etc/pki/libvirt/private/serverkey.pem
# chmod 440 /etc/pki/libvirt/servercert.pem /etc/pki/libvirt/private/serverkey.pem
If the server has SELinux enabled, we also update the SELinux labels:
# restorecon -R /etc/pki/libvirt /etc/pki/libvirt/private
$ ls -laZ /etc/pki/libvirt /etc/pki/libvirt: total 20 drwxr-xr-x 3 root qemu system_u:object_r:cert_t:s0 . drwxr-xr-x. 8 root root system_u:object_r:cert_t:s0 .. drwxr-x--- 2 root qemu system_u:object_r:cert_t:s0 private -r--r-----. 1 root qemu system_u:object_r:cert_t:s0 servercert.pem
$ ls -laZ /etc/pki/libvirt/private/ /etc/pki/libvirt/private/: total 16 drwxr-x--- 2 root qemu system_u:object_r:cert_t:s0 drwxr-xr-x 3 root qemu system_u:object_r:cert_t:s0 .. -r--r-----. 1 root qemu system_u:object_r:cert_t:s0 serverkey.pem
Transferring the files to host2
Notice the filenames are being changed in the transfer
# scp -p host2_server_certificate.pem someuser@host2:servercert.pem someuser@host2‘s password: host2_server_certificate.pem 100% 1164 1.2KB/s 00:00
# scp -p host2_server_key.pem someuser@host2:serverkey.pem someuser@host2‘s password: host2_server_key.pem 100% 1675 1.8KB/s 00:00
Logged into host2
First we create the directories and set their permissions:
$ sudo mkdir -p /etc/pki/libvirt/private
$ sudo chmod 755 /etc/pki/libvirt
$ sudo chmod 750 /etc/pki/libvirt/private
Then we move the files into place and set their permissions:
# mv servercert.pem /etc/pki/libvirt
# mv serverkey.pem /etc/pki/libvirt/private
# chgrp qemu /etc/pki/libvirt /etc/pki/libvirt/servercert.pem /etc/pki/libvirt/private /etc/pki/libvirt/private/serverkey.pem
# chmod 440 /etc/pki/libvirt/servercert.pem /etc/pki/libvirt/private/serverkey.pem
If the server has SELinux enabled, we also update the SELinux labels:
# restorecon -R /etc/pki/libvirt /etc/pki/libvirt/private
$ ls -laZ /etc/pki/libvirt /etc/pki/libvirt: total 20 drwxr-xr-x 3 root qemu system_u:object_r:cert_t:s0 . drwxr-xr-x. 8 root root system_u:object_r:cert_t:s0 .. drwxr-x--- 2 root qemu system_u:object_r:cert_t:s0 private -r--r-----. 1 root qemu system_u:object_r:cert_t:s0 servercert.pem
$ ls -laZ /etc/pki/libvirt/private/ /etc/pki/libvirt/private/: total 16 drwxr-x--- 2 root qemu system_u:object_r:cert_t:s0 . drwxr-xr-x 3 root qemu system_u:object_r:cert_t:s0 .. -r--r-----. 1 root qemu system_u:object_r:cert_t:s0 serverkey.pem
The Server Certificate setup step is now complete
Overriding the default locations
If you need the Server Certificate file and its public key to be in a different location on the host, you can configure this in the /etc/libvirt/libvirtd.conf configuration file.
The two settings are:
cert_file = "Full path to new Server Certificate location" key_file = "Full path to new Server Certificate Private Key location"
The paths should be enclosed in double quotes.
For example:
cert_file = "/opt/libvirt/etc/pki/libvirt/servercert.pem" key_file = "/opt/libvirt/etc/pki/libvirt/private/serverkey.pem"
Creating Transport Layer Security Client Certificates for libvirt
In our example scenario we have two Virtualisation Host Servers being set up for TLS communication, along with an Administrative desktop used to perform virtualisation management functions.
We also have the Certificate Authority Certificate and its private key created in a previous step.
In this step we create the TLS Client Certificates for both hosts and the administrative desktop, allowing them to communicate using TLS connections.
Create the Client Certificates
This can be done wherever you have both the Certificate Authority Certificate file, and its private key.
We use the utility certtool, from the gnutls-utils package for many parts of this.
Create the Client Certificate Template files using a text editor
These are plain text files, one for each virtualisation client, containing the following fields:
country = Country state = State locality = City organization = Name of your organization cn = Client Host Name tls_www_client encryption_key signing_key
The Name of your organization field should be adjusted to suit your organization, the location related fields need to be updated, and the Client Host Name field must be changed to match the host name of each client.
For our example scenario, we have three files:
# ls -al *client_template.info -rw-r--r--. 1 root root 141 Aug 26 13:21 admin_desktop_client_template.info -rw-r--r--. 1 root root 134 Aug 26 13:20 host1_client_template.info -rw-r--r--. 1 root root 134 Aug 26 13:20 host2_client_template.info
# cat host1_client_template.info country = AU state = Queensland locality = Brisbane organization = libvirt.org cn = host1 tls_www_client encryption_key signing_key
# cat host2_client_template.info country = AU state = Queensland locality = Brisbane organization = libvirt.org cn = host2 tls_www_client encryption_key signing_key
# cat admin_desktop_client_template.info country = AU state = Queensland locality = Brisbane organization = libvirt.org cn = admindesktop tls_www_client encryption_key signing_key
Create the Client Certificate Private Key files using certtool
Generate the private key files, to be used with the Client Certificates.
These keys are used to create the TLS Client Certificates, by each virtualisation host when the virtualisation system starts up, and by the administration desktop each time the virtualisation tools are used.
We create a unique private key for each client, also ensuring the permissions only allow very restricted access to these files:
# (umask 277 && certtool --generate-privkey > host1_client_key.pem) Generating a 2048 bit RSA private key...
# (umask 277 && certtool --generate-privkey > host2_client_key.pem) Generating a 2048 bit RSA private key...
# (umask 277 && certtool --generate-privkey > admin_desktop_client_key.pem) Generating a 2048 bit RSA private key...
# ls -al *_client_key.pem -r--------. 1 root root 1675 Aug 26 13:26 admin_desktop_client_key.pem -r--------. 1 root root 1675 Aug 26 13:26 host1_client_key.pem -r--------. 1 root root 1679 Aug 26 13:26 host2_client_key.pem
NOTE - The security of these private key files is very important.
If an unauthorised person obtains one of these private key files, they could use it with a Client Certificate to impersonate one of your virtualisation clients. Depending upon your host configuration, they may then be able to perform administrative commands on your host servers. Use good unix security to restrict access to the key files appropriately.
Combine the template files with the private key files, to create the Client Certificates
We generate Client Certificates using the template files, along with the corresponding private key files. Also, the Certificate Authority Certificate file is added with its private key, to ensure each new client certificate is signed properly.
For our two virtualisation hosts and the admin desktop, this means:
# certtool --generate-certificate --template host1_client_template.info --load-privkey host1_client_key.pem --load-ca-certificate certificate_authority_certificate.pem --load-ca-privkey certificate_authority_key.pem --outfile host1_client_certificate.pem Generating a signed certificate... X.509 Certificate Information: Version: 3 Serial Number (hex): 4c75e08c Validity: Not Before: Thu Aug 26 03:33:32 UTC 2010 Not After: Fri Aug 26 03:33:32 UTC 2011 Subject: C=AU,O=libvirt.org,L=Brisbane,ST=Queensland,CN=host1 Subject Public Key Algorithm: RSA Modulus (bits 2048): a4:73:68:6d:b3:d2:5a:b8:82:78:ad:d7:69:5b:9f:92 a8:a1:1c:a7:a3:49:af:5b:a6:20:95:f6:e9:a2:80:88 85:a7:fb:72:a4:39:e1:b3:6c:9d:fb:3c:4a:97:02:dd cf:46:e0:72:8a:cd:fc:44:30:d5:f0:b1:65:55:4d:a2 e8:7e:0c:c6:38:3d:b1:aa:d8:ff:e4:4e:fe:8a:c7:5e e0:9c:b6:f6:4b:bd:9b:f1:b3:f1:48:b0:60:d8:ef:f4 f2:c8:50:94:92:80:54:fc:48:ef:bb:13:69:58:50:9f fb:c9:e0:df:b2:2c:1c:3f:65:fa:d4:58:a5:18:dc:7a 12:0c:bc:ef:6f:fd:56:bc:e1:47:20:75:6b:4a:f9:f5 a3:b4:ab:ca:07:43:e1:2a:fa:47:2c:9a:ec:97:7c:7f c7:3f:1a:d5:9a:c2:ad:57:5c:52:ed:70:42:8b:8c:a8 00:a4:c4:a7:84:56:09:fe:ad:c8:ed:92:70:7a:b2:d7 88:e4:36:7a:0f:76:ae:65:fc:e0:9b:29:f7:e3:f4:11 5e:b8:56:27:0f:6b:1b:bc:d2:29:3e:82:12:15:7d:e0 91:44:4e:6c:eb:e8:ed:92:68:4c:ce:49:d6:67:bc:23 fc:f6:18:e9:c1:0d:84:cd:99:36:f2:c9:4f:60:5d:f1 Exponent (bits 24): 01:00:01 Extensions: Basic Constraints (critical): Certificate Authority (CA): FALSE Key Purpose (not critical): TLS WWW Client. Key Usage (critical): Digital signature. Key encipherment. Subject Key Identifier (not critical): 20a33ffc7ead1c61ea0890c0c30da0248c8fa80d Authority Key Identifier (not critical): 9512006c97dbdedbb3232a22cfea6b1341d72d76 Other Information: Public Key Id: 20a33ffc7ead1c61ea0890c0c30da0248c8fa80d Signing certificate...
Make a note of the highlighted contents of the Subject field in the output. This is the Distinguished Name of the client. It is used in an optional final part of TLS configuration, where access is restricted to only specific clients. So keep a copy of it around until then.
In addition to the displayed output, the certtool command will have created the file host1_client_certificate.pem. This is the TLS Client Certificate file for host1:
# ls -la host1_client_certificate.pem -rw-r--r--. 1 root root 1233 Aug 26 13:33 host1_client_certificate.pem
We do the same thing for host2, and for the administrative desktop, after adjusting the input and output files names:
# certtool --generate-certificate --template host2_client_template.info --load-privkey host2_client_key.pem --load-ca-certificate certificate_authority_certificate.pem --load-ca-privkey certificate_authority_key.pem --outfile host2_client_certificate.pem Generating a signed certificate... X.509 Certificate Information: Version: 3 Serial Number (hex): 4c75e110 Validity: Not Before: Thu Aug 26 03:35:44 UTC 2010 Not After: Fri Aug 26 03:35:44 UTC 2011 Subject: C=AU,O=libvirt.org,L=Brisbane,ST=Queensland,CN=host2 Subject Public Key Algorithm: RSA Modulus (bits 2048): ed:74:42:38:0b:37:20:8a:de:0d:44:70:d4:99:d1:ed 77:fb:32:b4:6d:3e:bb:8d:9d:4b:dd:65:8c:03:d2:30 ec:d6:89:34:b2:e6:fa:cd:ac:a3:a1:6f:b2:ad:dc:45 82:95:1a:8e:87:f1:4e:8f:4e:a8:01:b3:8a:3a:e9:74 8d:34:6b:4e:3f:fc:a0:10:a2:0e:75:ee:5e:d9:1c:d0 ef:d7:c4:79:8f:94:bf:c9:c0:59:a3:56:99:a2:08:2c 3d:cb:bf:3c:a8:2a:17:fe:9a:f5:9f:3f:ef:fb:bb:13 2c:b5:40:4c:5a:00:e6:1e:86:07:73:ae:2a:1d:72:79 8e:9c:5e:8b:a8:2a:ea:eb:4d:f3:19:f3:62:32:9f:99 f0:2f:e1:1a:52:bb:32:47:7e:1d:b3:82:30:18:66:d2 56:a9:38:23:88:64:2b:84:89:f9:0a:9a:b4:71:49:58 22:ef:e3:47:44:40:ad:28:2c:77:5a:18:92:5e:4d:5f 74:a9:92:92:d8:df:44:d6:b2:83:77:da:1b:63:98:66 ce:57:89:bd:95:51:12:f7:43:bb:1c:1d:7f:87:4f:69 3b:34:90:6e:d7:ff:df:1b:cd:49:72:ad:b6:42:8a:2d 45:03:f0:d0:f8:68:e4:86:1b:8b:9c:58:be:4a:b6:95 Exponent (bits 24): 01:00:01 Extensions: Basic Constraints (critical): Certificate Authority (CA): FALSE Key Purpose (not critical): TLS WWW Client. Key Usage (critical): Digital signature. Key encipherment. Subject Key Identifier (not critical): 3aa582550543cd4de72f22ca791600a04d2c0dbb Authority Key Identifier (not critical): 9512006c97dbdedbb3232a22cfea6b1341d72d76 Other Information: Public Key Id: 3aa582550543cd4de72f22ca791600a04d2c0dbb Signing certificate...
# certtool --generate-certificate --template admin_desktop_client_template.info --load-privkey admin_desktop_client_key.pem --load-ca-certificate certificate_authority_certificate.pem --load-ca-privkey certificate_authority_key.pem --outfile admin_desktop_client_certificate.pem Generating a signed certificate... X.509 Certificate Information: Version: 3 Serial Number (hex): 4c75e1d8 Validity: Not Before: Thu Aug 26 03:39:04 UTC 2010 Not After: Fri Aug 26 03:39:04 UTC 2011 Subject: C=AU,O=libvirt.org,L=Brisbane,ST=Queensland,CN=admindesktop Subject Public Key Algorithm: RSA Modulus (bits 2048): d4:f3:23:dc:15:9e:f6:0f:ab:fe:77:5e:dc:72:a2:4d e3:36:a0:cd:6c:47:b7:8a:f0:19:3c:fd:72:da:9e:56 41:a7:2e:e2:14:87:b8:14:79:2c:e1:20:64:63:ca:91 05:69:9c:9c:7e:db:d4:50:3f:82:90:df:b9:d8:87:85 a4:12:55:a2:34:42:19:5e:e0:1a:78:f4:c7:82:2c:a1 0b:cd:22:98:cd:c0:35:d9:8f:c0:db:7e:8f:6c:9b:52 ec:82:af:97:3f:71:5e:9e:d5:9c:fd:02:9b:c8:5f:67 bc:ba:37:99:0b:2d:0e:91:c9:c0:21:92:e6:3f:84:7e c7:b3:b8:16:d3:85:bd:69:73:a2:a5:f2:d5:95:79:79 9f:64:ad:36:24:94:a2:2b:1c:24:7e:19:23:ba:33:b7 29:c6:f2:ea:84:46:16:c4:95:ad:f9:a1:ab:35:15:62 3c:27:d7:b6:4a:dd:13:dc:1e:b4:00:f2:a0:01:12:38 a1:03:4e:24:bf:ac:eb:58:87:46:51:56:dd:ce:e2:10 02:16:a6:9f:e7:ae:e3:b8:35:5c:7e:11:59:e8:02:e6 2d:13:7e:fa:64:b7:8f:16:07:df:a9:f3:12:a7:dc:de 81:8b:b1:56:aa:dd:72:18:75:73:23:c8:5e:df:48:31 Exponent (bits 24): 01:00:01 Extensions: Basic Constraints (critical): Certificate Authority (CA): FALSE Key Purpose (not critical): TLS WWW Client. Key Usage (critical): Digital signature. Key encipherment. Subject Key Identifier (not critical): 93a5c2f0b48351e6043bf4d7a62a3a0b458b70f2 Authority Key Identifier (not critical): 9512006c97dbdedbb3232a22cfea6b1341d72d76 Other Information: Public Key Id: 93a5c2f0b48351e6043bf4d7a62a3a0b458b70f2 Signing certificate...
This will have created the TLS Client Certificate files, host2_client_certificate.pem for host2, and admin_desktop_client_certificate.pem for the admin desktop:
# ls -al *client_certificate.pem -rw-r--r--. 1 root root 1245 Aug 26 13:39 admin_desktop_client_certificate.pem -rw-r--r--. 1 root root 1233 Aug 26 13:33 host1_client_certificate.pem -rw-r--r--. 1 root root 1233 Aug 26 13:35 host2_client_certificate.pem
The template files are no longer needed, so can be discarded
# rm host1_client_template.info host2_client_template.info admin_desktop_client_template.info
Moving the Certificates into place
Now the Client Certificates have been created, they need to be transferred to each of the virtualisation hosts and the admin client.
The default location the libvirt daemon looks for the Client Certificate file is /etc/pki/libvirt/clientcert.pem. The private key to match this needs to be in /etc/pki/libvirt/private/clientkey.pem.
The private key file should be kept secure, with only the root user able to access it in any way. The client certificate file is not as sensitive.
Ownership and permissions
Reasonable ownership, permissions, and SELinux labelling for these two files are:
Client Certificate path: /etc/pki/libvirt/clientcert.pem Ownership: root:root Permissions: u=r,g=,o= (400) SELinux label: system_u:object_r:cert_t:s0
Private Key for Client Certificate: /etc/pki/libvirt/private/clientkey.pem Ownership: root:root Permissions: u=r,g=,o= (400) SELinux label: system_u:object_r:cert_t:s0
The SELinux label is only relevant if the server or desktop has SELinux enabled. It can be ignored otherwise.
You should take into account your site security practices and requirements, as they may need things to be done differently.
Transferring the files and setting them up
In the example below, we use the utility scp to transfer the certificate and key to each virtualisation client. We then log in directly to each host to move the files into place and set their permissions accordingly.
Transferring the files to host1
Notice the filenames are being changed in the transfer
# scp -p host1_client_certificate.pem someuser@host1:clientcert.pem someuser@host1‘s password: host1_client_certificate.pem 100% 1164 1.4KB/s 00:00
# scp -p host1_client_key.pem someuser@host1:clientkey.pem someuser@host1‘s password: host1_client_key.pem 100% 1675 1.7KB/s 00:00
Logged into host1
We move the files into place and set their permissions:
$ sudo mv clientcert.pem /etc/pki/libvirt
$ sudo mv clientkey.pem /etc/pki/libvirt/private
$ sudo chmod 400 /etc/pki/libvirt/clientcert.pem /etc/pki/libvirt/private/clientkey.pem
If SELinux is enabled, then update the labels as well:
$ sudo restorecon /etc/pki/libvirt/clientcert.pem /etc/pki/libvirt/private/clientkey.pem
$ ls -laZ /etc/pki/libvirt /etc/pki/libvirt: total 20 drwxr-xr-x 3 root root system_u:object_r:cert_t:s0 . drwxr-xr-x. 8 root root system_u:object_r:cert_t:s0 .. -r--------. 1 root root system_u:object_r:cert_t:s0 clientcert.pem drwx------ 2 root root system_u:object_r:cert_t:s0 private -r--------. 1 root root system_u:object_r:cert_t:s0 servercert.pem
$ sudo ls -laZ /etc/pki/libvirt/private/ /etc/pki/libvirt/private/: total 16 drwx------ 2 root root system_u:object_r:cert_t:s0 . drwxr-xr-x 3 root root system_u:object_r:cert_t:s0 .. -r--------. 1 root root system_u:object_r:cert_t:s0 clientkey.pem -r--------. 1 root root system_u:object_r:cert_t:s0 serverkey.pem
Transferring the files to host2
Notice the filenames are being changed in the transfer
# scp -p host2_client_certificate.pem someuser@host2:clientcert.pem someuser@host2‘s password: host2_client_certificate.pem 100% 1164 1.2KB/s 00:00
# scp -p host2_client_key.pem someuser@host2:clientkey.pem someuser@host2‘s password: host2_client_key.pem 100% 1675 1.1KB/s 00:00
Logged into host2
We move the files into place and set their permissions:
$ sudo mv clientcert.pem /etc/pki/libvirt
$ sudo mv clientkey.pem /etc/pki/libvirt/private
$ sudo chmod 400 /etc/pki/libvirt/clientcert.pem /etc/pki/libvirt/private/clientkey.pem
If SELinux is enabled, then update the labels as well:
$ sudo restorecon /etc/pki/libvirt/clientcert.pem /etc/pki/libvirt/private/clientkey.pem
$ ls -laZ /etc/pki/libvirt /etc/pki/libvirt: total 20 drwxr-xr-x 3 root root system_u:object_r:cert_t:s0 . drwxr-xr-x. 8 root root system_u:object_r:cert_t:s0 .. -r--------. 1 root root system_u:object_r:cert_t:s0 clientcert.pem drwx------ 2 root root system_u:object_r:cert_t:s0 private -r--------. 1 root root system_u:object_r:cert_t:s0 servercert.pem
$ sudo ls -laZ /etc/pki/libvirt/private/ /etc/pki/libvirt/private/: total 16 drwx------ 2 root root system_u:object_r:cert_t:s0 . drwxr-xr-x 3 root root system_u:object_r:cert_t:s0 .. -r--------. 1 root root system_u:object_r:cert_t:s0 clientkey.pem -r--------. 1 root root system_u:object_r:cert_t:s0 serverkey.pem
Transferring the files to the administrative desktop
Notice the filenames are being changed in the transfer
# scp -p admin_desktop_client_certificate.pem someuser@admindesktop:clientcert.pem someuser@admindesktop‘s password: admin_desktop_client_certificate.pem 100% 1164 1.1KB/s 00:00
# scp -p admin_desktop_client_key.pem someuser@admindesktop:clientkey.pem someuser@admindesktop‘s password: admin_desktop_client_key.pem 100% 1675 1.6KB/s 00:00
Logged into the administrative desktop
We move the files into place and set their permissions:
$ sudo mv clientcert.pem /etc/pki/libvirt
$ sudo mv clientkey.pem /etc/pki/libvirt/private
$ sudo chmod 400 /etc/pki/libvirt/clientcert.pem /etc/pki/libvirt/private/clientkey.pem
If SELinux is enabled, then update the labels as well:
$ sudo restorecon /etc/pki/libvirt/clientcert.pem /etc/pki/libvirt/private/clientkey.pem
$ ls -laZ /etc/pki/libvirt /etc/pki/libvirt: total 20 drwxr-xr-x 3 root root system_u:object_r:cert_t:s0 . drwxr-xr-x. 8 root root system_u:object_r:cert_t:s0 .. -r--------. 1 root root system_u:object_r:cert_t:s0 clientcert.pem drwx------ 2 root root system_u:object_r:cert_t:s0 private
$ sudo ls -laZ /etc/pki/libvirt/private/ /etc/pki/libvirt/private/: total 16 drwx------ 2 root root system_u:object_r:cert_t:s0 . drwxr-xr-x 3 root root system_u:object_r:cert_t:s0 .. -r--------. 1 root root system_u:object_r:cert_t:s0 clientkey.pem
The Client Certificate setup step is now complete
Configuring the libvirt daemon to use TLS
The libvirt daemon on both virtualisation servers needs to be configured to use the TLS Certificates and Private Keys that have been installed.
If you have installed the TLS Certificates and keys in their default locations, and if using the default network port is acceptable, the next step is very simple.
All that needs to be done is instruct libvirt to listen for network connections.
On RHEL 6 and Fedora, this is done by uncommenting the LIBVIRTD_ARGS line in /etc/sysconfig/libvirtd.
i.e. Changing the line from this:
#LIBVIRTD_ARGS="--listen"
to this:
LIBVIRTD_ARGS="--listen"
Then restart the libvirt daemon:
# service libvirtd restart Stopping libvirtd daemon: [ OK ] Starting libvirtd daemon: [ OK ]
# ps -ef |grep libvirtd root 6910 1 18 09:49 ? 00:00:01 libvirtd --daemon --listen
If for some reason the libvirt daemon hasn‘t restarted correctly with this enabled, try manually starting the daemon from the command line. It will helpfully display an error message indicating the problem, before it exits.
For example, with the server certificate not in place, this is given:
# libvirtd --listen 09:58:12.968: error : remoteCheckCertFile:277 : Cannot access server certificate ‘/etc/pki/libvirt/servercert.pem‘: No such file or directory
Restricting access
To assist in protecting your virtualisation servers against unauthorised access, you can instruct libvirt to only accept TLS connections from a given list of client systems.
This is done by configuring the tls_allowed_dn_list option in the libvirtd.conf configuration file, listing the Distinguished Name of each virtualisation client allowed to connect.
tls_allowed_dn_list = ["Client 1", "Client 2", "Client 3"]
The Distinguished Name is in the output from the certtool command used when creating Client Certificates, as shown in the previous step.
For example:
tls_allowed_dn_list = ["C=AU,O=libvirt.org,L=Brisbane,ST=Queensland,CN=host1", "C=AU,O=libvirt.org,L=Brisbane,ST=Queensland,CN=host2", "C=AU,O=libvirt.org,L=Brisbane,ST=Queensland,CN=admindesktop"]
NOTE - Do not enable this option with an empty list. That will cause libvirt to listen for TLS connections but reject all of them.
For this change to take effect, the libvirt daemon needs to be restarted:
# service libvirtd restart Stopping libvirtd daemon: [ OK ] Starting libvirtd daemon: [ OK ]
Verifying it all works
The final step is to verify TLS connections are set up and working correctly.
This can be done using the virsh utility, and client to server path should be individually tested. In our example scenario this means testing:
- From the admin desktop to both virtualisation hosts
- From host 1 to host 2
- From host 2 to host 1
If the connection works, then we‘ll be able to run an administrative command on the remote host. We use the virsh command "hostname" for our testing, to retrieve the host name of the remote host. This doesn‘t change anything on the remote host, but proves the TLS connection is working.
If something is not set up correctly, the connection will fail with virsh giving an error message. For example:
# virsh -c qemu+tls://host1/system hostname error: server verification (of our certificate or IP address) failed error: failed to connect to the hypervisor
It‘s worth also remembering that TLS is the default connection type attempted for QEMU URL‘s, so we don‘t need to include +tls in the connection string. Both of these are equivalent:
# virsh -c qemu://host2/system
# virsh -c qemu+tls://host2/system
Testing from the admin desktop to both hosts
# virsh -c qemu://host1/system hostname host1.libvirt.org
# virsh -c qemu://host2/system hostname host2.libvirt.org
From host 1 to host 2
# virsh -c qemu://host2/system hostname host2.libvirt.org
Finally, from host 2 to host 1
# virsh -c qemu://host1/system hostname host1.libvirt.org
If all of the tests worked fine (they should), then congratulations, the TLS Configuration is complete
Further information
These pages have covered setting up TLS on your virtualisation hosts.
Further information is available on several of the major items covered:
VNC Client configuration for TLS - Instructions for setting up several well known VNC client packages are on the VNC Client TLS Setup page.
libvirtd.conf - The libvirt daemon configuration file has more options than described in these pages. They are all shown and briefly described in the libvirt.org reference page.
certtool - The utility used to generate private keys and certificates, has its full manual page online. This includes both its command line options, and the options usable in the template file.
The X509 Trust Model - The GnuTLS pages have useful information describing the X509 certificate trust model.