[libvirt] Implementing VNC per VM access control lists

Hi, At the moment SASL VNC authentication in libvirt allows any of the userids to access any of the VNC consoles on a particular libvirt host. There is a section in the qemu_command code marked "TODO: Support ACLs later" and we would really like the ability to have per VM user authorization to the VNC console from within libvirt. Essentially the people who are accessing the VNC consoles are not administrators and have no access to the Host server - so these ACLs need to be completely based on a separate list of userids to any access mechanism for the libvirtd itself. Given that the VNC restrictions are enforced within qemu from the monitor system, I'm presuming the authorization list is going to have to be passed in via XML and be capable of being updated throughout the life of a VM session. Unless there's another way of doing it... What's the feeling about how this feature should be provided within libvirt? If there is somebody out there who has a bit of time at the moment and fancies having a go at implementing this - and, of course, there is agreement on a specification here - then we'd look at sponsoring them to add the feature into Libvirt. Please put your hand up! Regards, Neil Wilson

On 12/29/2010 11:45 AM, Neil Wilson wrote:
Hi,
At the moment SASL VNC authentication in libvirt allows any of the userids to access any of the VNC consoles on a particular libvirt host. There is a section in the qemu_command code marked "TODO: Support ACLs later" and we would really like the ability to have per VM user authorization to the VNC console from within libvirt.
Essentially the people who are accessing the VNC consoles are not administrators and have no access to the Host server - so these ACLs need to be completely based on a separate list of userids to any access mechanism for the libvirtd itself.
Given that the VNC restrictions are enforced within qemu from the monitor system, I'm presuming the authorization list is going to have to be passed in via XML and be capable of being updated throughout the life of a VM session. Unless there's another way of doing it...
What's the feeling about how this feature should be provided within libvirt?
One issue is probably around migration and the server (qemu-referenced) x509 certificates. If the certificates are embedded (rather than referenced) in the domain XML they will automatically migrate when the VM migrates, which is desirable. Otherwise migration becomes (again) problematic and layers above libvirt would have to take care of their migration. The VNC session will still be lost due to the change of host and thus the IP address and the client user will need to learn about the new VNC port as well. Quoting from Qemu documentation webpage: http://wiki.qemu.org/download/qemu-doc.html#vnc_005fsecurity <quote> 3.10.3 With x509 certificates The QEMU VNC server also implements the VeNCrypt extension allowing use of TLS for encryption of the session, and x509 certificates for authentication. The use of x509 certificates is strongly recommended, because TLS on its own is susceptible to man-in-the-middle attacks. Basic x509 certificate support provides a secure session, but no authentication. This allows any client to connect, and provides an encrypted session. qemu [...OPTIONS...] -vnc :1,tls,x509=/etc/pki/qemu -monitor stdio In the above example |/etc/pki/qemu| should contain at least three files, |ca-cert.pem|, |server-cert.pem| and |server-key.pem|. Unprivileged users will want to use a private directory, for example |$HOME/.pki/qemu|. NB the |server-key.pem| file should be protected with file mode 0600 to only be readable by the user owning it. </quote> It looks like the above mentioned 3 files would need to be embedded... Stefan

On Mon, 2011-01-03 at 09:19 -0500, Stefan Berger wrote:
One issue is probably around migration and the server (qemu-referenced) x509 certificates. If the certificates are embedded (rather than referenced) in the domain XML they will automatically migrate when the VM migrates, which is desirable. Otherwise migration becomes (again) problematic and layers above libvirt would have to take care of their migration.
The VNC session will still be lost due to the change of host and thus the IP address and the client user will need to learn about the new VNC port as well.
Don't you have the same problem at the moment with the existing per Host SASL authentication? I was more concerned with adding access list filters to the individual VMs after the authentication has happened. And surely those would migrate since they are contained within the configuration of the running process? I wasn't thinking of touching the authentication layer at all, more adding an authorization filter layer.

