On Wed, Nov 23, 2011 at 06:17:46PM +0100, Michal Privoznik wrote: > Hi all, > > I'd like to implement this new feature for libvirt. However, I think we > should settle down on design first. My biggest concern is choosing the > right level on on which ACLs will be implemented. Should be interested > only in (user, API), or with more granularity (user, API, API's parameters)? > Or should we take the RBAC path? > How should we even identify and authorize users? > > My initial though is to create framework which can be used then to > implement ACLs on any level we want. > > What's our opinion? I have been working on the plan & investigating various implementation details of this myself over the past few months. Here is the initial design mail I had on the subject: https://www.redhat.com/archives/libvir-list/2011-June/msg00244.html In terms of level of ACLs, this isn't something that can be done at the "API" entry point level, since it is only secure to perform checks after the internal object has been obtained by the driver: eg, consider a virDomainPtr instance containing name=foo, uuid=c7b3edbd-edaf-9455-926a-d65c16db1800 Now, the QMEU driver does virDomainObjPtr vm = virDomainObjLookupByUUID(c7b3edbd-edaf-9455-926a-d65c16db1800) And could in theory get back a virDomainObjPtr instance containing name=bar, uuid=c7b3edbd-edaf-9455-926a-d65c16db1800 If our access control checks specify "allow { name=foo }", then we should *deny* access, because the actual object we're about to use has name=bar. If we did the checks at the API entry point level, we would mistakenly allow access. In addition "API" is really the wrong level of granularity for expressing the checks. Several separate APIs will need to be covered under the same check, while at the same time, one API might require multiple checks. So what we actually need to do is perform checks, at time of use (ie inside each driver), on the triple (subject, object, operation). As per the design mail above, we need to consider two implementations of the access controllers. One is SELinux based and integrates with sVirt where, and here 'subject' will be the SELinux context of the client application which we obtain over the UNIX socket, or over the TCP socket using IPSec. The other general purpose RBAC system will be based around the authenticated client identity. If SASL was in use, then the SASL username (eg Kerberos principle). If SSL was in use then the identity is the x509 client DName from the certificate. If the socket is a UNIX socket, we also get th UNIX userid/groupid, regardless of auth mechanism. For SELinux, the object will be identified by the SELinux context of the object being operated upon, or the context of the libvirtd daemon if there is no context for the object itself. For non-SELinux controller, the object will be identified by the corresponding unique attributes, eg UUID, Name, path. For SELinux, authorization will be done through the SELinux policy. For non-SELinux controller, we will invent a configuration file format that can express RBAC. eg, something like role engineeringadmins { user jim; user fred; user ralph; }; objectset engineeringvms { vm name=vmapache1; vm name=vmapache2; vm name=vmbrew1; }; objectset engineeringstorage { pool name=engnfs1; pool name=engiscsi2; } actionset manage { actions start stop read read_secure ...more...; } permission { role engineeringadmins; objectset engineeringvms; actionset manage; } permission { role engineeringadmins; objectset engineeringstorage; actionset manage; } NB this is just a rough idea of a config format - ideally we will actually use the existing virConfPtr classes, so the data format will look a bit different. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list