FreeIPA has quite flexible system to define access rights for any resources in the LDAP store. The system consists of three different parts:

  • a permission object
  • a privilege object, and
  • a role object.

Permission object specifies the target of the access grant: what attributes of which objects in LDAP would be subject of the checks.

A privilege allows to combine several permissions together in a logical task. A role defines who can have access to privileges.

An example below is a somewhat complex use of the permission system to allow groups of administrators to manage specific hosts. We want administrators in group ‘my-admins’ to manage hosts in ‘my-hostgroup’ but otherwise have no other privileges.

Let’s start with a host group ‘my-hostgroup’:

# ipa hostgroup-add my-hostgroup
-----------------------------
Added hostgroup "my-hostgroup"
-----------------------------
  Host-group: my-hostgroup

And with a group ‘my-admins’:

# ipa group-add my-admins
-----------------------
Added group "my-admins"
-----------------------
  Group name: my-admins
  GID: 903200040

A member of ‘my-admins’ should be able to edit all attributes of the hosts in the host group ‘my-hostgroup’.

To manage permissions, use ipa permission family of commands. You need to create a basic permission which applies to hosts:

# ipa permission-add manage-my-hostgroup --right=all --bindtype=permission --type=host
--------------------------------------
Added permission "manage-my-hostgroup"
--------------------------------------
  Permission name: manage-my-hostgroup
  Granted rights: all
  Bind rule type: permission
  Subtree: cn=computers,cn=accounts,dc=ipa,dc=ad,dc=test
  Type: host
  Permission flags: V2, SYSTEM

A permission automatically generates an access control item (ACI) in the LDAP. To check all low-level details of the permission, use --all and --raw options:

# ipa permission-show --all --raw manage-my-hostgroup
  dn: cn=manage-my-hostgroup,cn=permissions,cn=pbac,dc=ipa,dc=ad,dc=test
  cn: manage-my-hostgroup
  ipapermright: all
  ipapermbindruletype: permission
  ipapermlocation: cn=computers,cn=accounts,dc=ipa,dc=ad,dc=test
  ipapermtargetfilter: (objectclass=ipahost)
  ipapermissiontype: V2
  ipapermissiontype: SYSTEM
  aci: (targetfilter = "(objectclass=ipahost)")
       (version 3.0; acl "permission:manage-my-hostgroup";
                     allow (all)
                     groupdn = "ldap:///cn=manage-my-hostgroup,cn=permissions,cn=pbac,dc=ipa,dc=ad,dc=test";)
  objectclass: ipapermission
  objectclass: top
  objectclass: groupofnames
  objectclass: ipapermissionv2

As you can see, it applies to hosts: cn=computers,cn=accounts,$SUFFIX subtree, and target filter is set to (objectclass=ipahost). So it would apply to any host. To further limit the permission, you have to add more target filters.

To define raw target filter, we need to know a DN of the hostgroup that will be our target limit:

# ipa hostgroup-show --raw --all my-hostgroup
  dn: cn=my-hostgroup,cn=hostgroups,cn=accounts,dc=ipa,dc=ad,dc=test
  cn: my-hostgroup
  ipaUniqueID: 6d8c72f2-6e6d-11e6-b9e4-525400bf08fe
  mepManagedEntry: cn=my-hostgroup,cn=ng,cn=alt,dc=ipa,dc=ad,dc=test
  objectClass: ipahostgroup
  objectClass: ipaobject
  objectClass: nestedGroup
  objectClass: groupOfNames
  objectClass: top
  objectClass: mepOriginEntry

Using the DN of the my-hostgroup, we can now add a filter to the permission:

# ipa permission-mod manage-my-hostgroup --filter '(memberOf=cn=my-hostgroup,cn=hostgroups,cn=accounts,dc=ipa,dc=ad,dc=test)'
-----------------------------------------
Modified permission "manage-my-hostgroup"
-----------------------------------------
  Permission name: manage-my-hostgroup
  Granted rights: all
  Bind rule type: permission
  Subtree: cn=computers,cn=accounts,dc=ipa,dc=ad,dc=test
  Extra target filter: (memberOf=cn=my-hostgroup,cn=hostgroups,cn=accounts,dc=ipa,dc=ad,dc=test)
  Type: host
  Permission flags: V2, SYSTEM

Take a look at the permission in detail:

