{scrollbar}

Basic authorization

This section describes the default authorization functionality of ApacheDS 1.0, which is very simple. On the other hand, it is inadequate for most serious deployments. Therefore a basic example to the "real" authorization subsystem is provided as well.

22list

What is authorization?

After authentication of a user or an application (or more generally an LDAP client) against the directory server (or attaining anonymous access respectively), certain LDAP operations will be granted or rejected, according to configuration and certain rules. This process of granting access is called authorization.

Authorization for directory operations is not strictly standardized in the LDAP world, RFC 2829 describes various scenarios and concepts, but does not enforce a concrete implementation. Thus each product comes with its own authorization feature. So does ApacheDS. A powerful authorization subsystem is provided since version 0.9.3, but disabled as a default.

Authorization for directory operations vs. group membership

In order to accomplish their authorization functionality, software components often take advantage of LDAP groups stored within the directory. groupOfNames and groupOfUniqueNames are common object classes for groups entries; they contain the DNs of their members (users, other groups) as attribute values.

In order to illustrate this, the "Seven Seas" example partition contains such group entries below "ou=groups,o=sevenSeas". Here the entry of a group describing the HMS Bounty crew (before the mutiny) in LDIF format.

none dn: cn=HMS Bounty,ou=crews,ou=groups,o=sevenSeas objectclass: groupOfUniqueNames objectclass: top cn: HMS Bounty uniquemember: cn=William Bligh,ou=people,o=sevenSeas uniquemember: cn=Fletcher Christian,ou=people,o=sevenSeas uniquemember: cn=John Fryer,ou=people,o=sevenSeas ...

In such a scenario, a user, who is directly or indirectly member of a certain group is permitted to do something. The software component acts as a normal LDAP client and determines group belonging with the help of ordinary search operations. This is widely used but has nothing to do with the authorization for directory operations as described in this section (except that the client needs the permission to search the data). Learn more about best practices in this area in the article Practices in Directory Groups. Further examples in this guide are the Tomcat and Apache HTTPD integration sections.

Default authorization behavior for directory operations

Without access controls enabled all entries are accessible and alterable by all: even anonymous users. There are however some minimal built-in rules for protecting users and groups within the server without having to turn on the ACI subsystem.

Sample data within "ou=users,ou=system"

In addition to our brave sailors below ou=people,o=sevenSeas, assume the following to entries present within ou=users,ou=system:

dn: cn=Tori Amos,ou=users,ou=system objectclass: person objectclass: top sn: Amos cn: Tori Amos userpassword: amos dn: cn=Kate Bush,ou=users,ou=system objectclass: person objectclass: top sn: Bush cn: Kate Bush userpassword: bush

They are used in the following examples, in conjunction with o=sevenSeas, to describe the default authorization rules.

Rules and sample operations

Without ACIs the server automatically protects, hides, the admin user from everyone but the admin user. Here a sample search operation in order to demonstrate this protection. The same command is submitted three times with different users.

$ ldapsearch -h zanzibar -p 10389 -D "uid=admin,ou=system" -w secret \\ -b "ou=system" -s one "(uid=admin)" dn version: 1 dn: uid=admin,ou=system $ ldapsearch -h zanzibar -p 10389 -D "cn=William Bush,ou=people,o=sevenSeas" -w pass \\ -b "ou=system" -s one "(uid=admin)" dn $ ldapsearch -h zanzibar -p 10389 -D "cn=Tori Amos,ou=users,ou=system" -w amos \\ -b "ou=system" -s one "(uid=admin)" dn $

Users cannot see other user entries under the 'ou=users,ou=system' entry. So placing new users there automatically protects them. Placing new users anywhere else exposes them.

