Collective attributes provide a standard mechanism for defining
attributes that appear on all the entries in a subtree potentially filtered
by object class. Standard collective attribute type names have the prefix
c-.
OpenDJ extends collective attributes to make them easier to use.
You can define any OpenDJ attribute as collective using the
;collective attribute option. You can use LDAP filters
in your subtree specification for fine-grained control over which entries
have the collective attributes.
You can have entries inherit attributes from other entries using collective attributes. You establish the relationship between entries either by specifying another attribute of the entry that specifies the DN of the entry from which to inherit the attributes, or by specifying how to construct the RDN of the entry from which to inherit the attributes.
To Add Privileges For a Group of Administrators demonstrates setting administrative privileges in OpenDJ using collective attributes. The following examples demonstrate additional ways to use collective attributes in OpenDJ.
Example 18.1. Class of Service With Collective Attributes
This example defines attributes that specify services available to a user depending on that user's service level.
![]() |
Note |
|---|---|
|
The following example depends on the |
This example positions collective attributes that depend on the
classOfService attribute values.
-
For entries with
classOfService: bronze,mailQuotais set to 1 GB, anddiskQuotais set to 10 GB. -
For entries with
classOfService: silver,mailQuotais set to 5 GB, anddiskQuotais set to 50 GB. -
For entries with
classOfService: gold,mailQuotais set to 10 GB, anddiskQuotais set to 100 GB.
You define collective attributes in the user data using a subentry.
In other words, collective attributes can be replicated. Collective
attributes use attributes defined in the directory schema. First, add the
mailQuote and diskQuota attributes,
and adjust the definition of the cos object class to
allow the two quota attributes.
$ cat quotas.ldif dn: cn=schema changetype: modify add: attributeTypes attributeTypes: ( example-class-of-service-attribute-type NAME 'classOfService ' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnore SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE USAGE user Applications X-ORIGIN 'OpenDJ Documentation Examples' ) - add: attributeTypes attributeTypes: ( example-class-of-service-disk-quota NAME 'diskQuota ' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR case IgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE user Applications X-ORIGIN 'OpenDJ Documentation Examples' ) - add: attributeTypes attributeTypes: ( example-class-of-service-mail-quota NAME 'mailQuota ' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR case IgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE user Applications X-ORIGIN 'OpenDJ Documentation Examples' ) - add: objectClasses objectClasses: ( example-class-of-service-object-class NAME 'cos' SUP top AUX ILIARY MAY ( classOfService $ diskQuota $ mailQuota ) X-ORIGIN 'OpenDJ Doc umentation Examples' ) $ ldapmodify --port 1389 --bindDN "cn=Directory Manager" --bindPassword password --filename quotas.ldif Processing MODIFY request for cn=schema MODIFY operation successful for DN cn=schema
Use the following collective attribute definitions to set the quotas depending on class of service.
# cos.ldif: quotas by class of service
dn: cn=Bronze Class of Service,dc=example,dc=com
objectClass: collectiveAttributeSubentry
objectClass: extensibleObject
objectClass: subentry
objectClass: top
cn: Bronze Class of Service
diskQuota;collective: 10 GB
mailQuota;collective: 1 GB
subtreeSpecification: { base "ou=People", specificationFilter "(classOfService=
bronze)" }
dn: cn=Silver Class of Service,dc=example,dc=com
objectClass: collectiveAttributeSubentry
objectClass: extensibleObject
objectClass: subentry
objectClass: top
cn: Silver Class of Service
diskQuota;collective: 50 GB
mailQuota;collective: 5 GB
subtreeSpecification: { base "ou=People", specificationFilter "(classOfService=
silver)" }
dn: cn=Gold Class of Service,dc=example,dc=com
objectClass: collectiveAttributeSubentry
objectClass: extensibleObject
objectClass: subentry
objectClass: top
cn: Gold Class of Service
diskQuota;collective: 100 GB
mailQuota;collective: 10 GB
subtreeSpecification: { base "ou=People", specificationFilter "(classOfService=
gold)" }
You can add the collective attribute subentries by using the ldapmodify command.
$ ldapmodify --port 1389 --bindDN "cn=Directory Manager" --bindPassword password --defaultAdd --filename cos.ldif Processing ADD request for cn=Bronze Class of Service,dc=example,dc=com ADD operation successful for DN cn=Bronze Class of Service,dc=example,dc=com Processing ADD request for cn=Silver Class of Service,dc=example,dc=com ADD operation successful for DN cn=Silver Class of Service,dc=example,dc=com Processing ADD request for cn=Gold Class of Service,dc=example,dc=com ADD operation successful for DN cn=Gold Class of Service,dc=example,dc=com
With the collective attributes defined, you can see the results on user entries.
$ ldapsearch --port 1389 --baseDN dc=example,dc=com uid=bjensen classOfService mailQuota diskQuota dn: uid=bjensen,ou=People,dc=example,dc=com mailQuota: 1 GB classOfService: bronze diskQuota: 10 GB $ ldapsearch --port 1389 --baseDN dc=example,dc=com uid=kvaughan classOfService mailQuota diskQuota dn: uid=kvaughan,ou=People,dc=example,dc=com mailQuota: 5 GB classOfService: silver diskQuota: 50 GB $ ldapsearch --port 1389 --baseDN dc=example,dc=com uid=scarter classOfService mailQuota diskQuota dn: uid=scarter,ou=People,dc=example,dc=com mailQuota: 10 GB classOfService: gold diskQuota: 100 GB
Example 18.2. Inheriting an Attribute From the Manager's Entry
This example demonstrates how to have OpenDJ set an employee's
department number using the manager's department number. To try the example,
first import Example.ldif into OpenDJ in
order to load the appropriate sample data.
For this example the relationship between employee entries and manager
entries is based on the manager attributes on employee entries. Each
manager attribute on an employee's entry specifies the
DN of the manager's entry. OpenDJ retrieves the department number from the
manager's entry to populate the attribute on the employee's entry.
The collective attribute subentry that specifies the relationship looks like this:
dn: cn=Inherit Department Number From Manager,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: inheritedCollectiveAttributeSubentry
objectClass: inheritedFromDNCollectiveAttributeSubentry
cn: Inherit Department Number From Manager
subtreeSpecification: { base "ou=People" }
inheritFromDNAttribute: manager
inheritAttribute: departmentNumber
This entry specifies that users inherit department number from their manager.
As seen in Example.ldif, Babs Jensen's manager
is Torrey Rigden.
dn: uid=bjensen,ou=People,dc=example,dc=com manager: uid=trigden, ou=People, dc=example,dc=com
Torrey's department number is 3001.
dn: uid=trigden,ou=People,dc=example,dc=com departmentNumber: 3001
Babs inherits her department number from Torrey.
$ ldapsearch --port 1389 --baseDN dc=example,dc=com uid=bjensen departmentNumber dn: uid=bjensen,ou=People,dc=example,dc=com departmentNumber: 3001
Example 18.3. Inheriting Attributes From the Locality
This example demonstrates how to have OpenDJ set a user's language
preferences and street address based on locality. To try the example, first
import Example.ldif into OpenDJ in
order to load the appropriate sample data.
For this example the relationship between entries is based on locality. The collective attribute subentry specifies how to construct the RDN of the object holding the attribute values to inherit.
dn: cn=Inherit From Locality,dc=example,dc=com
objectClass: top
objectClass: subentry
objectClass: inheritedCollectiveAttributeSubentry
objectClass: inheritedFromRDNCollectiveAttributeSubentry
cn: Inherit From Locality
subtreeSpecification: { base "ou=People" }
inheritFromBaseRDN: ou=Locations
inheritFromRDNAttribute: l
inheritFromRDNType: l
inheritAttribute: preferredLanguage
inheritAttribute: street
collectiveConflictBehavior: real-overrides-virtual
This specifies that the RDN of the entry from which to inherit
attributes is like l=, where localityName,ou=LocationslocalityName is the value of the l
(localityName) attribute on the user's entry.
In other words, if the user's entry has l: Bristol,
then the RDN of the entry from which to inherit attributes starts with
l=Bristol,ou=Locations. The actual entry looks like
this:
dn: l=Bristol,ou=Locations,dc=example,dc=com objectClass: top objectClass: locality objectClass: extensibleObject l: Bristol street: 60 Queen Square preferredLanguage: en-gb
The subentry also specifies two attributes to inherit for preferred language and street address.
The object class extensibleObject is added to allow
the entry to take a preferred language.[9]
Notice the last line of the collective attribute subentry:
collectiveConflictBehavior: real-overrides-virtual
This line says that if a collective attribute clashes with a real
attribute, the real value takes precedence over the virtual, collective
value. You can also set collectiveConflictBehavior to
virtual-overrides-real for the opposite precedence, or to
merge-real-and-virtual to keep both sets of values.
Here, users can set their own language preferences. When users set language preferences manually, the collective attribute subentry is configured to give the user's settings precedence over the locality-based setting, which is only a default guess.
Sam Carter is located in Bristol. Sam has specified no preferred languages.
dn: uid=scarter,ou=People,dc=example,dc=com l: Bristol
Sam inherits both the street address and also preferred language from the Bristol locality.
$ ldapsearch --port 1389 --baseDN dc=example,dc=com uid=scarter preferredLanguage street dn: uid=scarter,ou=People,dc=example,dc=com preferredLanguage: en-gb street: 60 Queen Square
Babs's locality is San Francisco. Babs prefers English, but also knows Korean.
dn: uid=bjensen,ou=People,dc=example,dc=com preferredLanguage: en, ko;q=0.8 l: San Francisco
Babs inherits the street address from the San Francisco locality, but keeps her language preferences.
$ ldapsearch --port 1389 --baseDN dc=example,dc=com uid=bjensen preferredLanguage street dn: uid=bjensen,ou=People,dc=example,dc=com preferredLanguage: en, ko;q=0.8 street: 500 3rd Street
[9] The object class
extensibleObject means, "Let me add whatever attributes
I want." It is usually better practice to add your own auxiliary object class
if you need to decorate an entry with more attributes. The shortcut is taken
here as the focus of this example is not schema extension, but instead how
to use collective attributes.

![[Note]](common/images/admon/note.png)