On Wed, Dec 29, 2010 at 04:45:26PM +0000, Neil Wilson wrote:
Hi,
At the moment SASL VNC authentication in libvirt allows any of the userids to access any of the VNC consoles on a particular libvirt host. There is a section in the qemu_command code marked "TODO: Support ACLs later" and we would really like the ability to have per VM user authorization to the VNC console from within libvirt.
Essentially the people who are accessing the VNC consoles are not administrators and have no access to the Host server - so these ACLs need to be completely based on a separate list of userids to any access mechanism for the libvirtd itself.
Given that the VNC restrictions are enforced within qemu from the monitor system, I'm presuming the authorization list is going to have to be passed in via XML and be capable of being updated throughout the life of a VM session. Unless there's another way of doing it...
What's the feeling about how this feature should be provided within libvirt?
Well I'd like us to have fine grained access control across users, objects & operations, probably using the role based access control model. Once you have such fine grained access control, then I don't believe you have a clearcut boundary between users of libvirtd and users of VNC. eg, you may well give the VNC admin access to the 'virDomainDestroy' and 'virDomainStart' commands for his own domains, but not other people's domains. So I think we should think about the solution to the authorization problem for both libvirtd & VNC at the same time. Regards, Daniel

On Tue, 2011-01-04 at 16:22 +0000, Daniel P. Berrange wrote:
Well I'd like us to have fine grained access control across users, objects & operations, probably using the role based access control model. Once you have such fine grained access control, then I don't believe you have a clearcut boundary between users of libvirtd and users of VNC. eg, you may well give the VNC admin access to the 'virDomainDestroy' and 'virDomainStart' commands for his own domains, but not other people's domains. So I think we should think about the solution to the authorization problem for both libvirtd & VNC at the same time.
Have you got an RBAC library in mind that would take the group management outside of libvirt (like SASL does for authentication), or does it all need building? Neil

On Wed, Jan 05, 2011 at 11:01:38AM +0000, Neil Wilson wrote:
On Tue, 2011-01-04 at 16:22 +0000, Daniel P. Berrange wrote:
Well I'd like us to have fine grained access control across users, objects & operations, probably using the role based access control model. Once you have such fine grained access control, then I don't believe you have a clearcut boundary between users of libvirtd and users of VNC. eg, you may well give the VNC admin access to the 'virDomainDestroy' and 'virDomainStart' commands for his own domains, but not other people's domains. So I think we should think about the solution to the authorization problem for both libvirtd & VNC at the same time.
Have you got an RBAC library in mind that would take the group management outside of libvirt (like SASL does for authentication), or does it all need building?
There's no general library that I'm aware of that'd be suitable. In addition to the general access control solution, we'd like to expand our SELinux support to cover MAC of the entire API (kinda like SEPostgreSQL). Regards, Daniel

On Wed, 2011-01-05 at 11:14 +0000, Daniel P. Berrange wrote:
There's no general library that I'm aware of that'd be suitable. In addition to the general access control solution, we'd like to expand our SELinux support to cover MAC of the entire API (kinda like SEPostgreSQL).
That's a very grand vision, but it is an awful lot of work when the feature request is just access control on the VNC screens. Am I better off just using accessing the qemu monitor out of band? Rgs Neil

Having looked through this, I'm thinking that the simplest thing that would be useful at the moment is simply to have an option in the /etc/libvirt/qemu.conf that adds the acl option to the vnc switch in qemu. It means that user will have to manipulate the acls directly via the monitor command for the time being until the access layer is designed, but at least you would be able to use acls on a machine launched by libvirt ('change vnc' doesn't appear to activate acls unless the option is active on the command line to start with.). I can't find a way of doing it with 'qemu:commandline' either - since it is an option to an existing switch. So I'm thinking a new option in qemu.conf (vnc_acl) which would add ',acl' to the vnc switch on the qemu command. By default this would bar access to VNC until you'd issued monitor commands to manipulate the access lists. The option only really makes sense if either vnc_tls_x509_verify or vnc_sasl is set as well, so it may be worth only activating 'acl' in the code if either of those two are also on. My preliminary tests show that it is ignored by RHEL5's default qemu-kvm much as it ignores SASL and that it is works as expected on RHEL6. If this sounds useful, I'm happy to code it up. Thoughts? Rgs Neil

