Virtual Attributes
Virtual attributes augment directory entries with attribute values that the DS server computes or obtains dynamically. Virtual attribute values do not exist in persistent storage. They help to limit the amount of data that needs to be stored. They fit well in some use cases, such as determining the groups a users belongs to, or adding an ETag to an entry.
Note
Do not index virtual attributes.
Virtual attribute values are generated by the server when they are read. They are not designed to be stored in a persistent index. Since you do not index virtual attributes, searching on a virtual attribute can result in an unindexed search. Unindexed searches are resource-intensive for large directories. By default, a directory server lets only the directory superuser perform unindexed searches.
Avoid searches that use a simple filter with a virtual attribute.
If you must use a virtual attribute in a search filter, use it in a complex search filter that first narrows the search by filtering on an indexed attribute. For example, the following filter first narrows the search based on the user's ID before checking group membership. Make sure that the user performing the search has access to read
isMemberOf
in the results:(&(uid=user-id)(isMemberOf=group-dn))
If you must use the entryDN
and isMemberOf
virtual attributes in a filter, use a simple equality filter. The following example shows how to add access to read isMemberOf
, and then run a search that returns the common names for members of a group:
$ldapmodify \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN uid=admin \ --bindPassword password << EOF dn: dc=example,dc=com changetype: modify add: aci aci: (targetattr="isMemberOf")(version 3.0; acl "See isMemberOf"; allow (read,search,compare) groupdn= "ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com";) EOF
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN uid=kvaughan,ou=People,dc=example,dc=com \ --bindPassword bribery \ --baseDN dc=example,dc=com \ "(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)" \ cn
dn: uid=hmiller,ou=People,dc=example,dc=com cn: Harry Miller dn: uid=kvaughan,ou=People,dc=example,dc=com cn: Kirsten Vaughan dn: uid=rdaugherty,ou=People,dc=example,dc=com cn: Robert Daugherty
DS servers define the following virtual attributes by default:
entryDN
The DN of the entry.
entryUUID
String. Provides a universally unique identifier for the entry.
etag
String entity tag. Defined in RFC 2616. Useful when checking whether an entry has changed since it was retrieved.
hasSubordinates
Boolean. Indicates whether the entry has children.
numSubordinates
The number of child entries directly beneath the entry.
isMemberOf
DN. Groups the entry belongs to.
By default, the server generates
isMemberOf
on entries having one of the following object classes:groupOfEntries
groupOfNames
groupOfUniqueNames
person
To generate
isMemberOf
on entries with other object classes, edit the filter property of theisMemberOf
virtual attribute configuration.member
DN. Generated for virtual static groups.
uniqueMember
DN. Generated for virtual static groups.
pwdPolicySubentry
DN of the password policy that applies to the entry.
Default global access control settings prevent normal users from accessing this operational attribute.
subschemaSubentry
DN. References the schema definitions.
collectiveAttributeSubentries
DNs of applicable collective attribute definitions.
governingStructureRule
DN. References the rule specifying the type of subordinates the entry can have.
structuralObjectClass
DN. References the structural object class for the entry.
Virtual attributes are generally operational, and so are returned only when explicitly requested. The searches in these examples are unindexed, and so are performed with directory administrator credentials:
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN uid=admin \ --bindPassword password \ --baseDN dc=example,dc=com \ "(dc=example)"
dn: dc=example,dc=com dc: example objectClass: domain objectClass: top
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --bindDN uid=admin \ --bindPassword password \ --baseDN dc=example,dc=com \ "(dc=example)" \ numSubordinates
dn: dc=example,dc=com numSubordinates: 12
You can use the existing virtual attribute types to create your own virtual attributes. You can also use the user-defined
type to create your own virtual attribute types. The virtual attribute is defined by the server configuration, which is not replicated:
$dsconfig \ create-virtual-attribute \ --hostname localhost \ --port 4444 \ --bindDN uid=admin \ --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 my favorite directory server" \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --no-prompt
$ldapsearch \ --hostname localhost \ --port 1636 \ --useSsl \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --baseDN dc=example,dc=com \ "(uid=wlutz)" \ description
dn: uid=wlutz,ou=People,dc=example,dc=com description: Description on ou=People description: Served by my favorite directory server