$ ldapsearch -h zanzibar -p 10389 -D "uid=admin,ou=system" -w secret \\ -b "ou=users,ou=system" -s one "(objectclass=*)" dn version: 1 dn: cn=Tori Amos,ou=users,ou=system dn: cn=Kate Bush,ou=users,ou=system $ ldapsearch -h zanzibar -p 10389 -D "cn=Kate Bush,ou=users,ou=system" -w bush \\ -b "ou=users,ou=system" -s one "(objectclass=*)" dn version: 1 dn: cn=Kate Bush,ou=users,ou=system $ ldapsearch -h zanzibar -p 10389 -D "cn=William Bush,ou=people,o=sevenSeas" -w pass \\ -b "ou=users,ou=system" -s one "(objectclass=*)" dn $ ldapsearch -h zanzibar -p 10389 -D "cn=William Bush,ou=people,o=sevenSeas" -w pass \\ -b "ou=people,o=sevenSeas" -s one "(objectclass=*)" dn version: 1 dn: cn=Horatio Hornblower,ou=people,o=sevenSeas dn: cn=William Bush,ou=people,o=sevenSeas dn: cn=Thomas Masterman Hardy,ou=people,o=sevenSeas dn: cn=Cornelius Buckley,ou=people,o=sevenSeas dn: cn=William Bligh,ou=people,o=sevenSeas ... $

Groups defined using groupOfNames or groupOfUniqueNames under the 'ou=groups,ou=system' are also protected from access or alteration by anyone other than the admin user. Again this protection is not allowed anywhere else but under these entries.

Is this sufficient?

For simple configurations the described rules should provide adequate protection but it lacks flexibility. For advanced configurations users should enable the ACI subsystem. This however shuts down access to everything by everyone except the admin user which bypasses the ACI subsystem. Directory administrators should look at the documentation on how to specify access control information in the Advanced User's Guide.

Simple example for the ACI subsystem

As an appetizer for the stunning ACI subsystem (ACI = access control item) within ApacheDS, we provide a simple yet realistic example. It manifests the following requirements

Requirements met

  1. Suffix "o=sevenSeas" used as Access Control Specific Area
  2. User "cn=Horatio Nelson,ou=people,o=sevenSeas" should be able to perform all operations (delete, add, ...) below the base "o=sevenSeas"
  3. Other users and anonymous users should only be able to search and compare (no add, modify etc.)
  4. Other users and anonymous users should not be able to read the userPassword attribute

Enable the ACI Subsystem

The authorization (ACI) subsystem is disabled by default. If you use the server standalone configured with a server.xml file, you can enable it by changing the value for property accessControlEnabled in the Spring bean definition for bean configuration, as depicted in the following fragment:

xml <bean id="configuration" class="org.apache.directory.server.configuration.MutableServerStartupConfiguration"> ... <property name="accessControlEnabled" value="true" /> ... </bean>

A restart of the server is necessary for this change to take effect.

Further configuration tasks to perform afterwards

1. Create an operational attribute administrativeRole with value "accessControlSpecificArea" in the entry "o=sevenSeas".
2. Create a subentry subordinate to "o=sevenSeas" to grant all operations' permissions to "cn=Horatio Nelson,ou=people,o=sevenSeas", who acts as directory manager

The subentry should contain the following attributes and values:

cn="sevenSeasAuthorizationRequirementsACISubentry" subtreeSpecification="{}" prescriptiveACI="{ identificationTag "directoryManagerFullAccessACI", precedence 11, authenticationLevel simple, itemOrUserFirst userFirst: { userClasses { name { "cn=Horatio Nelson,ou=people,o=sevenSeas" } }, userPermissions { { protectedItems { entry, allUserAttributeTypesAndValues }, grantsAndDenials { grantAdd, grantDiscloseOnError, grantRead, grantRemove, grantBrowse, grantExport, grantImport, grantModify, grantRename, grantReturnDN, grantCompare, grantFilterMatch, grantInvoke } } } } }"

3. A new attribute value should added to the previously created Subentry's prescriptiveACI attribute to grant search and compare permissions to all users.

The new value:

prescriptiveACI="{ identificationTag "allUsersSearchAndCompareACI", precedence 10, authenticationLevel simple, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems { entry, allUserAttributeTypesAndValues }, grantsAndDenials { grantRead, grantBrowse, grantReturnDN, grantCompare, grantFilterMatch, grantDiscloseOnError } } } } }"