On 01/06/2011 11:00 AM, Neil Wilson wrote:
Having looked through this, I'm thinking that the simplest thing that would be useful at the moment is simply to have an option in the /etc/libvirt/qemu.conf that adds the acl option to the vnc switch in qemu.
It means that user will have to manipulate the acls directly via the monitor command for the time being until the access layer is designed, but at least you would be able to use acls on a machine launched by libvirt ('change vnc' doesn't appear to activate acls unless the option is active on the command line to start with.).
I can't find a way of doing it with 'qemu:commandline' either - since it is an option to an existing switch.
When we first designed qemu:commandline, we debated about making it smart enough to allow rewriting of existing arguments (rather than only allowing addition of new arguments). This definitely sounds like a use case worth revisiting that situation, and enhancing qemu:commandline to have more features.
So I'm thinking a new option in qemu.conf (vnc_acl) which would add ',acl' to the vnc switch on the qemu command. By default this would bar access to VNC until you'd issued monitor commands to manipulate the access lists.
The option only really makes sense if either vnc_tls_x509_verify or vnc_sasl is set as well, so it may be worth only activating 'acl' in the code if either of those two are also on.
Should this be a per-XML setting, rather than a global qemu.conf setting? Is this something that is forward-looking (ie. once we also have an access layer designed, will it still make sense to keep and honor the qemu.conf setting), or is it enough of a hack that we should instead try to resolve it via the qemu:commandline approach (where we've explicitly documented that use of the interface is the approved way to do hacks in the absence of proper libvirt support)? It's definitely a hack that would let us get to the point o -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/06/2011 11:33 AM, Eric Blake wrote:
Is this something that is forward-looking (ie. once we also have an access layer designed, will it still make sense to keep and honor the qemu.conf setting), or is it enough of a hack that we should instead try to resolve it via the qemu:commandline approach (where we've explicitly documented that use of the interface is the approved way to do hacks in the absence of proper libvirt support)?
It's definitely a hack that would let us get to the point o
Sorry for the incomplete sentence - I rewrote my thoughts into the earlier paragraph but failed to delete the entire first draft before hitting send (I wasn't trying to leave you hanging for more of my thoughts). -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Eric, Thanks for the reply. On Thu, 2011-01-06 at 11:33 -0700, Eric Blake wrote:
When we first designed qemu:commandline, we debated about making it smart enough to allow rewriting of existing arguments (rather than only allowing addition of new arguments). This definitely sounds like a use case worth revisiting that situation, and enhancing qemu:commandline to have more features.
Possibly, although it would complicate it horribly. Are there sufficient unsupported options on the existing qemu switches to justify the work?
The option only really makes sense if either vnc_tls_x509_verify or vnc_sasl is set as well, so it may be worth only activating 'acl' in the code if either of those two are also on.
Should this be a per-XML setting, rather than a global qemu.conf setting?
That argument could be made for all the vnc options in qemu.conf. I might want SASL username and password on one VM and specific x509 client certs on another. Currently the server certificate configuration is per Host, which means that CNAMES like 'console.myvm.brightbox.es' and 'console.yourvm.brightbox.es' are not possible in the configuration. There's a lot of the qemu.conf that is arguably VM specific stuff. Having said that I think that pragmatically it is right to keep it out of the XML to prevent a nasty backward compatibility problem later on. Really all this stuff belongs in the RBAC structure because you want to apply a security profile to groups of VMS - possibly across Hosts. But RBAC is going to need a strategic sponsor from one of the distributions - probably as part of a system wide RBAC along Solaris lines.
Is this something that is forward-looking (ie. once we also have an access layer designed, will it still make sense to keep and honor the qemu.conf setting), or is it enough of a hack that we should instead try to resolve it via the qemu:commandline approach (where we've explicitly documented that use of the interface is the approved way to do hacks in the absence of proper libvirt support)?
It's as forward looking as all the other options in qemu.conf and at the same scope. The libvirt support proposed is Host wide - as it is with SASL, tls, etc. The VM specific stuff is done out of band using the hack channel. So the honouring problem is going to be exactly the same as the other options. Libvirt is going to need a deprecation policy to trim the warty stuff at some point. I think pragmatically it is best to stick with the existing qemu.conf approach because the code is there to handle it already. Regards Neil

On Thu, Jan 06, 2011 at 06:00:12PM +0000, Neil Wilson wrote:
Having looked through this, I'm thinking that the simplest thing that would be useful at the moment is simply to have an option in the /etc/libvirt/qemu.conf that adds the acl option to the vnc switch in qemu.
It means that user will have to manipulate the acls directly via the monitor command for the time being until the access layer is designed, but at least you would be able to use acls on a machine launched by libvirt ('change vnc' doesn't appear to activate acls unless the option is active on the command line to start with.).
I can't find a way of doing it with 'qemu:commandline' either - since it is an option to an existing switch.
So I'm thinking a new option in qemu.conf (vnc_acl) which would add ',acl' to the vnc switch on the qemu command. By default this would bar access to VNC until you'd issued monitor commands to manipulate the access lists.
That sounds reasonable, and would not adversely impact future work on enabling RBAC for VNC, since we likely want such a config option anyway.
The option only really makes sense if either vnc_tls_x509_verify or vnc_sasl is set as well, so it may be worth only activating 'acl' in the code if either of those two are also on.
If you enable 'acl' and don't add any rules to the ACL, then no one will be able to connect. So we can't automatically add ',acl' when either of those two options you mention are present, because that would break all existing usage. Regards, Daniel

On Fri, 2011-01-07 at 11:47 +0000, Daniel P. Berrange wrote:
The option only really makes sense if either vnc_tls_x509_verify or vnc_sasl is set as well, so it may be worth only activating 'acl' in the code if either of those two are also on.
If you enable 'acl' and don't add any rules to the ACL, then no one will be able to connect. So we can't automatically add ',acl' when either of those two options you mention are present, because that would break all existing usage.
Yes. I'm not suggesting automatically. That obviously wouldn't work. What I was asking is if vnc_acl=1 should it add it regardless of the other options or only when either 'vnc_sasl=1' or 'vnc_tls_x509_verify=1' as well. Regards Neil

On Fri, Jan 07, 2011 at 11:56:30AM +0000, Neil Wilson wrote:
On Fri, 2011-01-07 at 11:47 +0000, Daniel P. Berrange wrote:
The option only really makes sense if either vnc_tls_x509_verify or vnc_sasl is set as well, so it may be worth only activating 'acl' in the code if either of those two are also on.
If you enable 'acl' and don't add any rules to the ACL, then no one will be able to connect. So we can't automatically add ',acl' when either of those two options you mention are present, because that would break all existing usage.
Yes. I'm not suggesting automatically. That obviously wouldn't work. What I was asking is if vnc_acl=1 should it add it regardless of the other options or only when either 'vnc_sasl=1' or 'vnc_tls_x509_verify=1' as well.
I don't think it matters either way really, since its just shifting who is ignoring it. Either libvirtd ignores it when sasl/tls aren't active, or qemu will ignore it. Daniel

Hi, Here's the patch to add basic ACL support to QEMU within libvirt. Like SASL it's ignored by RHEL5's default qemu. Newer qemu picks it up as expected and you can manipulate the acls using 'virsh'. diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index ba41f80..7ab5eee 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -71,6 +71,15 @@ # vnc_sasl = 1 +# Enable the VNC access control lists. When switched on this will +# initially block all vnc users from accessing the vnc server. To +# add and remove ids from the ACLs you will need to send the appropriate +# commands to the qemu monitor as required by your particular version of +# QEMU. See the QEMU documentation for more details. +# +# vnc_acl = 1 + + # The default SASL configuration file is located in /etc/sasl2/ # When running libvirtd unprivileged, it may be desirable to # override the configs in this location. Set this parameter to diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7dd8e03..0ffeaab 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3542,8 +3542,11 @@ qemuBuildCommandLine(virConnectPtr conn, virCommandAddEnvPair(cmd, "SASL_CONF_DIR", driver->vncSASLdir); - /* TODO: Support ACLs later */ } + + if (driver->vncACL) + virBufferAddLit(&opt, ",acl"); + } else { virBufferVSprintf(&opt, "%d", def->graphics[0]->data.vnc.port - 5900); diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index e1502dc..806432d 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -204,6 +204,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, } } + p = virConfGetValue (conf, "vnc_acl"); + CHECK_TYPE ("vnc_acl", VIR_CONF_LONG); + if (p) driver->vncACL = p->l; + p = virConfGetValue (conf, "spice_tls"); CHECK_TYPE ("spice_tls", VIR_CONF_LONG); if (p) driver->spiceTLS = p->l; diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 83ddedd..3e7506d 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -85,6 +85,7 @@ struct qemud_driver { unsigned int vncTLS : 1; unsigned int vncTLSx509verify : 1; unsigned int vncSASL : 1; + unsigned int vncACL : 1; char *vncTLSx509certdir; char *vncListen; char *vncPassword;
participants (4)
-
Daniel P. Berrange
-
Eric Blake
-
Neil Wilson
-
Stefan Berger