[Libvir] [Suggestion] The "ISP scenario"

This pattern has come up a few times now: ISP provides a Xen hosting service to customers. ISP wants to provide some basic statistics to their customers. The statistics could be provided to a customer through the libvirt remote protocol, eg: customer$ virsh -c xen://dom0/ dominfo mydom But the problem with this is that (as libvirt is currently architected) _any_ access to dom0, if it authenticates, gives access to information from all domains. We've previously discussed adding access control using something like SELinux (see for example: https://www.redhat.com/archives/libvir-list/2007-August/msg00030.html) but nothing much has come of it so far. But can we solve the single common case above directly, without thwarting our ability to solve the bigger picture later? My suggestion is that we add an option to /etc/libvirt/libvirtd.conf, something like: tls_restrict_dn: [ "DN1", "name:customer1", "DN2", "uuid:12345678", "DN3", "*" ] with the meaning that (presumably a customer) connecting with certificate DN1 could only find out information about the domain "customer1", DN2 similarly, DN3 is a privileged client, and any other DN would be rejected. (Compare and contrast to tls_allowed_dn_list: http://libvirt.org/remote.html#Remote_libvirtd_configuration) An implementation of this would modify the call to virConnectOpen to add an additional flag (or call?) allowing the access control to be passed, and this would have to be checked in the relevant virDomain* calls. This is not dissimilar to how read-only connections are implemented in libvirtd currently. I would also suggest as a matter of course that we modify all public API calls in src/libvirt.c to add a call to a generic permission checking routine, for example: int virDomainSuspend(virDomainPtr domain) { virConnectPtr conn; DEBUG("domain=%p", domain); if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } + if (!check_permission (domain, OP_SUSPEND)) return -1; With the initial implementation of check_permission just doing the VIR_CONNECT_RO check to start with, but able to do other checks in future. Also relevant to this is SASL support, see: https://www.redhat.com/archives/libvir-list/2007-November/msg00005.html since AIUI this changes the possible formats for Distinguished Names, or could even make DNs irrelevant. Rich. -- Emerging Technologies, Red Hat - http://et.redhat.com/~rjones/ Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SL4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 03798903

