Archive for January 4th, 2014

January 4, 2014

Adding and Updating AD/LDS schema with PowerShell

Recently I had the need to migrate AD LDS schema values between Development, QA, UAT, and Production environments. The process to add schema through the AD schema management MMC is not so bad but adding schema by hand is error prone and ends up being inconsistent.  This inconsistency can, and has, led to errors in applications and processes.

After a bit of trial and error I was able to track down two New-ADObject commands, using the AD PowerShell module, that will add 1) attribute and 2) class schema to LDS. These are the two main object types that dictate AD schema. The commands are very similar but each one has different required optional properties. First, the attribute command:

New-ADObject {Name/CN of the attribute} -server {address/name of the LDS server or domain controller} -Path {This is the path to the schema container in AD or LDS. See below for a nice hint on this one} -Type attributeSchema -Description {optional:The adminDescripion of the attribute}
-DisplayName {optional: the AdminDisplayName of the attribute} -OtherAttributes {Key/Value pairs of other properties of the attribute}

As you may have already guessed the magic sauce to adding the schema is in the “OtherAttributes”. To add attribute schema the following properties must be supplied during the add process:

adminDescription,adminDisplayName,attributeID,oMSyntax

There are other properties that, while they are not required in order to create the object, to set them at all they have to be supplied at object creation time.  This is because, once created, they become owned by the directory service. The following properties are in that list:

OtherAttributes,isSingleValued,attributeSyntax

It is possible that there are more properties that should be in the “optional base” properties list. I am sure I have not tried every permutation…rather only those that get me to my specific solution of migrating my schema.  All other properties can be set later using the Set-ADObject command (see below)

These same principals hold true for class schema as well but are even more stringent due to class schema being more complex than attributes. Here is the class schema command:

New-ADObject {Name/CN of the attribute} -server {address/name of the LDS server or domain controller} -Path {This is the path to the schema container in AD or LDS. See below for a nice hint on this one} -Type classSchema -Description {optional:The adminDescripion of the attribute}
-DisplayName {optional: the AdminDisplayName of the attribute} -OtherAttributes {Key/Value pairs of other properties of the attribute}

As you can see all I have done is change the “Type” from attributeSchema to classSchema in the command.  Once again the magic is in the “base” and “optional base” properties. The required base properties for classSchema are:

adminDisplayName,governsID,Name,subClassOf,objectClassCategory

The optional base properties are…

mustContain

Note: I am assuming that these commands are being run by an account that has rights to make schema changes. If run from remote or from a non-elevated PowerShell you will need to pass credentials with the command.

If this is AD LDS the Set-ADObject command can be used to change or update properties of the attribute after it has been created. (BTW, I’m using the term “property” instead of “attribute” for the attribute object to avoid confusion)(..not sure it’s helping 😉 ).  Any attribute that is not in the “base” attributes list(s) can be updated after the fact using the Set-ADObject command. That process works by setting the object into a PowerShell object using Get-ADObject and then use Set-ADObject to update it.  That looks like this…

$CurObject = Get-ADObject -Filter {cn -eq {Name of the attribute} -server {same as above}  -searchbase {same as the path specified in the creation command}

$CurObject | Set-ADObject -Replace @{{property name}={property value},{next property name}={next property value}}

Please forgive the use of the {} brackets for two different things. The “property name” and “property value” must not have the brackets around them in the real command but the “@{}” after “-Replace” must be there.

Most of this work has been with AD LDS.  Set-ADObject may or may not work with ADDS since it is more picky about removing or changing schema than AD LDS. I have not tested this extensively so your mileage may vary.

2nd Note: I am not trying to detail all of the capabilities of Add-ADObject (et al) because there are too many. That is way too big of a subject. Check http://technet.microsoft.com/en-us/library/ee617260.aspx for a reference on that. My goal is to provide the minimum requirements to get schema put in place in AD.

3rd Note: For any property that is Boolean you will need to pass the value in the command as $True or $False. The commands fail with just strings of True of False.

BTW, here’s slick little way to grab the schema context to pass into your commands:

$TargetLDSServerPath = “localhost:389”
$TargetLDSSchemaObject = Get-ADRootDSE -server $TargetLDSServerPath |select-object schemaNamingContext
$TargetLDSSchemaPath = $TargetLDSSchemaObject.schemaNamingContext

Once you have these set you can standardize your commands to: New-ADObject {Name} -server $TargetLDSServerPath -Path $TargetLDSSchemaPath etc…

UPDATE: FYI: I have found that the system manages the ldapDisplayName (which is the attribute that is listed in the mayContain and mustContain fields if you export the schema to XML). Active Directory automatically sets these attributes to “camelback” even though you pass them with different case.

Tags: , ,