Reference version:
FIM PowerShell Modules v2.1
http://fimpowershellmodule.codeplex.com/releases/view/98374
Get-ExportAttributeFlow
<#.SYNOPSISGets the Export Attribute Flow Rules from Sync Server Configuration.DESCRIPTIONReads the server configuration from the XML files, and outputs the Export Attribute Flow rules as PSObjects.OUTPUTSPSObjects containing the synchronization server export attribute flow rules.EXAMPLEGet-ExportAttributeFlow-ServerConfigurationFolder"E:\sd\IAM\ITAuthorize\Source\Configuration\FimSync\ServerConfiguration"#>Function Get-ExportAttributeFlow{Param([parameter(Mandatory=$false)][String][ValidateScript({Test-Path $_})]$ServerConfigurationFolder)End{### This is where the rules will be aggregated before we output them$rules =@()### Export attribute flow rules are contained in the ma-data nodes of the MA*.XML files$maFiles = @(get-item (Join-Path $ServerConfigurationFolder "MA-*.xml"))foreach ($maFile in $maFiles){### Get the MA Name and MA ID$maName = (select-xml $maFile -XPath "//ma-data/name").Node.InnerTextforeach($exportFlowSet in (Select-Xml -path $maFile -XPath "//export-flow-set" | select -ExpandProperty Node)){$mvObjectType = $exportFlowSet.'mv-object-type'$cdObjectType = $exportFlowSet.'cd-object-type'foreach($exportFlow in $exportFlowSet.'export-flow'){$cdAttribute = $exportFlow.'cd-attribute'[bool]$allowNulls = $falseif ([bool]::TryParse($exportFlow.'suppress-deletions', [ref]$allowNulls)){$allowNulls = -not $allowNulls}if ($exportFlow.'direct-mapping' -ne $null){###### Handle src-attribute that are intrinsic (<src-attribute intrinsic="true">object-id</src-attribute>)###if ($exportFlow.'direct-mapping'.'src-attribute'.intrinsic){$srcAttribute = "<{0}>" -F $exportFlow.'direct-mapping'.'src-attribute'.'#text'}else{$srcAttribute = $exportFlow.'direct-mapping'.'src-attribute'}$rule = New-Object PSObject$rule | Add-Member -MemberType noteproperty -name 'RuleType' -value 'DIRECT'$rule | Add-Member -MemberType noteproperty -name 'MAName' -value $maName$rule | Add-Member -MemberType noteproperty -name 'MVObjectType' -value $mvObjectType$rule | Add-Member -MemberType noteproperty -name 'MVAttribute' -value $srcAttribute$rule | Add-Member -MemberType noteproperty -name 'CDObjectType' -value $cdObjectType$rule | Add-Member -MemberType noteproperty -name 'CDAttribute' -value $cdAttribute$rule | Add-Member -MemberType noteproperty -name 'ScriptContext' -value $null$rule | Add-Member -MemberType noteproperty -name 'AllowNulls' -value $allowNulls$rules += $rule}elseif ($exportFlow.'scripted-mapping' -ne $null){$scriptContext = $exportFlow.'scripted-mapping'.'script-context'$srcAttributes = @()###### Handle src-attribute that are intrinsic (<src-attribute intrinsic="true">object-id</src-attribute>)###$exportFlow.'scripted-mapping'.'src-attribute' | ForEach-Object {if ($_.intrinsic){$srcAttributes += "<{0}>" -F $_.'#text'}elseif ($_) # Do not add empty values.{$srcAttributes += $_}}# (Commented) Leave as collection.#if ($srcAttributes.Count-eq 1)#{# $srcAttributes = $srcAttributes -as[String]#}$rule = New-Object PSObject$rule | Add-Member -MemberType noteproperty -name 'RuleType' -value 'SCRIPTED'$rule | Add-Member -MemberType noteproperty -name 'MAName' -value $maName$rule | Add-Member -MemberType noteproperty -name 'MVObjectType' -value $mvObjectType$rule | Add-Member -MemberType noteproperty -name 'MVAttribute' -value $srcAttributes$rule | Add-Member -MemberType noteproperty -name 'CDObjectType' -value $cdObjectType$rule | Add-Member -MemberType noteproperty -name 'CDAttribute' -value $cdAttribute$rule | Add-Member -MemberType noteproperty -name 'ScriptContext' -value $scriptContext$rule | Add-Member -MemberType noteproperty -name 'AllowNulls' -value $allowNulls$rules += $rule}elseif ($exportFlow.'sync-rule-mapping' -ne $null){$srcAttribute = $exportFlow.'sync-rule-mapping'.'src-attribute'if($exportFlow.'sync-rule-mapping'.'mapping-type' -eq 'direct'){$rule = New-Object PSObject$rule | Add-Member -MemberType noteproperty -name 'RuleType' -value 'OSR-Direct'$rule | Add-Member -MemberType noteproperty -name 'MAName' -value $maName$rule | Add-Member -MemberType noteproperty -name 'MVObjectType' -value $mvObjectType$rule | Add-Member -MemberType noteproperty -name 'MVAttribute' -value $srcAttribute$rule | Add-Member -MemberType noteproperty -name 'CDObjectType' -value $cdObjectType$rule | Add-Member -MemberType noteproperty -name 'CDAttribute' -value $cdAttribute$rule | Add-Member -MemberType noteproperty -name 'ScriptContext' -value $null$rule | Add-Member -MemberType noteproperty -name 'AllowNulls' -value $allowNulls$rules += $rule}elseif ($exportFlow.'sync-rule-mapping'.'mapping-type' -eq 'expression'){$scriptContext = $exportFlow.'sync-rule-mapping'.'sync-rule-value'.'export-flow'.InnerXml$srcAttribute = $exportFlow.'sync-rule-mapping'.'sync-rule-value'.'export-flow'.dest$rule = New-Object PSObject$rule | Add-Member -MemberType noteproperty -name 'RuleType' -value 'OSR-Expression'$rule | Add-Member -MemberType noteproperty -name 'MAName' -value $maName$rule | Add-Member -MemberType noteproperty -name 'MVObjectType' -value $mvObjectType$rule | Add-Member -MemberType noteproperty -name 'MVAttribute' -value $srcAttribute$rule | Add-Member -MemberType noteproperty -name 'CDObjectType' -value $cdObjectType$rule | Add-Member -MemberType noteproperty -name 'CDAttribute' -value $cdAttribute$rule | Add-Member -MemberType noteproperty -name 'ScriptContext' -value $scriptContext$rule | Add-Member -MemberType noteproperty -name 'AllowNulls' -value $allowNulls$rules += $rule}else{throw "Unsupported Export Flow type"}}}}}Write-Output $rules}#End}
Join-ImportToExportAttributeFlow
<#.SYNOPSISGets the Joined Rules where the IAF rules are joined to the EAF rules based on the MV Attributes and Object Types.DESCRIPTIONReads the server configuration from the XML files, and outputs the Joined IAF and EAF Rules as PSObjects.OUTPUTSPSObjects containing the synchronization server attribute flow rules.EXAMPLEJoin-ImportToExportAttributeFlow-ServerConfigurationFolder"E:\sd\IAM\ITAuthorize\Source\Configuration\FimSync\ServerConfiguration"#>Function Join-ImportToExportAttributeFlow{[CmdletBinding()]Param([parameter(Mandatory=$false)][String][ValidateScript({Test-Path $_})]$ServerConfigurationFolder)End{### Get the Import Attribute Flow Rules$IAF = Get-ImportAttributeFlow -ServerConfigurationFolder $ServerConfigurationFolder### Get the Export Attribute Flow Rules$EAF = Get-ExportAttributeFlow -ServerConfigurationFolder $ServerConfigurationFolder### This is where the rules will be aggregated before we output them$e2eFlowRules =@()foreach ($iafRule in $IAF){### Look for a corresponding EAF rule$eafMatches = @($EAF | where {$_.'MVAttribute' -contains $iafRule.'MVAttribute' -and $_.'MVObjectType' -eq $iafRule.'MVObjectType'})### There may be multiple EAF rule for each IAF rulesif ($eafMatches.count -gt 0){foreach($eafRule in $eafMatches){$e2eFlowRuleProperties =@{'IAFRuleType' = $iafRule.'RuleType''IAFSourceMA' = $iafRule.'SourceMA''IAFCDObjectType' = $iafRule.'CDObjectType''IAFCDAttribute' = $iafRule.'CDAttribute''IAFScriptContext' = $iafRule.'ScriptContext''IAFPrecedenceType' = $iafRule.'PrecedenceType''IAFPrecedenceRank' = $iafRule.'PrecedenceRank''MVObjectType' = $iafRule.'MVObjectType''MVAttribute' = $iafRule.'MVAttribute''EAFMVAttribute' = $eafRule.'MVAttribute''EAFCDAttribute' = $eafRule.'CDAttribute''EAFTargetMA' = $eafRule.'MAName''EAFCDObjectType' = $eafRule.'CDObjectType''EAFRuleType' = $eafRule.'RuleType''EAFScriptContext' = $eafRule.'ScriptContext'}$e2eFlowRules += New-Object PSObject -Property $e2eFlowRuleProperties}}### It is possible there are NO EAF rules for an IAF rule### here we stuff $null into the EAF side to make our output easy to consume for Out-GridView and Compare-Object### otherwise jagged objects seem to confuse things###### In this case the rule may be useless### Or the use of that MV attribute may not be visible here because some rules extension calls it (need to check the source code to confirm)else{$e2eFlowRuleProperties =@{'IAFRuleType' = $iafRule.'RuleType''IAFSourceMA' = $iafRule.'SourceMA''IAFCDObjectType' = $iafRule.'CDObjectType''IAFCDAttribute' = $iafRule.'CDAttribute''IAFScriptContext' = $iafRule.'ScriptContext''IAFPrecedenceType' = $iafRule.'PrecedenceType''IAFPrecedenceRank' = $iafRule.'PrecedenceRank''MVObjectType' = $iafRule.'MVObjectType''MVAttribute' = $iafRule.'MVAttribute''EAFMVAttribute' = $null'EAFCDAttribute' = $null'EAFTargetMA' = $null'EAFCDObjectType' = $null'EAFRuleType' = $null'EAFScriptContext' = $null}$e2eFlowRules += New-Object PSObject -Property $e2eFlowRuleProperties}}### There's one more case in which the MV attribute is blank for an EAF.foreach ($eafRule in @($EAF | where {$_.'MVAttribute'.count -eq 0})){Write-Verbose $eafRule$e2eFlowRuleProperties = @{'IAFRuleType' = $null'IAFSourceMA' = $null'IAFCDObjectType' = $null'IAFCDAttribute' = $null'IAFScriptContext' = $null'IAFPrecedenceType' = $null'IAFPrecedenceRank' = $null'MVObjectType' = $null'MVAttribute' = $null'EAFMVAttribute' = $eafRule.'MVAttribute''EAFCDAttribute' = $eafRule.'CDAttribute''EAFTargetMA' = $eafRule.'MAName''EAFCDObjectType' = $eafRule.'CDObjectType''EAFRuleType' = $eafRule.'RuleType''EAFScriptContext' = $eafRule.'ScriptContext'}$e2eFlowRules += New-Object PSObject -Property $e2eFlowRuleProperties}$e2eFlowRules | select `'IAFSourceMA',`'IAFCDObjectType',`'IAFCDAttribute',`'IAFRuleType',`'IAFScriptContext',`'IAFPrecedenceType',`'IAFPrecedenceRank',`'MVObjectType',`'MVAttribute',`'EAFMVAttribute',`'EAFTargetMA',`'EAFCDObjectType',`'EAFCDAttribute',`'EAFRuleType',`'EAFScriptContext'`}}