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 theExport Attribute Flow rules as PSObjects.OUTPUTSPSObjects containing the synchronization server export attribute flowrules.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 beaggregated before we output them$rules = @()### Export attribute flow rules arecontained 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){###### Handlesrc-attribute that are intrinsic (object-id )###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 = @()###### Handlesrc-attribute that are intrinsic (object-id )###$exportFlow.'scripted-mapping'.'src-attribute' | ForEach-Object {if ($_.intrinsic){$srcAttributes += "<{0}>" -F $_.'#text'}elseif ($_) # Do not addempty 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}elseif ($exportFlow.'sync-rule-mapping'.'mapping-type' -eq 'constant'){$srcAttributes = @()$scriptContext = $exportFlow.'sync-rule-mapping'.'sync-rule-value'$rule = New-Object PSObject$rule | Add-Member -MemberType noteproperty -name 'RuleType' -value 'OSR-Constant'$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}else{throw "UnsupportedExport Flow type '$($exportFlow.'sync-rule-mapping'.'mapping-type')'"}}}}}Write-Output $rules}#End}
In the Join-ImportToExportAttributeFlow function, is there really a need for "EAFMVAttribute"?
ReplyDeleteThere's 3 scenarios for each attrbute in the function IAF+EAF, IAF, EAF.
For IAF+EAF MVAttribute is part of the matching so no need for EAFMVAttribute there.
For IAF there is no EAF and it's set to null so no need for EAFMVAttribute there.
For EAF wouldn't it make more sense to map it to plain "MVAttribute" since there's no IAF mapping to it? Also would be good to include "MVObjectType" in this one since there's no IAF contributing as well. MVAttribute and MVObjectType should be required independent of whether output is for IAF,EAF, or IAF+EAF.
Is there a reason -contains is used in the matching of MVAttribute? Shouldn't they be exact like MVObjectType? Could have attributes like email, personalEmail,companyEmail, etc where email could match up with other attributes.
In the Join-ImportToExportAttributeFlow function, is there really a need for "EAFMVAttribute"?
DeleteThanks for the feedback. The difference between MVAttribute and EAFMVAttribute is that MVAttribute will always contain a single attribute, whereas EAFMVAttribute will contain the full list of MV attributes that contribute to a single EAF.
To give you an example of how this would be helpful, I ultimately dump these end-to-end flow rules into an Excel spreadsheet, where I can slice and dice them. Having the two separate columns allows me to (a) filter by a single MV attribute while at the same time (b) see the full list of MV attributes that contribute to each EAF.
Is there a reason -contains is used in the matching of MVAttribute? Shouldn't they be exact like MVObjectType?
The Powershell -contains operator matches by complete item. In order to do a wildcard search (as you demonstrate), you would do -like "*email*".
One last thing. For each IAF all matching EAFs are "linked". This means if you have more than one IAF for a unique MVObjectType/MVAttribute combo, then the same EAFs will be output more than once.
ReplyDeleteIAFs should be matched together same way each IAF is matched to EAFs.
Maybe a counter for matches to add properties such as IAFRuleType1,IAFSourceMA1,etc. Then each output object will be end to end for each MVObjectType/MVAttribute combo. Also would remove the duplicated EAFs
As I mentioned in my previous comment, exposing all possible circuits for end-to-end flow rules allows you to slice and dice the data very nicely in Excel. If this doesn't suit your needs, I encourage you to develop a new function and (if you'd like) submit it to the Codeplex team as a contribution.
DeleteAh I totally didn't think about multiple MV attributes combined for EAF! I had to add that back into my version of the function. Thanks for pointing that out.
ReplyDeleteGlad to understand the reasoning for making it work the way it does. I did use this to make my own similar function with an output that returns an array of PSObjects. Each has a MVObjectType,MVAttribute, IAFs (array of matching IAFs), and EAFs (array of matching EAFs).
I'll look at getting it submitted to Codeplex.
Here's a sample output that's readable if an array of objects isn't what you want output.
------------------------------------------------------------------------------
MVObjectType : group
MVAttribute : displayName
IAFs
----
RuleType : DIRECT
SourceMA : FIMMA
CDObjectType : Group
CDAttribute : DisplayName
ScriptContext :
PrecedenceType : equal
PrecedenceRank :
Matched : False
RuleType : ISR - direct
SourceMA : ADMA
CDObjectType : group
CDAttribute : cn
ScriptContext :
PrecedenceType : equal
PrecedenceRank :
Matched : True
EAFs
----
RuleType : DIRECT
MAName : FIMMA
CDObjectType : Group
CDAttribute : DisplayName
ScriptContext :
AllowNulls : False
Matched : True
RuleType : OSR-Direct
MAName : ADMA
CDObjectType : group
CDAttribute : displayName
ScriptContext :
AllowNulls : False
Matched : True
------------------------------------------------------------------------------