4. A new attribute value should added to the previously created Subentry's prescriptiveACI attribute to deny search and compare permissions for userPassword attribute to all users.

The new value:

prescriptiveACI="{ identificationTag "preventAllUsersFromReadingUserPasswordAttributeACI", precedence 10, authenticationLevel simple, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems { attributeType { userPassword } }, grantsAndDenials { denyRead, denyCompare, denyFilterMatch } } } } }"

The two values given in 3 and 4 can be combined in a single value as:

prescriptiveACI="{ identificationTag "allUsersACI", precedence 10, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems { entry, allUserAttributeTypesAndValues }, grantsAndDenials { grantRead, grantBrowse, grantReturnDN, grantCompare, grantFilterMatch, grantDiscloseOnError } }, { protectedItems { attributeType { userPassword } }, grantsAndDenials { denyRead, denyCompare, denyFilterMatch } } } } }"

LDIF for this configuration

The following LDIF file (authz_sevenSeas.ldif) provides a set of changes made to directory entries in the "Seven Seas" data. In total it performs the steps described above.

none # File authz_sevenSeas.ldif # # Create an operational attribute "administrativeRole" # with value "accessControlSpecificArea" in the entry "o=sevenSeas". # dn: o=sevenSeas changetype: modify add: administrativeRole administrativeRole: accessControlSpecificArea # Create a subentry subordinate to "o=sevenSeas" to grant all operations' permissions # to "cn=Horatio Nelson,ou=people,o=sevenSeas", to grant search and compare permissions # to all users and to deny search and compare permissions for userPassword attribute to all users. # dn: cn=sevenSeasAuthorizationRequirementsACISubentry,o=sevenSeas changetype: add objectclass: top objectclass: subentry objectclass: accessControlSubentry cn: sevenSeasAuthorizationRequirementsACISubentry subtreeSpecification: {} prescriptiveACI: { identificationTag "directoryManagerFullAccessACI", precedence 11, authenticationLevel simple, itemOrUserFirst userFirst: { userClasses { name { "cn=Horatio Nelson,ou=people,o=sevenSeas" } }, userPermissions { { protectedItems { entry, allUserAttributeTypesAndValues }, grantsAndDenials { grantAdd, grantDiscloseOnError, grantRead, grantRemove, grantBrowse, grantExport, grantImport, grantModify, grantRename, grantReturnDN, grantCompare, grantFilterMatch, grantInvoke } } } } } prescriptiveACI: { identificationTag "allUsersACI", precedence 10, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems { entry, allUserAttributeTypesAndValues }, grantsAndDenials { grantRead, grantBrowse, grantReturnDN, grantCompare, grantFilterMatch, grantDiscloseOnError } }, { protectedItems { attributeType { userPassword } }, grantsAndDenials { denyRead, denyCompare, denyFilterMatch } } } } }

To apply this configuration to the sample data partition, you can perform an ldapmodify with the LDIF as agrument:

$ ldapmodify -h zanzibar -p 10389 -D "uid=admin,ou=system" -w secret -f authz_sevenSeas.ldif modifying entry o=sevenSeas adding new entry cn=sevenSeasAuthorizationRequirementsACISubentry,o=sevenSeas $

It is also possible to use graphical tools; some of them offer the feature to perform operations given in LDIF.

Verification, that it works

After successfully applying the changes to the sample partition, one may ask how to check whether it works. We therefore perform some operations with the help of command line tools. Some will be permitted, some will not (and cause an appropriate error message). It would also be able to check this with the help of graphical tools (you might like to do this instead). But it is easier to document the parameters used with the help command line arguments.

Performing some search operations in order to read data

Bind as user "William Bush" and search for entries which match "(uid=hhornblo)". Expected behavior: We are able to read the attributes of entry "cn=Horatio Hornblower,ou=people,o=sevenSeas" (the only entry which matches the filter). The password attribute should not be visible. It works as desired:

