Subentries are used for managing the administration of different aspects of the directory. LDAP has just recently formalized the notion of subentires in RFC 3672 . Subentries have existed within X.500 Directories for years with clear specifications for administering collective attributes, schema, and access controls. With the exception of managing collective attributes LDAP has no equivalent *yet* for administering these aspects. However with RFC 3672, LDAP is on its way towards adopting and adapting these mechanisms from X.500 Directories. It is only a matter of time.
For this reason we intend to remain ahead of the curve by implementing these aspects of administration using Subentries and Administrative Areas similar to X.500 Directories.
To explain this properly we're going to need to discuss a couple other things like administrative areas (AA) and administrative points (AP) within the directory. However for the impatient here's a quick attempt to describe what subentries are:
Subentries are hidden leaf entries (which cannot have children). These entries immediately subordinate to an administrative point (AP) within the directory. They are used to specify administrative information for a part of the Directory Information Tree (DIT). Subentries can contain administrative information for aspects of access control, schema administration, and collective attributes (and others which have not been defined in any specification yet).
First some definitions as provided by X.501:
Usually an entry is selected as the administrative point and marked with an operational attribute. The attributeType of the operational attribute is 'administrativeRole'. This attribute can have the following values:
OID | NAME |
---|---|
2.5.23.1 | autonomousArea |
2.5.23.2 | accessControlSpecificArea |
2.5.23.3 | accessControlInnerArea |
2.5.23.4 | subschemaAdminSpecificArea |
2.5.23.5 | collectiveAttributeSpecificArea |
2.5.23.6 | collectiveAttributeInnerArea |
As you can see, 3 aspects, *schema*, *collective attributes*, and *access control* are considered. An autonomous administrative area can hence be considered with respect to all three specific aspect of administration. If an AP is marked as an autonomousArea it generally means that administration of all aspects are allowed by the authority. If marked with a specific aspect then only that aspect of administration is delegated. The administrativeRole operational attribute is multivalued so the uber admin can delegate any number of specific administration aspects as he likes.
Also notice that two aspects, collective attribute and access controls, allow administrative points to be inner areas. Delegated authorities for these two aspects can create inner administrative areas to further delegate their administrative powers. The schema aspect unlike the others cannot have inner areas because of potential conflicts this may cause which would lead to data integrity issues. For this reason only the authority of an automomous area can manage schema for the entire subtree.
An autonomous administrative area (AAA) includes the AP and spans all descendants below the AP down to the leaf entries of the subtree with one exception. If another AAA, let's call it AAA' (prime) is present and rooted below the first AAA then the first AAA does not include the entries of AAA'. Translation: an AAA spans down until other AAAs or leaf entries are encountered within the subtree. This is due to the fact that AAAs do not overlap as do inner AAs (IAA).
Subentries hold administrative information for an IAA or an AAA. These entries are of the objectClass 'subentry'. The subentry must contain two attributes: a *commonName* and a *subtreeSpecification*. The commonName (or cn) is used as the subentry's rdn attribute. The subtreeSpecification describes the collection of entries within the AA (IAA or AAA) that the administrative instruction applies to.
A subtree specification uses various parameters described below to define the set of entries. Note that entries need not exist for them to be included in the collection on addition.
This is the relative name of the root vertex of the subtree relative to the AP. So if the AP is *'ou=system'* and the base is *'ou=users'*, the subtree begins at *'ou=users,ou=system'*. The base can be any length of name components including 0 where it's the empty name "". In this case, the subtree begins at the AP, *'ou=system'* in the example above.
Chop specification parameters define specific nodes to be excluded from the collection as well as how deep the subtree spans and even where it starts relative to the base.
These parameters are names relative to the root vertex of the subtree, hence they are relative to the base parameter. They specify whether or not an entry and its descendants are to be excluded from the collection.
When *chopBefore* is used, the entry specified is excluded from the collection. When *chopAfter* is used the entry is included however all descendants below the entry are excluded.
The minimum parameter describes the minimum DN length required to include entries within the selection. The maximum parameter describes the maximum DN length allowed before entries are excluded from the collection.
The specification filter is a unique beast. It's a filter like a search filter, however its syntax and expressivity is radically different. Think of a specification filter as a simplified form of search filters where all terms only test the objectClass attribute and only equality checks can be performed. Oh and yes, you do have logical operators like *and*, *or* and *not*.
So with a filter you have the ability to "refine" the subtree already specified with chop, and base parameters. This "refinement" makes it so the collection is not really a contiguous subtree of entries but a possibly disconnected set of selected based on the objectClass characteristics of entries. This feature of a subtreeSpecification is very powerful. For example, I can define a subtree to cover a region of an AA yet include only inetOrgPersons within this region.
Different subentry objectClasses exist for applying different aspects of administration to the entry collection described by their subtreeSpecification attribute. By the way the subtreeSpecification attribute is single valued so there can only be one in a subentry. However you can have several subentries of various kinds under an AP. Furthermore their collections can intersect.
The kinds of subentries allowed though are limited by the administrativeRole of the AP. If the AP is for an access control AA then you can't add a subentry to it for schema administration. The AP must have the role for schema administration as well to allow both types of subentries.
ApacheDS does not manage schema using subentries in the formal X.500 sense right now. There is a single global subentry defined at *'cn=schema'* for the entire DSA. The schema is static and cannot be updated at runtime even by the administrator. Pretty rough for now but it's the only lagging subsystem. We'll of course make sure this subsystem catches up.
ApacheDS does however manage collective attributes using subentries. An AP that takes the administrativeRole for managing collective attributes can have subentries added. These subentries are described in greater detail here: Collective . In short, collective attributes added to subentries show up within entries included by the subtreeSpecification. Adding, removing, and modifying the values of collective attributes within the subentries instantly manifest changes in the entries selected by the subtreeSpecification. Again consult Collective for a hands on explanation of how to use this feature.
ApacheDS performs access control and allows delegation using subentries, AAAs, and IAAs. ApacheDS uses the Basic Access Control Scheme from X.501 to manage access control. By default this subsystem is deactivated because it locks down everything except access by the admin. More information about hands on use is available here: Authorization . However to summarize its association with subentries, access control information (ACI) can be added to subentries under an AP for access control AAs. When one or more ACI are added in this fashion, the access rules of the ACI set apply to all entries selected by the subtreeSpecification. Even with this powerful feature individual entries can have ACI added to them for controlling access to them. Also there are things you can do with ACI added to subentries that cannot be done with entry level ACI. For example you cannot allow entry addition with entry ACI. You must use subtreeSpecifications to define where entries may be added because those entries and their parents may not exist yet.
The best way to demonstrate subtreeSpecification values are through examples. Here's the simplest filter of them all:
{}
This basically selects the entire contiguous subtree below the AP. The base is the empty name and it's rooted at the AP.
Next step let's add a base:
{ base "ou=users" }
If this is the subtreeSpecification under the AP, *'ou=system'*, then it selects every entry under *'ou=users,ou=system'*.
OK that was easy so now let's slice and dice the tree now using the minimum and maximum chop parameters.
{ minimum 3, maximum 5 }
This selects all entries below *'ou=system'* which have a DN size equal to 3 name components, but no more than 5. So for example *'uid=jdoe,ou=users,ou=system'* would be included but *'uid=jack,ou=do,ou=not,ou=select,ou=users,ou=system'* would not be included. Let's continue and combine the base with just a minimum parameter:
{ base "ou=users", minimum 4 }
Here the subtree starts at *'ou=users,ou=system'* if the subentry subordinates to the AP at *'ou=system'*. The user *'uid=jdoe,ou=deepenough,ou=users,ou=system'* is selected by the spec where as *'uid=jbean,ou=users,ou=system'* is not.
It's time to add some chop exclusions:
{ base "ou=users", minimum 4, specificExclusions { chopBefore: "ou=untrusted" } }
Again if placed at the AP *'ou=system'* this subtree would begin at *'ou=users,ou=system'*. It would not include users that subordinate to it though because of the minimum constraint since these users would have 3 components in their DN. The specific exclusions prevent *'ou=untrusted,ou=users,ou=system'* and all its descendants from being included in the collection. However *'uid=jbean,ou=trusted,ou=users,ou=system'* would be included since it meets the minimum requirement, is a descendant of *'ou=users,ou=system'* and is not under the excluded DN, *'ou=untrusted,ou=users,ou=system'*.
Note that you can add as many exclusions as you like by comma delimiting them. For example:
{ base "ou=users", minimum 4, specificExclusions { chopBefore: "ou=untrusted", chopAfter: "ou=ugly", chopBefore: "ou=bad" } }
The final example includes a refinement. Again any combination of chop, filter and base parameters can be used. The following refinement makes sure the users selected are of the objectClass inetOrgPerson and specialUser where the OID for the specialUser class is 32.5.2.1 (fictitious).
{ base "ou=users", minimum 4, specificExclusions { chopBefore: "ou=untrusted", chopAfter: "ou=ugly", chopBefore: "ou=bad" } specificationFilter and:{ item:32.5.2.1, item:inetOrgPerson } }
If you'd like to see the whole specification of the grammar used for the subtreeSpecification take a look at Appendix A in RFC 3672 .
In the immediate future we intend to introduce Triggers , stored procedures and views into ApacheDS. Subentries will play a critical role in the administration and application of these features. For example a Trigger specification need not include information on what entries it applies to since the subtreeSpecification handles this. The question of "on what" a trigger applies to is nicely disassociated from the "which operation" part of the specification. This makes for much better reuse of triggers. It also allows for the pin point application of triggers to entries in the DIT. Likewise a view itself will be defined by a specification. A view for example in a subentry can define a region of the tree that does not exist but is shadowed from another region all together. The possibilities here are limitless.
Of course we will revamp the schema subsystem of ApacheDS to use subentries in AAA to manage the schema in effect within different regions of the DIT. Today most LDAP servers just have a global scheme in effect for the entire DIT served by a DSA. We don't think that is reasonable at all. So expect some serious advances in the design of a new schema subsystem based on subentries.
Replication is yet another excellent candidate for using subentries. Replication of specific collections of entries can be managed for each cluster rather than replicating the entire DIT served by a DSA to replicas. This way we don't only control what is replicated but we can also control how and where it is replicated.
ApacheDS has implemented subentries for the administration of various aspects of the directory and gains several powerful features as a result: namely precision application of control to entry collections and the ability to delegate administrative authority. For details on the administration of each aspect using subentries ( Collective and Authorization ) please see the respective documentation.
As ApacheDS progresses it will gain an immense advantage from subentries. Both for existing LDAP features like scheme and for new experimental features like triggers, and replication.