In part one of this series I walked through some of the configuration, Packages, and GCVs used in the Office 365 IDM driver.
In part two of this series I walked through more of the GCVs and looked at some possible values for the License entitlements.
In this article I would like to look at the Filter and Schema Map. But first, one last point on the entitlements and GCVs. The other entitlement I was not certain of possible values was the Role entitlement. (User and Group were pretty standard. License is a bit confusing but hopefully the previous article at least gets an idea of what it should be)
I think I found a good explanation of the possible Roles in Office 365. It turns out in BPOS the Exchange 2007 based previous version (Office 365 is based on Exchange 2010 services) that there was no real delegation of administrative roles allowed. However now there are, and they are called Roles. The current roles supported are:
I found a good definition of the roles at this site: http://mycentraladmin.wordpress.com/2012/04/17/account-roles-in-office-365/
The question becomes what specific value are expected in the parameter of an Entitlement grant to assign such a Role. We can look back at the entitlementsConfiguration object from the previous article for hints. In the <parameter> node for the Role entitlement we see:
<parameter mandatory="true" name="ID" source="read-attr" source-name="Name"/>
That suggests that the Name is sufficient, which leads me to think that the names listed above are literal values that should work.
With that we can move on to the filter and schema map policy. The filter allows User and Groups with common attributes that make a lot of sense. In this case, one interesting twist is that DirXML-Associations is set to Subscriber notify which is different than most drivers. This is to allow using the association to a listed Active Directory driver elsewhere to be a gatekeeper for this driver. Passwords, using the Universal Password (and thus the nspmDistributionPassword) is set to Subscriber notify as expected. Otherwise this is pretty much the usual suspects, naming info, demographic stuff (Telephone, mobile, Postal address and code).
Groups get Member, CN, Description, and Owner synced which all make sense.
The schema map tells us that the two classes mapped to users and groups are MSolUser and MSolGroup. What is a little odd is that on the Group object, the Owner attribute is mapped to ManagedBy, but there is a policy in the Output transform that strips ManagedBy. Seems like it would be more appropriate to just remove Owner from the filter.
On the user, a very interesting mapping is that of CN to UserPrincipalName. There are policies to append the @domain.com (from the GCV drv.domain.name). Possibly uniqueID would be a better choice as CN can be multivalued (so can uniqueID but CN is often multivalued, whereas uniqueID is often not). I found it interesting that DirXML-ADAliasName was not used, since that is what the AD drivers use to store the User Principal Name values.
I see a couple of things you will probably want to add some policy to handle, like the mapping of Facsimile Telephone Number to Fax, and Postal Address to Street Address since they use structured syntaxes to hold their data and I do not see any transforms in the policy to 'flatten' them out. For the Fax number, this amounts to always having an extra 0 on the end of the number sent over. This is because the Fax syntax has three components, which I always forget the details, but basically one holds the number, one is always blank, and one defaults to 0, and is the final component. So when you cast this structured attribute to a string the three values (null, fax number, 0) get concatenated together, no spaces, so your fax number gets one digit longer and is always a 0, which is really hard to notice in testing, but breaks the usefulness of the value. Postal Address syntax has six components, all named 'string' (which is really annoying as in XPATH you have to address them using position() shorthand) and they too do not have a processing rule, so they will get all six lines of data concatenated together with no spaces, which is highly unlikely to be what you want. The policies to handle these are pretty trivial, but currently missing. Lets see how hard an example would be to construct.
As I think about it, it becomes clear that Reformat Operation Attribute is the perfect tool for this issue. A simple approach, for use in the Output Transform policy might be this:
For Facsimile Telephone Number: (Note this is after the Schema Map, so using Fax which is the application name)
<do-reformat-op-attr name="Fax"> <arg-value type="string"> <token-xpath expression="$current-value/component[@name='faxNumber']"/> </arg-value> </do-reformat-op-attr>
For Postal Address, you could try something like this. Again, using the application name space, so StreetAddress.
<do-reformat-op-attr name="StreetAddress"> <arg-value type="string"> <token-xpath expression="$current-value/component"/> <token-text xml:space="preserve"> </token-text> <token-xpath expression="$current-value/component"/> <token-text xml:space="preserve"> </token-text> <token-xpath expression="$current-value/component"/> <token-text xml:space="preserve"> </token-text> <token-xpath expression="$current-value/component"/> <token-text xml:space="preserve"> </token-text> <token-xpath expression="$current-value/component"/> <token-text xml:space="preserve"> </token-text> <token-xpath expression="$current-value/component"/> </arg-value> </do-reformat-op-attr>
In these cases I just use XPATH on the magical current-value variable, looking for the components that I want.
For Fax it is where the XML attribute name, has a value of faxNumber, and for the Postal Address I just use the 6 values in order, with a space in between. The current-value variable works like it is magical, and it only can be used inside the Reformat Operation Attribute token, (just as current-node only works in the For Each token, although current-op is always available), and it is an implicit loop. You can see it in trace that it performs whatever action you define, over each value in the event document, then loops over the next one (if there is another value). If you treat current-value as a string, you get a string (which for a node-set would be concatenated values as it is cast to a string) and if you treat it as a node-set, you get a node-set. So you can do XPATH tricks like above. Where an XPATH of $current-value/component[@name='faxNumber'] will look at each <value> node, and then look for a <component> child node, whose XML attribute name, is faxNumber. You do not need a trailing /value in the XPATH since you are already inside a <value> node. You could have a trailing /text() though if you wanted. But it will be cast as a string without the text() function.
For the Postal Address case, I just used the shorthand for position()=1 in the predicate, which is just  and much quicker to type. I just recently realized why when I tried a variable in a predicate like to provide the position information that $current-value/component[$COUNTER] does not work, but $current-value/component[position()=$COUNTER] is because $COUNTER is probably being seen as a string not an integer, and thus one more alternate way to get it to work would be $current-value/component[number($COUNTER)] which made me feel better once I figured out why that was not working. XPATH is interesting and somewhat confusing in the IDM context. I have tried to offer examples and explanations on the topic and you can read more about them here:
Another odd schema mapping is eDirectory's workforceId to Office 365's Office attribute. That seems like an odd default choice. I am trying to find a list of the Office 365 schema, but no luck yet. I asked some NetIQ contacts if the driver supports getSchema() and if so, to get me the DirXML-ApplicationSchema attribute from the driver. If your driver supports getSchema() then on the first driver start, and anytime you Refresh Application Schema in iManager, the driver calls the getSchema() function, which is supposed to return the entire application schema and store it on the driver object as DirXML-ApplicationSchema. Not all drivers support it (often the application may not provide it, in which case, the basic driver configuration could pre-populate the attribute, or just ignore it altogether). What this does is to show you the schema attributes, and if they are multivalued. You can see a really clever way to use this, in the context of the Active Directory driver, in this article: Generic Single-valued Schema Enforcement
I have not been able to find documentation from Microsoft yet on the schema used so it is hard to tell if there is a better choice than Office.
The last interesting schema map item I want to talk about is how Internet EMail Address is mapped to AlternateAddresses. In Office 365 it would seem that your User Principal Name is the key, and the main email address. But if you have a different email address in eDirectory that gets sent to the AlternateAddresses attribute.
That about covers the GCVs, schema map and filter settings but I forgot about configuration settings. Before I move on to the fun stuff, the policies I will cover the configuration settings.