# ipa permission-show --all --raw manage-my-hostgroup
  dn: cn=manage-my-hostgroup,cn=permissions,cn=pbac,dc=ipa,dc=ad,dc=test
  cn: manage-my-hostgroup
  ipapermright: all
  ipapermbindruletype: permission
  ipapermlocation: cn=computers,cn=accounts,dc=ipa,dc=ad,dc=test
  ipapermtargetfilter: (objectclass=ipahost)
  ipapermtargetfilter: (memberOf=cn=my-hostgroup,cn=hostgroups,cn=accounts,dc=ipa,dc=ad,dc=test)
  ipapermissiontype: V2
  ipapermissiontype: SYSTEM
  aci: (targetfilter = "(&(memberOf=cn=my-hostgroup,cn=hostgroups,cn=accounts,dc=ipa,dc=ad,dc=test)(objectclass=ipahost))")
       (version 3.0;acl "permission:manage-my-hostgroup";
        allow (all) groupdn = "ldap:///cn=manage-my-hostgroup,cn=permissions,cn=pbac,dc=ipa,dc=ad,dc=test";)
  objectclass: ipapermission
  objectclass: top
  objectclass: groupofnames
  objectclass: ipapermissionv2

Our ACI says: “Allow any changes to be done in all objects of objectclass ipahost that belong to a host group my-hostgroup to members of the permission group manage-my-hostgroup

Now you can add the manage-my-hostgroup permission to a new privilege and add that privilege to a role, and then assign users of the group my-admins to that role. Those users will be able to manage hosts targeted by the permission.

Start with a privilege:

# ipa privilege-add 'manage-hostgroup-my-hostgroup'
-----------------------------------------------
Added privilege "manage-hostgroup-my-hostgroup"
-----------------------------------------------
  Privilege name: manage-hostgroup-my-hostgroup

# ipa privilege-add-permission 'manage-hostgroup-my-hostgroup'
[permission]: manage-my-hostgroup
  Privilege name: manage-hostgroup-my-hostgroup
  Permissions: manage-my-hostgroup
-----------------------------
Number of permissions added 1
-----------------------------

Finally, create a role and add a privilege to it, and then add members that could use the privilege:

# ipa role-add role-manage-hostgroup-my-hostgroup
-----------------------------------------------
Added role "role-manage-hostgroup-my-hostgroup"
-----------------------------------------------
  Role name: role-manage-hostgroup-my-hostgroup

# ipa role-add-privilege role-manage-hostgroup-my-hostgroup
[privilege]: manage-hostgroup-my-hostgroup
  Role name: role-manage-hostgroup-my-hostgroup
  Privileges: manage-hostgroup-my-hostgroup
----------------------------
Number of privileges added 1
----------------------------

# ipa role-add-member role-manage-hostgroup-my-hostgroup --groups=my-admins
  Role name: role-manage-hostgroup-my-hostgroup
  Member groups: my-admins
  Privileges: manage-hostgroup-my-hostgroup
-------------------------
Number of members added 1
-------------------------

If we look at the original permission, we can see it is now an indirect member of a role:

# ipa permission-show manage-my-hostgroup
  Permission name: manage-my-hostgroup
  Granted rights: all
  Bind rule type: permission
  Subtree: cn=computers,cn=accounts,dc=ipa,dc=ad,dc=test
  Extra target filter: (memberOf=cn=my-hostgroup,cn=hostgroups,cn=accounts,dc=ipa,dc=ad,dc=test)
  Type: host
  Permission flags: V2, SYSTEM
  Granted to Privilege: manage-hostgroup-my-hostgroup
  Indirect Member of roles: role-manage-hostgroup-my-hostgroup

When user is added to the my-admins group, it automatically assumes a role that allows to manage the host group:

# ipa user-add hadmin
First name: Joe
Last name: Doe
-------------------
Added user "hadmin"
-------------------
  User login: hadmin
  First name: Joe
  Last name: Doe
  Full name: Joe Doe
  Display name: Joe Doe
  Initials: JD
  Home directory: /home/hadmin
  GECOS: Joe Doe
  Login shell: /bin/sh
  Principal name: hadmin@IPA.AD.TEST
  Principal alias: hadmin@IPA.AD.TEST
  Email address: hadmin@ipa.ad.test
  UID: 903200041
  GID: 903200041
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

# ipa group-add-member my-admins --users=hadmin
  Group name: my-admins
  GID: 903200040
  Member users: hadmin
  Roles: role-manage-hostgroup-my-hostgroup
-------------------------
Number of members added 1
-------------------------

In real life scenario we would probably like to tune our permission a bit more. For example, we definitely don’t want to allow full access to all attributes of the host – if users can write to objectclass attribute, they can turn that host into anything else in LDAP. But before tuning it, we need to see if our permission actually works:

