Skip to content

Instantly share code, notes, and snippets.

@darrenjrobinson
Last active April 26, 2017 00:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darrenjrobinson/4fea4f3a43bb95082ea0b57f919d290c to your computer and use it in GitHub Desktop.
Save darrenjrobinson/4fea4f3a43bb95082ea0b57f919d290c to your computer and use it in GitHub Desktop.
Create MIM Declarative Synchronisation Rule
# -- Create Sync Rule ---
[xml]$SyncRuleXML = @'
<Lithnet.ResourceManagement.ConfigSync>
<!-- Sync Rule -->
<Operations>
<!-- Declare some Objects -->
<ResourceOperation operation="None" resourceType="ma-data" id="SyncRuleID">
<AnchorAttributes>
<AnchorAttribute>DisplayName</AnchorAttribute>
</AnchorAttributes>
<AttributeOperations>
<AttributeOperation operation="none" name="DisplayName">TargetMADisplayName</AttributeOperation>
<AttributeOperation operation="none" name="SyncConfig-id"></AttributeOperation>
</AttributeOperations>
</ResourceOperation>
<!-- Create SynchronizationRule -->
<ResourceOperation operation="Add Update" resourceType="SynchronizationRule" id="SyncRuleID">
<AnchorAttributes>
<AnchorAttribute>DisplayName</AnchorAttribute>
</AnchorAttributes>
<AttributeOperations>
<AttributeOperation operation="add" name="DisplayName">__OutboundSyncRule</AttributeOperation>
<AttributeOperation operation="add" name="Description">OutboundSyncRuleDescription</AttributeOperation>
<AttributeOperation operation="add" name="CreateConnectedSystemObject">true</AttributeOperation>
<AttributeOperation operation="add" name="CreateILMObject">false</AttributeOperation>
<AttributeOperation operation="add" name="FlowType">1</AttributeOperation>
<AttributeOperation operation="add" name="DisconnectConnectedSystemObject">true</AttributeOperation>
<AttributeOperation operation="add" name="ConnectedSystem">##xmlref:TargetSystem:SyncConfig-id##</AttributeOperation>
<AttributeOperation operation="add" name="ConnectedObjectType">user</AttributeOperation>
<AttributeOperation operation="add" name="ILMObjectType">person</AttributeOperation>
<AttributeOperation operation="add" name="msidmOutboundIsFilterBased">false</AttributeOperation>
<AttributeOperation operation="add" name="RelationshipCriteria">&lt;conditions&gt;&lt;condition&gt;&lt;ilmAttribute&gt;accountName&lt;/ilmAttribute&gt;&lt;csAttribute&gt;sAMAccountName&lt;/csAttribute&gt;&lt;/condition&gt;&lt;/conditions&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;department&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;department&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;description&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;description&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;company&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;company&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;department&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;department&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;company&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;company&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;accountName&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;sAMAccountName&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;displayName&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;displayName&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;firstName&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;givenName&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;company&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;company&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;lastName&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;sn&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="PersistentFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;accountName&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;name&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="InitialFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;sourceDN&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;dn&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;fn id="ReplaceString" isCustomExpression="false"&gt;&lt;arg&gt;sourceDN&lt;/arg&gt;&lt;arg&gt;"DC=customer,DC=com,DC=au"&lt;/arg&gt;&lt;arg&gt;"DC=dev,DC=customer,DC=com,DC=au"&lt;/arg&gt;&lt;/fn&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="InitialFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;512&lt;/src&gt;&lt;dest&gt;userAccountControl&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="InitialFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;P@ssw0rd&lt;/src&gt;&lt;dest&gt;unicodePwd&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="InitialFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;sourceDN&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;dn&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;fn id="ReplaceString" isCustomExpression="false"&gt;&lt;arg&gt;sourceDN&lt;/arg&gt;&lt;arg&gt;"DC=customer,DC=com,DC=au"&lt;/arg&gt;&lt;arg&gt;"DC=dev,DC=customer,DC=com,DC=au"&lt;/arg&gt;&lt;/fn&gt;&lt;/export-flow&gt;</AttributeOperation>
<AttributeOperation operation="add" name="InitialFlow">&lt;export-flow allows-null="false"&gt;&lt;src&gt;&lt;attr&gt;sourceUPN&lt;/attr&gt;&lt;/src&gt;&lt;dest&gt;userPrincipalName&lt;/dest&gt;&lt;scoping&gt;&lt;/scoping&gt;&lt;fn id="ReplaceString" isCustomExpression="false"&gt;&lt;arg&gt;sourceUPN&lt;/arg&gt;&lt;arg&gt;"@"&lt;/arg&gt;&lt;arg&gt;"@dev."&lt;/arg&gt;&lt;/fn&gt;&lt;/export-flow&gt;</AttributeOperation>
</AttributeOperations>
</ResourceOperation>
</Operations>
</Lithnet.ResourceManagement.ConfigSync>
'@
# https://gist.github.com/jpoehls/2726969
function Edit-XmlNodes {
param (
[xml] $doc = $(throw "doc is a required parameter"),
[string] $xpath = $(throw "xpath is a required parameter"),
[string] $value = $(throw "value is a required parameter"),
[bool] $condition = $true
)
if ($condition -eq $true) {
$nodes = $doc.SelectNodes($xpath)
foreach ($node in $nodes) {
if ($node -ne $null) {
if ($node.NodeType -eq "Element") {
$node.InnerXml = $value
}
else {
$node.Value = $value
}
}
}
}
}
Function Get-Folder($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$foldername = New-Object System.Windows.Forms.FolderBrowserDialog
$foldername.rootfolder = "MyComputer"
if($foldername.ShowDialog() -eq "OK")
{
$folder += $foldername.SelectedPath
}
return $folder
}
# PSM to query MIM Sync Server
import-module LithnetMIISAutomation
# PSM to create MIM Service Objects
Import-Module LithnetRMA
# Where will we put the files we generate to create our rules?
$WorkingDirectory = Get-Folder
$WorkingDirectory[1]
# SyncRuleIDName
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
$title = 'What do you want to name your Sync Rule?'
$msg = 'Enter your Synchronisation Rule Name:'
$SyncRuleIDDisplayName = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title)
$SyncRuleIDDisplayName
# Get all my AD Management Agents
$ADmanagementAgents = Get-ManagementAgent | where-object {$_.category -eq "AD" } | select Name
# Prompt for Target MA for Sync Rule
If($ADmanagementAgents.Count -gt 1){
$title = "Target Management Agent Selection"
$message = "What is the Target MA for they Sync Rule?"
# Build the choices menu
$choices = @()
For($index = 0; $index -lt $ADmanagementAgents.Count; $index++){
$choices += New-Object System.Management.Automation.Host.ChoiceDescription ($ADmanagementAgents[$index]).Name, ($ADmanagementAgents[$index]).Name
}
$options = [System.Management.Automation.Host.ChoiceDescription[]]$choices
$result = $host.ui.PromptForChoice($title, $message, $options, 0)
$targetMA = $ADmanagementAgents[$result]
}
$targetMA.Name
#Find all nodes of type "Resource Operation" with attribute ID
$ids = $SyncRuleXML | Select-Xml -Xpath "//ResourceOperation[@id]"
write-host "Sync Rule ID's"
$ids.node
# Generate ID's for each of the objects we will create
# Sync Rule
$SyncRuleIDName = ($SyncRuleIDDisplayName -replace '[\W]', '')+"-SyncRule"
Write-Host "Sync Rule ID Name $SyncRuleIDName"
# Workflow
$WorkflowIDName = ($SyncRuleIDDisplayName -replace '[\W]', '')+"-Workflow"
Write-Host "Workflow ID Name $WorkflowIDName"
# Set
$SetIDName = ($SyncRuleIDDisplayName -replace '[\W]', '')+"-Set"
Write-Host "Set ID Name $SetIDName"
# MPR
$MPRIDName = ($SyncRuleIDDisplayName -replace '[\W]', '')+"-MPR"
Write-Host "MPR ID Name $MPRIDName"
# Update SyncRuleID from SyncRuleID to value of the SyncRuleName obtained for the user with spaces removed and -ID1 appended
Edit-XmlNodes $SyncRuleXML -xpath "/Lithnet.ResourceManagement.ConfigSync/Operations/ResourceOperation[@id='SyncRuleID']/@id" -value $SyncRuleIDName
$SyncRuleXML.'Lithnet.ResourceManagement.ConfigSync'.Operations.ResourceOperation.id
#Find the nodes with the DisplayName of the TargetMA and the Sync Rulename
$displayname = $SyncRuleXML | Select-Xml -Xpath "//AttributeOperation[@name='DisplayName']"
$displayname.node
# Update the Rule for the Management Agent that the Sync Rule will target to provision against
$node = $displayname.node | where {$_.'#text' -eq 'TargetMADisplayName'}
$node.'#text' = $targetMA.Name
# Update the Displayname for the desired SyncRule Name
$node = $displayname.node | where {$_.'#text' -eq '__OutboundSyncRule'}
$node.'#text' = $SyncRuleIDDisplayName
# Get and update the SyncRule Description
$description = $SyncRuleXML | Select-Xml -Xpath "//AttributeOperation[@name='Description']"
$description.node.'#text' = $SyncRuleIDDisplayName
# Get and update the node for the Connected System
$connectedSystems = $SyncRuleXML | Select-Xml -Xpath "//AttributeOperation[@name='ConnectedSystem']"
$connectedSystems.node.'#text' = ("##xmlref:"+$SyncRuleIDName+":SyncConfig-id##")
# Output the CreateSyncRule input file
$SyncRuleXML.save($WorkingDirectory[1]+"\CreateNewSyncRule.xml")
# Create User Sync Rule
Import-RMConfig -File ($WorkingDirectory[1]+"\CreateNewSyncRule.xml") # -Preview -Verbose
# Get the Sync Rule just created and get its ObjectID for the Workflow
$importedSyncRule = Get-Resource SynchronizationRule DisplayName $SyncRuleIDDisplayName | select ObjectID
$importedSyncRuleObjID = [string]$importedSyncRule.ObjectID -replace("urn:uuid:","")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment