Friday, May 31, 2013

Another update to FIM Powershell module for end-to-end attribute flows

Here's another tweak to the Get-FimSyncConfiguration.psm1 module to include export attribute flows with constant sync-rule values in the end-to-end attribute flows. See highlighted sections below.

Reference version:
FIM PowerShell Modules v2.1
http://fimpowershellmodule.codeplex.com/releases/view/98374

Get-ExportAttributeFlow

<#
  .SYNOPSIS
  Gets the Export Attribute Flow Rules from Sync Server Configuration
  .DESCRIPTION
  Reads the server configuration from the XML files, and outputs theExport Attribute Flow rules as PSObjects
  .OUTPUTS
  PSObjects containing the synchronization server export attribute flowrules
  
  .EXAMPLE
  Get-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.InnerText
          
            foreach($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 = $false
                    if ([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
}

Thursday, May 9, 2013

ResolveGrammarActivity doesn't like ma-data SyncConfig-id


I tried to set up a workflow that grabs the MA ID and display name whenever an MA changes, but the grammar resolver doesn't like the SyncConfig-id attribute of the ma-data object.

This seemed so close to an error I troubleshot before, but this time I have no control over the attribute type (which is an indexed string, BTW).

Grammar expression: [//Target/SyncConfig-id]

Error:
System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.ResourceManagement.WFActivities.Resolver.GetDisplayStringFromGuid(Guid id, String[] expansionAttributes) at Microsoft.ResourceManagement.WFActivities.Resolver.ReplaceGuidWithTemplatedString(Match m) at System.Text.RegularExpressions.RegexReplacement.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat) at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator) at Microsoft.ResourceManagement.WFActivities.Resolver.GetStringAttributeValue(Object attribute) at Microsoft.ResourceManagement.WFActivities.Resolver.ResolveEvaluatorWithoutAntiXSS(String match, ResolverOptions resolveOptions) at Microsoft.ResourceManagement.WFActivities.Resolver.ResolveEvaluatorForWithAntiXSS(String match, ResolverOptions resolveOptions) at Microsoft.ResourceManagement.WFActivities.Resolver.ReplaceMatches(String input, Boolean useAntiXssEncoding, ResolverOptions resolveOptions) at Microsoft.ResourceManagement.Workflow.Hosting.ResolverEvaluationServiceImpl.ResolveLookupGrammar(Guid requestId, Guid targetId, Guid actorId, Dictionary`2 workflowDictionary, Boolean encodeForHTML, String expression) at Microsoft.ResourceManagement.Workflow.Activities.ResolveGrammarActivity.Execute(ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime) at System.Workflow.Runtime.Scheduler.Run()