On Mon, Nov 19, 2007 at 02:56:10PM +0000, Richard W.M. Jones wrote:
This pattern has come up a few times now:
ISP provides a Xen hosting service to customers. ISP wants to provide some basic statistics to their customers. The statistics could be provided to a customer through the libvirt remote protocol, eg:
customer$ virsh -c xen://dom0/ dominfo mydom
But the problem with this is that (as libvirt is currently architected) _any_ access to dom0, if it authenticates, gives access to information from all domains.
We've previously discussed adding access control using something like SELinux (see for example: https://www.redhat.com/archives/libvir-list/2007-August/msg00030.html) but nothing much has come of it so far.
But can we solve the single common case above directly, without thwarting our ability to solve the bigger picture later?
My suggestion is that we add an option to /etc/libvirt/libvirtd.conf, something like:
tls_restrict_dn: [ "DN1", "name:customer1", "DN2", "uuid:12345678", "DN3", "*" ]
with the meaning that (presumably a customer) connecting with certificate DN1 could only find out information about the domain "customer1", DN2 similarly, DN3 is a privileged client, and any other DN would be rejected.
Hum, that still sounds very specific to me, it's just one special case that we need to keep in mind when designing the general solution.
(Compare and contrast to tls_allowed_dn_list: http://libvirt.org/remote.html#Remote_libvirtd_configuration)
An implementation of this would modify the call to virConnectOpen to add an additional flag (or call?) allowing the access control to be passed, and this would have to be checked in the relevant virDomain* calls.
This is not dissimilar to how read-only connections are implemented in libvirtd currently.
Understood
I would also suggest as a matter of course that we modify all public API calls in src/libvirt.c to add a call to a generic permission checking routine, for example:
int virDomainSuspend(virDomainPtr domain) { virConnectPtr conn; DEBUG("domain=%p", domain);
if (!VIR_IS_CONNECTED_DOMAIN(domain)) { virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); return (-1); } - if (domain->conn->flags & VIR_CONNECT_RO) { - virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); - return (-1); - } + if (!check_permission (domain, OP_SUSPEND)) return -1;
With the initial implementation of check_permission just doing the VIR_CONNECT_RO check to start with, but able to do other checks in future.
Yes that to me is uncontroversial, we need to plug finer grained auth at each call level and not just at Connect time (though I still think having a specific ConnectReadOnly method makes sense), now the big question is how do we actually plug the policy checks in (and also what).
Also relevant to this is SASL support, see: https://www.redhat.com/archives/libvir-list/2007-November/msg00005.html since AIUI this changes the possible formats for Distinguished Names, or could even make DNs irrelevant.
I looked at the SASL patches, the checking there seems to be done in the remote code front-end (assuming I understood this correctly) rather than in the top level entry point (which are presumably only called on the client side. Still it makes sense to be able to do finer access control locally (or on the client side) that doesn't prevent the approach needed by the SASL patch. Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

On Mon, Nov 19, 2007 at 02:56:10PM +0000, Richard W.M. Jones wrote:
This pattern has come up a few times now:
ISP provides a Xen hosting service to customers. ISP wants to provide some basic statistics to their customers. The statistics could be provided to a customer through the libvirt remote protocol, eg:
customer$ virsh -c xen://dom0/ dominfo mydom
But the problem with this is that (as libvirt is currently architected) _any_ access to dom0, if it authenticates, gives access to information from all domains.
We've previously discussed adding access control using something like SELinux (see for example: https://www.redhat.com/archives/libvir-list/2007-August/msg00030.html) but nothing much has come of it so far.
But can we solve the single common case above directly, without thwarting our ability to solve the bigger picture later?
My suggestion is that we add an option to /etc/libvirt/libvirtd.conf, something like:
tls_restrict_dn: [ "DN1", "name:customer1", "DN2", "uuid:12345678", "DN3", "*" ]
with the meaning that (presumably a customer) connecting with certificate DN1 could only find out information about the domain "customer1", DN2 similarly, DN3 is a privileged client, and any other DN would be rejected.
(Compare and contrast to tls_allowed_dn_list: http://libvirt.org/remote.html#Remote_libvirtd_configuration)
An implementation of this would modify the call to virConnectOpen to add an additional flag (or call?) allowing the access control to be passed, and this would have to be checked in the relevant virDomain* calls.
This is not dissimilar to how read-only connections are implemented in libvirtd currently.
I would also suggest as a matter of course that we modify all public API calls in src/libvirt.c to add a call to a generic permission checking routine, for example:
Yep, this example as you show sounds like a good idea regardless. Basically any API call will have a triple of a (object, subject, operation) to be checked. In the latest update of the SASL patches which I've not yet posted there is a a subject associated with all remote connections. This is basically the SASL authenticated username, either 'dan', or 'dan@REALM' depending on the particular auth scheme used.
With the initial implementation of check_permission just doing the VIR_CONNECT_RO check to start with, but able to do other checks in future.
Seems reasonable. Depending on how PolicyKit develops in the future, it may well be possible for us to turn 'check_permission' into a simple policykit call. Or we may end up taking to some API which does an SELinux check, or something ele. It'll be good to have this all isolated in one place now.
Also relevant to this is SASL support, see: https://www.redhat.com/archives/libvir-list/2007-November/msg00005.html since AIUI this changes the possible formats for Distinguished Names, or could even make DNs irrelevant.
The code I've got can run SASL over both plain & TLS connections, so we could conceivably have both a DN from the cert, and a SASL username. It shouldn't really matter for our internal APIs though - its just an opaque string representing the subject. If we have SASL username, use that, otherwise just fallback to the Cert DN. Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
participants (3)
-
Daniel P. Berrange
-
Daniel Veillard
-
Richard W.M. Jones