[Libvir] Certificate management APIs ?
Mark McLoughlin
markmc at redhat.com
Mon Jan 15 20:44:22 UTC 2007
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.
More information about the libvir-list
mailing list