Working With Virtual and Collective AttributesOpenDJ supports virtual attributes with dynamically generated values.
Virtual attributes are used by the server. You can also define your own.
OpenDJ also supports standard collective attributes as described in
RFC 3671,
allowing entries to share common, read-only attribute values.This chapter demonstrates how to define virtual and collective
attributes, showing common solutions as examples of their use.Virtual AttributesVirtual attributesOpenDJ defines a number of virtual attributes by default.entryDNThe value is the DN of the entry.entryUUIDProvides a universally unique identifier for the
entry.etagEntity tag as defined in RFC 2616, useful for checking whether an entry has changed since
you last read it from the directory.hasSubordinatesBoolean. Whether the entry has children.numSubordinatesProvides the number of direct child entries.isMemberOfIdentifies groups the entry belongs to.By default OpenDJ generates isMemberOf on user
entries (entries that have the object class person), and
on group entries (entries that have the object class
groupOfNames, groupOfUniqueNames, or
groupOfEntries). You can change this by editing
the filter property of the isMemberOf virtual
attribute configuration.memberGenerated for virtual static groups.uniqueMemberGenerated for virtual static groups.pwdPolicySubentryIdentifies the password policy that applies to the
entry.By default OpenDJ assigns root DN users
the password policy with DN cn=Root Password Policy,cn=Password
Policies,cn=config and regular users the password policy with DN
cn=Default Password Policy,cn=Password
Policies,cn=config. See Configuring
Password Policy for information on configuring and
assigning password policies.subschemaSubentryReferences the schema definitions.collectiveAttributeSubentriesReferences applicable collective attribute
definitions.governingStructureRuleReferences the rule on what type of subordinates the entry
can have.structuralObjectClassReferences the structural object class for the
entry.These virtual attributes are typically operational, so you get them
back from a search only when you request them.$ ldapsearch --port 1389 --baseDN dc=example,dc=com dc=example
dn: dc=example,dc=com
dc: example
objectClass: domain
objectClass: top
$ ldapsearch --port 1389 --baseDN dc=example,dc=com dc=example numSubordinates
dn: dc=example,dc=com
numSubordinates: 4
ReplicationNot for virtual attributesYou can use the existing virtual attribute types to create your
own virtual attributes, and you can also use the
user-defined type to create your own. The virtual
attribute is defined by the server configuration, which is not
replicated.$ dsconfig
create-virtual-attribute
--hostname opendj.example.com
--port 4444
--bindDN "cn=Directory Manager"
--bindPassword password
--name "Served By Description"
--type user-defined
--set enabled:true
--set attribute-type:description
--set base-dn:dc=example,dc=com
--set value:"Served by OpenDJ.Example.com"
--trustAll
--no-prompt
$ ldapsearch --port 1389 --baseDN dc=example,dc=com uid=bjensen description
dn: uid=bjensen,ou=People,dc=example,dc=com
description: Served by OpenDJ.Example.com
Collective attributes cover many use cases better than virtual
attributes.Collective AttributesCollective attributesCollective 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.For example, you can define administrative privileges that
apply to all users who belong to an administrators group. Alternatively
you can define attributes that specify services available for a user
depending on that user's service level.The following example depends on the cos object
class, and the classOfService attribute type defined but
commented out in the Example.ldif file imported as sample data. To try this example
for yourself, add the attribute type and object class definitions
in comments near the top of the file, and then uncomment the
objectClass: cos and classOfService
attribute lines in Example.ldif before importing
the data into OpenDJ.This example positions collective attributes that depend on the
classOfService attribute values.For entries with classOfService: bronze,
mailQuota is set to 1 GB, and
diskQuota is set to 10 GB.For entries with classOfService: silver,
mailQuota is set to 5 GB, and
diskQuota is set to 50 GB.For entries with classOfService: gold,
mailQuota is set to 10 GB, and
diskQuota is 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-disk-quota NAME 'diskQuota
' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR case
IgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-
VALUE USAGE userApplications 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 SINGLE-
VALUE USAGE userApplications X-ORIGIN 'OpenDJ Documentation Examples' )
-
delete: objectClasses
objectClasses: ( example-class-of-service-object-class NAME 'cos' SUP top AUX
ILIARY MAY classOfService X-ORIGIN 'OpenDJ Doc
umentation 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=schemaUse 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=comWith 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