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 :|