none $ ldapsearch -h zanzibar -p 10389 -D "cn=William Bush,ou=people,o=sevenSeas" -w pass \\ -b "o=sevenSeas" -s sub "(uid=hhornblo)" version: 1 dn: cn=Horatio Hornblower,ou=people,o=sevenSeas mail: hhornblo@royalnavy.mod.uk objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson objectclass: top cn: Horatio Hornblower uid: hhornblo givenname: Horatio description: Capt. Horatio Hornblower, R.N sn: Hornblower

In the described configuration, the user "Horatio Nelson" acts as a directory manager below "o=sevenSeas". Hence he should basically be allowed to do everything. He should even be able to see other users' userPassword values. In our case, the hash function SHA was applied to them:

none $ ldapsearch -h zanzibar -p 10389 -D "cn=Horatio Nelson,ou=people,o=sevenSeas" -w pass \\ -b "o=sevenSeas" -s sub "(objectclass=person) " uid userPassword version: 1 dn: cn=Horatio Hornblower,ou=people,o=sevenSeas userpassword: {SHA}nU4eI71bcnBGqeO0t9tXvY1u5oQ= uid: hhornblo dn: cn=William Bush,ou=people,o=sevenSeas userpassword: {SHA}nU4eI71bcnBGqeO0t9tXvY1u5oQ= uid: wbush dn: cn=Thomas Quist,ou=people,o=sevenSeas userpassword: {SHA}nU4eI71bcnBGqeO0t9tXvY1u5oQ= uid: tquist ...

But "Horation Nelson" is not able to perform searches in other areas than "o=sevenSeas" to see the entries. Of course our global ApacheDS administrator "uid=admin,ou=system" is still able to see them:

none $ ldapsearch -h zanzibar -p 10389 -D "cn=Horatio Nelson,ou=people,o=sevenSeas" -w pass \\ -b "ou=system" -s sub "(objectclass=person)" $ ldapsearch -h zanzibar -p 10389 -D "uid=admin,ou=system" -w secret \\ -b "ou=system" -s sub "(objectclass=person)" version: 1 dn: uid=admin,ou=system sn: administrator cn: system administrator objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson userpassword: secret uid: admin displayName: Directory Superuser dn: cn=Tori Amos,ou=users,ou=system cn: Tori Amos userpassword: amos objectclass: person objectclass: top sn: Amos ...

Trying to manipulate data

Until now the authorization only hided data (entries, attributes) from users with insufficient access rights. Let's perform some operations which try to manipulate the directory data!

Adding an entry

First we try to add a new user to the "Seven Seas" partition. The data for the entry is inspired by "Peter Pan" and provided by this LDIF file (captain_hook.ldif):

none # File captain_hook.ldif dn: cn=James Hook,ou=people,o=sevenSeas objectclass: inetOrgPerson objectclass: organizationalPerson objectclass: person objectclass: top cn: James Hook description: A pirate captain and Peter Pan's nemesis sn: Hook mail: jhook@neverland userpassword: peterPan

An anonymous user is not allowed to create new entries, as the following error message shows:

none $ ldapmodify -h zanzibar -p 10389 -a -f captain_hook.ldif adding new entry cn=James Hook,ou=people,o=sevenSeas ldap_add: Insufficient access ldap_add: additional info: failed to add entry cn=James Hook,ou=people,o=sevenSeas: null $

The same holds true for all "Seven Seas"-user other than "Horatio Nelson". The latter is permitted to do so:

none $ ldapmodify -h zanzibar -p 10389 -D "cn=William Bush,ou=people,o=sevenSeas" -w pass \\ -a -f captain_hook.ldif adding new entry cn=James Hook,ou=people,o=sevenSeas ldap_add: Insufficient access ldap_add: additional info: failed to add entry cn=James Hook,ou=people,o=sevenSeas: null $ ldapmodify -h zanzibar -p 10389 -D "cn=Horatio Nelson,ou=people,o=sevenSeas" -w pass \\ -a -f captain_hook.ldif adding new entry cn=James Hook,ou=people,o=sevenSeas $

