Creating permissions in FreeIPA
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.