GALSync: How to Extend GALSync to Provision Target Objects in Sub OUs Using a Configuration File
Introduction
The GALSync setup is fully documented in the MIIS 2003 Walkthrough Scenarios.
The walkthrough contains documents on GALSync:
- MIIS 2003: Global Address List (GAL) Synchronization (MIIS_2003_GAL_Synchronization.doc)
- MIIS 2003 Walkthrough: Global Address List Synchronization (MIIS_2003_GAL_synchronization_Step_by_step.doc)
Both are used as base to implement the GAL Sync.
Default Configuration
For this Wiki document, the MIIS agent configuration is kept as default as possible.
Full detail on default configuration can be found in MIIS_2003_GAL_Synchronization.doc.
Only the differences (changes made to the default setup) will be recorded in the procedure below.
The default GALSync configuration allows to provision target objects into one single container/OU.
Hub-and-spoke
In lots of cases customers wish to synchronize the existing address books within the different domains, targeting one central "Global Address Book", presenting the different domains as subdivisions.
Customers want to have an overview via Outlook of all existing mail addresses, grouped by domain or entity.
And frequently they need to use a structured target container, provisioning target objects in sub OUs of the main target container.
The functionality to use sub OU's in the target container must be added as customization into the IIFP/ILM server configuration.
Sample domain and OU structure
domain1.local (DOMAIN1)
├ ...
├┬ GAL Contacts (OU)
│├ Domain2 (OU)
│└ Domain3 (OU)
├ ...
domain2.local (DOMAIN2)
├ ...
├┬ GAL Contacts (OU)
│├ Domain1 (OU)
│└ Domain3 (OU)
├ ...
domain3.local (DOMAIN3)
├ ...
├┬ GAL Contacts (OU)
│├ Domain1 (OU)
│└ Domain2 (OU)
├ ...
GALSync Attributes
In the first stage of setup, the list of attributes that are configured by default (by default GALSync setup/wizard), will be maintained.
This will allow for a better review of the initial setup.
It's much easier to remove the unwanted data flow configuration instead of rebuilding (default) data flows from scratch.
Security
Reference: MIIS/ILM Management Agent Communication Ports, Rights, and Permissions
Keep in mind you need a management agent connection account with the proper rights and permissions to read and write data in the targets.
(import, update, provisioning, ...)
To allow the AD MA connection account to create, delete and update objects in the GAL contacts OU, the necessary permissions must be added to the GAL Contacts OU and its subfolders (using heritance).
By preference the administrator must create the container structure before you start provisioning.
You could allow MIIS/ILM/FIMSync to create the subOUs during provisioning, but that is not part of the scope of this document.
Attribute flows
To detect the source of an object (linked to the target subcontainer) an attribute is added to the MV object definition (all objects): targetSubOU.
Details will be documented further in this document.
Metaverse configuration
Automated object creation by GALSync
When using the GALSync MA's, MIIS automatically adds the necessary attribute flows to the new and to the existing management agents.
Also the MV is extended with new object types (like contact_XXX, where XXX is the name of the management agent, spaces replaces by underscore).
Add the targetSubOU attribute to the MV Objects
If you add another GALSync MA, you need to check that all active objects in the MV (MV objects in use by the GALSync) have the targetSubOU string attribute added.
This attribute is used to define the original source of an object, which also defines in which OU the related contact object must be created.
Check these MV object definitions:
- person
- group
- contact_gal_*
- contact_gal_domain
- contact_gal_domain2
- contact_gal_domain3
- .
Attribute flow precedence
Attribute flow precedence is handled automatically by the MIIS configuration wizard.
Management Agent Configuration
Auto generation of attribute flows
When using the GALSync MA's, MIIS automatically adds the necessary attribute flows to the new and to the existing management agents.
Also the MV is extended with new object types (like contact_XXX, where XXX is the name of the management agent, spaces replaces by underscore).
Add the targetSubOU attribute to the new GAL object
When you add a new management agent, the wizard automatically creates a new object type in the MV.
This object must include the new targetSubOU attribute. This attribute already exists in the attribute list but the attribute must be linked to the freshly created object.
Add targetSubOU attribute in attribute IMPORT flows
When implementing GAL Sync, the MA wizard automatically creates the needed attribute flows for the objects in the GAL Sync solution.
To determine the target in which a contact must be created, you need to add an additional attribute flow in the GAL Sync MA configuration.
Only for the (auto-created) attribute flows that mainly exist of import flows, you must add the "targetSubOU".
The attribute flows that exist of export attribute flows must not contain the targetSubOU attribute.
Attribute flows that mainly exist of export attribute flows must not have this import flow added.
Below you'll find some examples of flows that must be added:
Data Source Attribute | Metaverse Attribute | Type | Flow Nulls | |
Object Type: Contact | Object Type:contact_gal_<own MA>* | |||
<dn> | -> | targetSubOU | Rules Extension - targetSubOU | |
Object Type: user | Object Type:person | |||
<dn> | -> | targetSubOU | Rules Extension - targetSubOU | |
Object Type: group | Object Type:group | |||
<dn> | -> | targetSubOU | Rules Extension - targetSubOU |
Add EXPORT attribute flow to adres list filter attribute
To allow Exchange admins creating an address list in AD, a certain attribute must be filled with the msExchOriginatingForest attribute.
In this procedure I chose "extensionAttribute15" for ease of use.
Export Attribute Flow | |||||
Data Source Attribute | To | Metaverse Attribute | Mapping Type | Allow Nulls | |
contact | - | contact_gal_domain1 | - | - | |
extensionAttribute15 | <-- | msExchOriginatingForest | Direct | Allow | |
contact | - | person | - | - | |
extensionAttribute15 | <-- | msExchOriginatingForest | Direct | Allow | |
contact | - | group | - | - | |
extensionAttribute15 | <-- | msExchOriginatingForest | Direct | Allow |
targetSubOU attribute flow definition
GALMA.vb must be extended with an additional flowrule in MapAttributesForImport.
Source code - enable provisioning in sub containers
As mentioned before ((Ref. MIIS_2003_GAL_Synchronization.doc)
"When synchronizing with a connected data source that uses a hierarchical structure such as Active Directory, Microsoft Identity Integration Server 2003 does not export container operations. That is, when provisioning a child object, Microsoft Identity Integration Server 2003 does not create the parent automatically. The management of containers with hierarchies must be done completely in the connected data source."
The functionality to use sub OU's in the target container will be added as customization into the MIIS server configuration.
The GALSync code extensions are gathered into 1 project solution.The source code of the GALSync setup is installed by default in the MIIS program files directory (%program files%\Microsoft Identity Integration Server\SourceCode\GalSync).
The solution exists of 3 base code files:
- GALMA.vb : the GAL management agent extensions
- GALMV.vb : the GAL metaverse extensions
- GALUtil.vb: code library for functions used in GALMA.vb and GALMV.vb
In addition, the solution uses a XML file (GALSync.XML) to read MA l configuration options.
Galsync.xml
IMPORTANT:
The galsync.xml file in the Extensions folder is automatically updated/managed by the system, when the MA's in MIIS are added, updated or changed.
GALSync.xml is very volatile. It's not really suitable for containing custom information (like the sub OU configuration.)
For that reason, another similar xml file is created to contain custom information: GALSync_subOUs.xml.
GALSync_subOUs.xml
For each management agent, a section (<target-subou>) has to be added to the MA configuration, to support the provisioning in subcontainers.
This information is quite stable and is administrator-managed.
At the moment of configuration this information must be updated to the real life configuration data (AD Container info).
<rules-extension-properties>
<galsync-mas>
<galma name="GAL Domain1">
<contact-type>contact_gal_Domain1</contact-type>
<target-ou>OU= GALContacts,DC=domain1,DC=local</target-ou>
<target-subou>OU=Domain1/target-subou>
</galma>
<galma name="GAL Domain2">
<contact-type>contact_gal_Domain2</contact-type>
<target-ou>OU=Contacts,DC=domain2,DC=local</target-ou>
<target-subou>OU=Domain2</target-subou>
</galma>
<galma name="GAL Domain3">
<contact-type>contact_gal_Domain3</contact-type>
<target-ou>OU=Contacts,DC=domain3,DC=local</target-ou>
<target-subou>OU=Domain3</target-subou>
</galma>
</galsync-mas>
</rules-extension-properties>
Attribute flows
Per management agent, per managed object, all object flows that use (almost) only import attribute flows must be extended, to support the target-subou attribute import flow.
Object attribute flows that are (mainly) export must not be extended for the moment.
Management agent extension (GALMA.vb)
Advanced Import flow for targetSubOU
To support the advanced import attribute flow, the GALMA code must be extended.
The following code (between the '#Customized Code markers) has been added in the "Public Sub MapAttributesForImport" section:
Select Case FlowRuleName
'# Customized Code to add
Case "targetSubOU"
Dim tempMAConfig As new GALMA
tempMAConfig = FindMA(csentry)
mventry(FlowRuleName).Value = tempMAConfig.targetSubOU
'# Customized Code to add
Case "TargetAddressMapping"
Metaverse extension (GALMV.vb)
To support subcontainers , change the provisioning code:
'# Customized Code to add
Dim strTargetDN As String = _
mventry("targetSubOU").StringValue & "," & MAConfig.SynchronizationOU
'# Customized Code to add
'# Customized Code to change
Dim dn As ReferenceValue = _
'MA.EscapeDNComponent(rdn).Concat(MAConfig.SynchronizationOU)
MA.EscapeDNComponent(rdn).Concat(strTargetDN)
'# Customized Code to change
Note
The GALSync solution does not create the parent automatically.
The hierarchical structure is not dynamic, each MA has it's fixed position in the target GAL contacts OU.
So the function to create the parent is not added to the procedure.
GAL Utils extension (GALUtil.vb)
GAL MA Class
In the GALUtil.vb code, the following sections must be updated:
Public Class GALMA
'# Customized Code to add - begin 1
Public targetSubOU As String
'# Customized Code to add - end 1
End Class
XML Configuration tags
Add the customized code like:
Const GAL_SYNC_MA_XF_DELEGATION As String = _
"cross-forest-delegation"
'# Customized Code to add - begin 2
Const GAL_SYNC_MA_TARGET_SUBOU As String = _
"target-subOU"
'# Customized Code to add - end 2
FindMA Function
To call the FindMA function outside the code section, "private" cannot be used.
'# Customized Code to change - begin 3
'Private Function FindMA( _
Protected Function FindMA( _
ByVal csentry As CSEntry) _
As GALMA
'# Customized Code to change - end 3
GetSubOUNames (Custom function, added to out-of-the box code)
'# Customized code to add - begin 4
Public Sub GetSubOUNames(ByRef refHT As Hashtable)
Dim xMLDoc As XmlDocument = New XmlDocument
xMLDoc.Load(Utils.ExtensionsDirectory ├ "\GALSync_subOUs.xml")
Dim xmlnodeMA As XmlNode
Dim iCount As Integer
Dim xMLMaAttribute As XmlAttribute
Dim strMAName As String
Dim xMLnode As XmlNode
Dim xMLNodeMAs As XmlNode =xMLDoc.SelectSingleNode( "/" & MMS_RULES_EXTENSION & "/" ├ GAL_SYNC_MAS)
Dim xMLnodeMAList As XmlNodeList = xMLNodeMAs.SelectNodes(GAL_SYNC_MA)
For iCount = 0 To xMLnodeMAList.Count - 1
xmlnodeMA = xMLnodeMAList.Item(iCount)
' Find MA Name
For Each xMLMaAttribute In xmlnodeMA.Attributes
If "name" = xMLMaAttribute.Name() Then
strMAName = xMLMaAttribute.InnerText().Trim()
Exit For
End If
Next
If IsNothing(strMAName) Then
Throw New UnexpectedDataException( _
"No MA name Attribute in subOU configuration XML")
End If
' Read target Sub OU info
XmlNode = xmlnodeMA.SelectSingleNode(GAL_SYNC_MA_TARGET_SUBOU)
If Not IsNothing(XmlNode) Then
'add MA Name and MA subOU name to hashtable
'refHT.add(MAName, SubOUName)
refHT.Add(strMAName, xMLnode.InnerText().Trim())
End If
Next iCount
End Sub
'# Customized code to add - end 4
GetConFigurationData
/../
doc.Load(Utils.ExtensionsDirectory ├ "\GALSync.xml")
'# Customized code to add - begin 5
'' GALSync.xml is updated/modified by ILM/MIIS when saving a GAL MA configuration
'' thus GALSync.XML is not usable to store custom data, like subOU info
'' the subOU info is stored in a separate XML file "GALSync_subous.xml", similar to GALSync.XML
'' GALSync_subous.xml info is loaded in to hash table
Dim hTsubOU As New Hashtable
GetSubOUNames(hTsubOU)
'# Customized code to add ) end 5
nodeMAs = doc.SelectSingleNode("/" & MMS_RULES_EXTENSION & "/" ├ GAL_SYNC_MAS)
/../
/../
MAConfig.MailRouting = False
'# Customized code to add - begin 6
MAConfig.targetSubOU = Nothing
'# Customized code to add - end 6
' Find MA Name
For Each maAttribute In nodeMA.Attributes
If "name" = maAttribute.Name() Then
MAConfig.MAName = maAttribute.InnerText().Trim()
Exit For
End If
Next
If IsNothing(MAConfig.MAName) Then
Throw New UnexpectedDataException( _
"No MA name Attribute in configuration XML")
End If
'# Customized code to add - begin 7
'' Read target Sub OU info from hash table
'' that was initialized before
''if HT does not contain the MAName, throw error
If Not hTsubOU.Contains(MAConfig.MAName) Then
Throw New UnexpectedDataException( _
"No MA name Attribute in hash table configuration")
End If
MAConfig.targetSubOU = hTsubOU.Item(MAConfig.MAName).ToString
'# Customized code to add - end 7
' Read contact type
/../
Exchange Server Configuration
With Exchange 2003/2007, it is not possible to create an global address list based on objects in an OU.
To create a global address list with a custom query, you must use an existing attribute of an user, contact, distribution group.
This procedure uses the extensionAttribute15 to store a value.
The msExchOriginatingForest attribute, which is maintained by the GAL Sync, is propagated to the extensionAttribute15 attribute.
This allows for creating an address list based on a contact attribute.
Every target forest has a corresponding OU container in the GAL contacts structure.
For every existing (or new) target forest, create an address list.
ExtensionAttribute15 contains the FQDN of the source forest.
Example: domain1.local for GAL Domain1, domain2.local for GAL Domain2
Note
This article is not discussing provisioning to Exchange 2007 / Exchange 2010.
When using GALSync with these systems, make sure you install the proper tooling. (Powershell, Exchange Management Console, ..)
See Also
- Global Address List Synchronization (GALSync)
- GALSync: How to Provision Contacts to Specific OU Units Based Upon an Originating Forest