Afterwards a new entry is successfully created within the "Seven Seas" partition by user "Horatio Nelson". The '+' sign in the attributes list of the ldapsearch command causes ApacheDS to return the operational attributes, which demonstrate this.

none $ ldapsearch -h zanzibar -p 10389 -b "o=sevenSeas" -s sub "(cn=James Hook)" + version: 1 dn: cn=James Hook,ou=people,o=sevenSeas accessControlSubentries: cn=sevenSeasAuthorizationRequirementsACISubentry,o=sevenSeas creatorsName: cn=Horatio Nelson,ou=people,o=sevenSeas createTimestamp: 20061203140109Z

Modifying an entry

As a further example which tries to write to the directory, we add a new value to the description attribute of the freshly created entry for Captain Hook. With a change entry in an LDIF file, it looks like this (file captain_hook_modify.ldif):

none # File captain_hook_modify.ldif dn: cn=James Hook,ou=people,o=sevenSeas changetype: modify add: description description: Wears an iron hook in place of his right hand -

Performing the modification with the ldapmodify command line tool again fails for users other than "Horation Nelson" (who is allowed to due to the authorization configuration) and "uid=admin,ou=system".

none $ ldapmodify -h zanzibar -p 10389 -f captain_hook_modify.ldif modifying entry cn=James Hook,ou=people,o=sevenSeas ldap_modify: Insufficient access ldap_modify: additional info: failed to modify entry cn=James Hook,ou=people,o=sevenSeas: null $ ldapmodify -h zanzibar -p 10389 -D "cn=William Bush,ou=people,o=sevenSeas" -w pass \\ -f captain_hook_modify.ldif modifying entry cn=James Hook,ou=people,o=sevenSeas ldap_modify: Insufficient access ldap_modify: additional info: failed to modify entry cn=James Hook,ou=people,o=s evenSeas: null $ ldapmodify -h zanzibar -p 10389 -D "cn=Horatio Nelson,ou=people,o=sevenSeas" -w pass \\ -f captain_hook_modify.ldif modifying entry cn=James Hook,ou=people,o=sevenSeas

Deleting an entry

Now it is finale time. A demonstration on how to delete the villain's entry from the directory. With an LDIF file (captain_hook_delete.ldif) with an appropriate change entry, this can easily be accomplished, if the bind user is allowed to do so.

none # File captain_hook_delete.ldif dn: cn=James Hook,ou=people,o=sevenSeas changetype: delete

Applying this file with the help of ldapmodify results in a behavior comparable to the modification. Anonymous or "normal" users (like "William Bush") are not permitted to delete Captain Hook's entry. The user "Horatio Nelson", our directory manager for "Seven Seas", is:

none $ ldapmodify -h zanzibar -p 10389 -f captain_hook_delete.ldif deleting entry cn=James Hook,ou=people,o=sevenSeas ldap_delete: Insufficient access ldap_delete: additional info: failed to delete entry cn=James Hook,ou=people,o=sevenSeas: null $ ldapmodify -h zanzibar -p 10389 -D "cn=William Bush,ou=people,o=sevenSeas" -w pass \\ -f captain_hook_delete.ldif deleting entry cn=James Hook,ou=people,o=sevenSeas ldap_delete: Insufficient access ldap_delete: additional info: failed to delete entry cn=James Hook,ou=people,o=sevenSeas: null $ ldapmodify -h zanzibar -p 10389 -D "cn=Horatio Nelson,ou=people,o=sevenSeas" -w pass \\ -f captain_hook_delete.ldif deleting entry cn=James Hook,ou=people,o=sevenSeas $

The entry "cn=James Hook,ou=people,o=sevenSeas" has been successfully deleted from the partition. Our little demonstration on how the ACI subsystem with a realistic configuration behaves end here. Learn more about it in the Advanced User's Guide.

Resources

Resources

  • No labels