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.