Working With Virtual and Collective Attributes OpenDJ 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 Attributes Virtual attributes OpenDJ defines a number of virtual attributes by default. entryDN The value is the DN of the entry. entryUUID Provides a universally unique identifier for the entry. etag Entity tag as defined in RFC 2616, useful for checking whether an entry has changed since you last read it from the directory. hasSubordinates Boolean. Whether the entry has children. numSubordinates Provides the number of direct child entries. isMemberOf Identifies 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. member Generated for virtual static groups. uniqueMember Generated for virtual static groups. pwdPolicySubentry Identifies 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. subschemaSubentry References the schema definitions. collectiveAttributeSubentries References applicable collective attribute definitions. governingStructureRule References the rule on what type of subordinates the entry can have. structuralObjectClass References 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 Replication Not for virtual attributes You 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 Attributes Collective attributes 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. 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=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