Hi Dan,
On Wed, 2007-01-10 at 23:59 +0000, Daniel P. Berrange wrote:
I now have the QEMU backend working with full wire encryption using
the
TLS protocol, and so ready to start thinking about various authentication
related issues.
If only we had decent SSH infrastructure. I'd love if apps could easily
use a library to request an SSH connection to a host, authenticate and
then apps could request tunnels over that shared per-user connection.
- The client needs to have the certificate of the CA in order to
validate the signature on the remote server's certificate
(aka, just like web browsers need a set of CA certificates)
Currently I just have it loading 'cert.pem' out of the current
working directory of the app using libvirt. Obviously this is not
a real solution.
Personally, I'd start with the assumption that essentially no-one will
install a CA signed cert for the libvirt server. So, first and foremost,
the client needs to be present self-signed certs to the user.
As for the CA certs, we should use /etc/pki/tls/cert.pem by default,
right? And perhaps allow users and admins to install other CA certs just
for libvirt.
- The server end can optionally require the client to present a
certificate too, as its means of authenticating the client.
This obviously requires a way of specifying the client certificate
and secret key in libvirt when opening the connection.
For the networks stuff, I think the server will also need to be able to
connect to (and authenticate and be authenticated by) other servers.
Also, as much as it sucks, I think we'll want password based
authentication as well as certificate based authentication. Very few
people will copy the client cert over to the server, I think.
As a rough stab at an API my thoughts are:
typedef enum {
VIR_CERT_CA_CERT,
VIR_CERT_CA_CRL,
VIR_CERT_CLIENT_KEY,
VIR_CERT_CLIENT_CERT,
} virConnectCertDataType;
/**
* dataType: one of the virConnectCertDataType constants
* data: base64, PEM encoded certificate/key data
*/
int virConnectAddCertData(int dataType, const char *data);
/**
* dataType: one of the virConnectCertDataType constants
* dataFile: file containing base64, PEM encoded certificate/key data
*/
int virConnectAddCertDataFile(int dataType, const char *dataFile);
Seems reasonable, I can't think of anything better.
Virt-manager would use the latter API to load in its client
certificate,
CA certs, etc to libvirt prior to opening a connection to a TLS enabled
server. This means libvirt doesn't have to make the policy on where to
store its client cert data. On the otherhand, we probably want the
files to be in a common location for virsh & virt-manager so both can
use the same data. On yet another hand, virt-manager will also likely
end up using TLS to connect to VNC, so needs access to the files
independant on libvirt / virsh for that. So we should probably have
these flexible APIs, but recommend that all apps use a pre-defined
directory unless they have a particular need not to, eg
$HOME/.libvirt/tls/
|
+- ca
| |
| +- cert.pem
| +- ca-crl.pem
|
+- client
| |
| +- cert.pem
| +- key.pem
|
+- server
|
+- trusted.pem
Not entirely unreasonable, but I think I'd expect it to be in
~/.virt-manager and have a ~/.virshrc which you could point at it.
If it was ~/.libvirt, then I'd expect virt-manager to access the certs
through e.g. virConnectGetCertData() rather than making the directory
structure part of the API.
One final point on all that - "uggh".
/**
* hostname: canonical name of remote host providing certiifcate
* cert: base64, PEM encoded certificate data
*
* Invoked to let client application decide whether to accept a
* server certificate. The certificate wil already have been
* validated against the CA cert, and its expiration date, etc
* checked. This callback is intended to allow the end user to
* accept/reject the certificate. The trusted flag indicates
* whether the server is present in the list of known servers.
*/
typedef int (*virConnectCertificateValidator)(const char *hostname, const char *cert);
int virConnectSetCertificateValidator(virConnectCertificateValidator cb)
The applications like virt-manager would probably want to present the
certificate details to the user for validation, also optionally maintaining
a list of previously trusted server certs.
The callback approach seems fine. I'd think about adding a
virConnectCertificate structure whose contents are only available
through accessor functions and passing that to the callback, though. For
future expansion.
Cheers,
Mark.