Constructed attributes are your friend

The schema itself has a whole lot of interesting nuances. Within the schema we define multiple different types of attributes. One of the most useful attribute types we have might just be the constructed attribute.

 

Constructed attributes are interesting in that they aren’t a single value in the database which is read and returned. When you read a constructed attribute, rather than retrieving a value from the database, we perform a calculation of some sort and return the result of that calculation. The idea of constructed attributes is to provide the LDAP client reading them with some information that would otherwise be very difficult to obtain. Let’s look at an example.

 

Often times people would like to look at metadata on an object that is used during replication. Perhaps you are writing tools to monitor replication (hey, it could happen J) and see this information as of use to you. For this purpose we created two attributes: msDS-ReplAttributeMetaData and msDS-ReplValueMetaData. First, let’s look at the schema definition for one of these attributes (partial definition):

 

Dn: CN=ms-DS-Repl-Value-Meta-Data,CN=Schema,CN=Configuration,DC=domain,DC=local

            1> attributeID: 1.2.840.113556.1.4.1708;

            1> attributeSyntax: 2.5.5.12;

            1> isSingleValued: FALSE;

            1> oMSyntax: 64;

            1> lDAPDisplayName: msDS-ReplValueMetaData;

            1> systemFlags: 0x14 = ( FLAG_ATTR_IS_CONSTRUCTED | FLAG_SCHEMA_BASE_OBJECT );

 

 

Note the element I placed in red (one of the flags set, LDP parsed this out for me). This flag tells us that the attribute is constructed.

 

If I visit an object in my directory and request this attribute be returned, I get something like:

>> Dn: CN=Builtin,DC=domain,DC=local

            26> msDS-ReplAttributeMetaData: <DS_REPL_ATTR_META_DATA>

            <pszAttributeName>isCriticalSystemObject</pszAttributeName>

            <dwVersion>1</dwVersion>

            <ftimeLastOriginatingChange>2003-01-12T02:13:38Z</ftimeLastOriginatingChange>

            <uuidLastOriginatingDsaInvocationID>8ee69288-cf81-4b36-898c-f4bf3de88cab</uuidLastOriginatingDsaInvocationID>

            <usnOriginatingChange>8201</usnOriginatingChange>

            <usnLocalChange>7160</usnLocalChange>

            <pszLastOriginatingDsaDN></pszLastOriginatingDsaDN>

</DS_REPL_ATTR_META_DATA>

 

(I trimmed this output some for the sake of the length of this post)

Note that this particular attribute is returned in XML format. Some constructed attributes are returned as XML, some in other formats. But all are returned in a way so as to facilitate you parsing them if required, and just read them normally if they are a simple data type of some sort (int, etc.)

Of course, like other attributes in the directory, we define these elements on MSDN: https://msdn.microsoft.com/library/default.asp?url=/library/en-us/adschema/adschema/a_msds_replattributemetadata.asp

 

So with all of that said, what are the caveats? Not many, but there are a few:

  • Constructed attributes are only returned if you request them. If you simply query for all attributes (*) on an object, these attributes will not be returned. One must explicitly request them if they wish to see them.
  • Constructed attributes are only returned when a base search is used against an object. If you perform a subtree search against an entire group of objects and request this attribute, it will not be returned for all objects in the subtree.
  • One can not use a constructed attribute in a search filter. That is to say, if you were to search for all objects that match a filter (msds-replattributemetadata=foo), we would be unable to evaluate that expression properly.