# kinit hadmin
Password for hadmin@IPA.AD.TEST:

# ipa host-mod my-host --random
ipa: ERROR: Insufficient access: Insufficient 'write' privilege to the 'userPassword' 
            attribute of entry 'fqdn=my-host.ipa.ad.test,cn=computers,cn=accounts,dc=ipa,dc=ad,dc=test'.

Oops, it does not work – we cannot write to a userPassword attribute of the host. What is wrong? To answer this question we need to look at the documentation of the LDAP server FreeIPA builds upon: 389-ds. Red Hat Directory Server Administration Guide says the following in the section “Targeting Entries or Attributes Using LDAP Filters”:

Note Although using LDAP filters can be useful when you are targeting entries and attributes that are spread across the directory, the results are sometimes unpredictable because filters do not directly name the object for which you are managing access. The set of entries targeted by a filtered ACI is likely to change as attributes are added or deleted. Therefore, if you use LDAP filters in ACIs, you should verify that they target the correct entries and attributes by using the same filter in an ldapsearch operation.

The documentation doesn’t tell this explicitly, but when targetattr is missing, the default for matching target attributes when matching with target filter for modification is none, not *. This is done to deny modrdn (entry rename).

To allow modification of the host entries, we need to list attributes which can be modified by our host group admins. The list below is an example only: it allows to set meta-data about the host, change one-time enrollment password, assigned ID view, add certificates and SSH public keys. One needs to carefully review what attributes should be allowed to modify.

# kinit admin
Password for admin@IPA.AD.TEST: 

# ipa permission-mod manage-my-hostgroup --attrs={'userPassword','description','l',\
               'nshardwareplatform','nsosversion','usercertificate','userclass',\
               'macaddress','ipaassignedidview','ipasshpubkey'}
-----------------------------------------
Modified permission "manage-my-hostgroup"
-----------------------------------------
  Permission name: manage-my-hostgroup
  Granted rights: all
  Effective attributes: description, ipaassignedidview, ipakrbauthzdata, ipasshpubkey,
                        l, macaddress, nshardwareplatform, nsosversion, userPassword,
                        usercertificate, userclass
  Bind rule type: permission
  Subtree: cn=computers,cn=accounts,dc=ipa,dc=ad,dc=test
  Extra target filter: (memberOf=cn=my-hostgroup,cn=hostgroups,cn=accounts,dc=ipa,dc=ad,dc=test)
  Type: host
  Permission flags: V2, SYSTEM
  Granted to Privilege: manage-hostgroup-my-hostgroup
  Indirect Member of roles: role-manage-hostgroup-my-hostgroup

With these changes, our admin can now set a random one-time password:

# kinit hadmin
Password for hadmin@IPA.AD.TEST:

# ipa host-mod my-host --random
-----------------------
Modified host "my-host"
-----------------------
  Host name: my-host.ipa.ad.test
  Random password: 5Krkbj_eW7UR@SUxj0lx22
  Principal name: host/my-host.ipa.ad.test@IPA.AD.TEST
  Principal alias: host/my-host.ipa.ad.test@IPA.AD.TEST
  Password: True
  Member of host-groups: my-hostgroup
  Keytab: False
  Managed by: my-host.ipa.ad.test

However, this is not all. The permission we created above doesn’t answer a very important question: how the host my-host would appear in the host group? We surely want to be able to add and remove hosts from the host group. But if we create a permission that allows per-hostgroup admins to add and remove members of the host group at will, they could take over any host – by simply adding it in the host group they manage.

An easiest way to solve this problem, no surprise, is organizational: do not give host group admin rights to include hosts to the hostgroup or delete them, only allow them to manage what’s in the host group.

A separation of rights requires to create a separate permission for ‘add’/’del’ rights against ‘member’ attribute that would allow to include/remove hosts. That’s easy but it would not allow us to limit what hosts could be added/removed from the host group.

Unfortunately, to make that possible, permission-add/permission-mod should be extended to allow specifying target attribute’s values like described in the RHDS Administration Guide.

Even then to define something like this, we’d need to have specific naming of hosts to be able to specify a pattern as a ‘member’ attribute value.

An alternative is to use automembership rules, defined with ipa automember family of commands. It might work with predictable host names but would probably be hard to implement in case of host names coming out of existing cloud provider where you don’t have control over the undercloud.

This is why I’m saying it is an organizational issue, not really a technical one.