Dmitri Pal wrote:
For some background see: http://www.freeipa.com/page/Access_Control
I took a look at the ACIs in DS. An ACI consists of 6 parts:
2) Users and Groups that the permission is granted to
3) The right (read, write, add, delete etc)
4) Target - an object against which the operation is performed
effectively an LDAP filter
5) Host - to have different rules for different clients (not interesting
6) Time when the rule is active (we will assume all).
I don't agree with this simplification. I'll try to comment in-line.
An ACI has 3 parts: the target, the permissions and who are you
granting the rights to (the bind rule). They affect more than just
users and groups. They affect anything in the system, or everything in
the system. They can control any object in the tree: users, groups,
hosts, hostgroups, netgroups, services, hbac, sudo, etc. or attributes
in any object.
There is also the placement of the ACI which controls what it affects.
We currently place all ACIs in the basedn of the tree (a necessary
simplification for now).
Our goal is to provide and easy to was to specify and manage ACIs vi UI
To accomplish this goal we need to provide a much simple abstraction
that can be reused for CLI and UI.
But first let us limit the ACI itself and leave only the parts that are
We really need Name, User/Group, Right and Target. We will not do
anything about Host and Time.
The right can be limited to:
write, add, delete.
Assume that any authenticated user can read, search and compare. We
should also assume that every user can manage a predefined subset of the
attributes in his entry. So we actually talking about three rights here:
add, delete and modify. For the sake of IPA v2 I am willing to go even
further in simplifying ACIs and say that there are three kinds of
* full control which translates into add an object, delete an object and
modify any attribute (this is a superuser mode)
* operational control which translates into add an object, delete an
object and modify a predefined subset of the attributes
* tuneup control which translates into add an object, delete an object
and modify a predefined subset of the attributes
Read is rather important, particularly for things like userPassword.
But yes, most acis will use either add, delete or write.
Don't assume that users can manage their own entries. This in itself
is an ACI that people will want to control.
I know we have to start somewhere with the rights abstractions but I
think these controls will be misunderstood and lead to problems.
Target is the most complex one it consists from the attributes and
filters. This is where an abstraction will be really helpful.
For this I suggest we create an ACI helper object class. The object
class will consist of the following attributes
name - a unique name of the helper like: User - full control, User -
standard management, User - limited access, etc
filter - single value string attribute that denotes a filter that allows
to identify the object the helper applies to
right - a multi value attribute that specifies rights, in out cases
based on the three operations above it will be either triplet add,
modify, delete or just modify
attributes - a multi value string attribute that stores the set of
attributes the ACI applies to
negation - a boolean flag that specified how to interpret the attribute
list i.e. are those the attributes that the rule applies to or they are
the attributes excluded from the rule.
here is the example:
dn: cn=User - full control, cn=ipaconfig, dc=somewhere, dc=com
cn: User - full control
I can see what you are trying to do but I am really, very strongly
against this. We can manage this data internally just as easily. I
think this is a recipe for getting the acis out of sync.
We actually have most of this implemented today. What it lacks is a
way to *output* an aci so it can be easily represented in a UI or on
the command line. That is where our focus should be.
I'm not sure I agree with the full/object/etc abstractions, I think
they would be easily abused/misunderstood because the definitions of
these aren't obvious (and don't actually grant what you might expect
You also have to understand how the tree is put together and how we
use it. For example, to add a user you need 3 acis:
- an aci to add a user to the tree
- an aci granting permission to write the password
- an aci granting permission to add a member to a group
Also, the 389-ds team has very strong recommended against using deny
ACIs in the past which is why I don't support them in the current plugin.
This is just an example and we can sort out the right names so do not
pick me if the attribute already exists and we should reuse it. It is
semantics at the moment.
Any ACI has a name. We need to allow advanced administrators (and
ourselves) to manage raw ACIs. On the other hand we need to allow
managing "simplified" ACIs in CLI and UI.
For this I suggest we use the following linking between the actual ACIs
and helper object:
The ACI name will store a DN of the helper object.
Let us look at the commands that associate ACIs with a "taskgroup":
ipa aci-add -aci='User - full control ' taskgroup
for this command the management plugin will will lookup helper object
and create an ACI based on the data stored in the helper object.
ipa aci-del -aci='User - full control' taskgroup
for this command the management plugin will find the aci that has the
name equal to the DN of the specified helper object.
ipa aci-find -aci='User - full control' taskgroup
will find the helper object by name, find an ACI by the DN of the helper
ipa aci-list taskgroup
will list the ACIs for the taskgroup. If the ACI name is a DN of a
helper object the contents of the helper object will be displayed. If
the ACI doe not map to the helper object then it will not be shown.
This way only the ACIs that are attached to helper objects will be
visible through the UI and CLI and custom CLIs created by IPA at the
installation or CLIs created manually by admins will be accessible
The helper object will be preloaded and predefined and thus not
replicated. This means that each new extension to IPA will need to add
its own helper entries. For SUDO for example it will be probably couple
entries. One to do everything and another to modify a subset of the
attributes in the rule.
ACIs are ACIs. There is nothing a plugin would add except perhaps a
part of the DIT. See the type enum currently in the plugin.
What is good about this approach is that later we can add an interface
to create helper objects. Those are much better structured and would be
easier to manage. For example instead of actually typing filter we can
have a selectable list of the objects like "user", "group", "sudo",
"hbac rule" etc. (The mapping between name and actual filter might be
stored in another kind of the helper object - but we will get there
later). Yes that would mean that the admin would have to create a helper
object then to create ACI using this object, then combine the task into
role but it is manageable because the complex task is decomposed into
logical parts. I do not suggest that we do it in v2 but I think it is a
way to go in general in future.
We actually have these objects implemented in the current plugin. The
following aci commands all work today:
You can say "This taskgroup can add users":
ipa aci-add 'Add Users' --type=user --taskgroup=add_users
This creates the aci:
3.0;acl "Add Users";allow (add) groupdn =
It will even create the taskgroup for you if it doesn't already exist.
Right now I just have defined users, groups and hosts but it is
trivial to add the others. I couldn't think of a reason the would want
this since we supply pre-canned versions of add/delete/modify for
those on install, but I can add them as options if desired.
We also need to cover v1-style delegation: group A can write
attributes of group B.
Secretaries can write the mailing address of engineers:
ipa aci-add --attrs=streetAddress,postalCode,c,l,st
--memberof=engineering --group=secretaries --permissions=write
"Secretaries can write engineering addresses"
(targetattr = "streetAddress || postalCode || c || l ||
3.0;acl "Secretaries can write engineering addresses";allow (write)
Or even simple things like "I want my engineers to be able to add hosts"
ipa aci-add --type=host --permissions=write --group=engineering
'Engineers can add hosts'
3.0;acl "Engineers can add hosts";allow (write) groupdn =
Ideally these would be mostly done through existing taskgroups instead:
ipa taskgroup-add-member --groups=engineering addhosts
Or even more preferably via rolegroups:
ipa rolegroup-add-member --groups=engineering hostadmin
The aci's here are actual output from the plugin. This is where we
need the work. I already have an internal abstraction of the acis so I
can operate on them. I merely need to display this instead of the aci
string and I think we'll be good to go. Some way to manage the
attribute list without requiring one to type the whole thing would be
Hope this approach does not have much flaws. Yes it will require some
work in the ACI space but I hope it is not a huge rework.
This would represent a tremendous amount of work. I think we would be
better served fixing the way that acis are output so the UI (and by
extension cli) can better represent the data to users. The --raw
option can display the raw aci.
Working with acis is always going to be a bit of a nasty business
because by definition you have to deal directly with LDAP attribute
names, the DIT and how we create and manage objects in the framework.