How to create custom AD LDS attributes...

The steps that one might use to create custom AD LDS attributes.

Recently, I was working with a client that had has an enterprise application that is outsourced to an Application Service Provider (ASP). Because this application is outsourced and using a completely separate authentication database from their internal Active Directory (AD) forest, they have been experiencing a number of account lockout problems because of password differences between AD and the external application. In addition, the external application also relied on user data that was stored in Active Directory. To replicate the data to the external application there were a number of manual steps that needed to be completed which often resulted in data validity differences between the two systems.

In an effort to solve these issues, the client wanted to have the external application both use AD for authentication and as the direct source for some of the data displayed in the external application. At first, the ASP suggested having the external application talk directly to the clients AD forest. However, there are a number of reasons why allowing an outside entity access to your AD environment isn’t such a great idea. First, because an application would require read access to your directory. This also means that an outside vendor would have access to more enterprise data then their application needed (unless you messed with the default AD permissions structure). Two, such a solution would also require a direct connection between the outside vendor’s systems and your AD domain controllers. This means that you must then trust the external vendor’s systems and their security practices are sound. Naturally, this is not a solution that would fly with most IT security departments.

So, to meet the client’s requirements, a solution was proposed that was based on AD LDS. This solution involved the following items:

  • The userProxyFull object class would be used to represent replicated user objects in AD LDS. The userProxyFull and userProxy object classes are special object classes that allow AD LDS to process bind requests to objects based on these classes and then redirect the authentication requests back to Active Directory.

Note:

Yes, Microsoft complains that people are over using these object classes considering they were originally intended only for legacy applications. But, the only other viable option is then to replicate user password information using some sort of IdM solution. While these are great solutions and I would normally recommend them for most deployments, deploying these solutions would have been overkill in this case. Also, it is important to note that using these object classes also requires that the AD LDS server be a domain member.

  • In addition, to the AD LDS schema being extended using the default MS-User.LDF and MS-UserProxyFull.LDF files. The AD LDS schema would have to be extended to include custom attributes as defined by the client for the userProxyFull object class.
  • Lastly, a replication script would be developed to replicate user objects and data from AD to AD LDS based on a predetermined attribute mapping scheme.

The first item is actually very easy to implement. You just need to install an AD LDS instance on a host that is a domain member. The only catch is that you need to have a Server Authentication certificate in place on the host so that the bind redirection will work. The last item, while it may be most time consuming, is also very easy to implement because the solution is based on your ability to create a directory replication script. The resulting script for this client was a PowerShell script that used a CSV based mappings file to replicate data from AD to AD LDS. If I’m feeling randy, I will post some code samples.

It turned out that the second item was the most difficult item to implement. Not impossible, but rather it took some research into understanding how to extend the AD LDS schema. I make this statement for two reasons. One, I don’t normally do directory schema extensions (as MS tends to provide these). Two, in my opinion, there are no clear cut examples or explanations into how to extend the AD or AD LDS schemas. Maybe this is why so many organizations get into so much trouble when trying to add attributes into AD. There is no document clearly stating why you shouldn’t be doing this (as in my opinion AD LDS should be used instead) or how to extend the schema correctly if you really need to do this.

And so, this brings us to why I’m writing this blog entry in the first place. My whole intent was to share a couple of concepts that may prove useful if you want to write your own ADAM schema extension. First, when adding in a new attribute or object class you need to have a unique attribute ID for the item that is being added. In other words, you need to have an OID. OIDs or object identifiers are basically unique IDs that are used to identify an object. Second, each item that you are adding needs to also have its own unique GUID. Meeting this requirement at first sounds easy as you can use any number of tools to generate GUID (guidgen.com or UUIDGEN.EXE). But, when writing the LDIF file that will be used to extend your schema the GUID must be Base64 encoded. Fun!

Well, that is not entirely true because if you don’t specify the schemaIDGUID parameter in your LDIF file then AD LDS or AD will actually generate a unique GUID for you. But, that isn’t a best practice because if you are trying to programmatically control extend rights for your custom schema extensions then it is recommended that the same GUID be used across directories. In other words, your final LDIF that you use must have a Base64 encoded value for the schemaIDGUID.

There are several ways that you can accomplish this task. You can either write or download an application to encode the GUID (something most IT pros will not do). Or, you can follow these steps:

  1. Create a development instance of ADAM.
  2. Create your LDIF file without the schemaIDGUID defined.
  3. Extend the development instance of AD LDS with the LDF file.
  4. Fire up the ADSchemaAnalyzer and then set your development AD LDS instance as both the target and base schema (seems strange but it works).
  5. Find the attribute that you just created, mark it as included, and then generate an LDIF file.
  6. Last, update your custom LDIF file with the schemaIDGUID from the ADSchemaAnalyzer LDIF file.

Example:

# Attribute: MyCustom-Attribute

dn: cn= MyCustom-Attribute,cn=Schema,cn=Configuration,dc=X

changetype: ntdsschemaadd

objectClass: attributeSchema

#

attributeId: 1.3.6.1.4.1.311.21.8.some_numbers

attributeSyntax: 2.5.5.12

isSingleValued: TRUE

rangeLower: 1

rangeUpper: 1000

adminDisplayName: MyCustom-Attribute

adminDescription: MyCustom-Attribute

# schemaIDGUID: 1234-Look-A-GUID

schemaIDGUID:: xLLovJTaNEyBASE064

oMSyntax: 64

searchFlags: 16

lDAPDisplayName: MyCustomAttribute

systemOnly: FALSE

dn:

changetype: modify

add: schemaUpdateNow

schemaUpdateNow: 1

-

# Now you need to update the userProxyFull object class

# to include your custom attribute.

dn: cn=User-Proxy-Full,cn=Schema,cn=Configuration,dc=X

changetype: ntdsschemamodify

add: mayContain

mayContain: 1.3.6.1.4.1.311.21.8.some_numbers

-

dn:

changetype: modify

add: schemaUpdateNow

schemaUpdateNow: 1

If you like this, check out some other posts from Tyson:

Or if you want, you can also check out some of Tyson's latest publications:

Lastly, visit the Microsoft Subnet for more news, blogs, and opinions from around the Internet. Or, sign up for the bi-weekly Microsoft newsletter. (Click on News/Microsoft News Alert)

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Related:

Copyright © 2010 IDG Communications, Inc.

IT Salary Survey: The results are in