Jorge's Quest For Knowledge!

All About Identity And Security On-Premises And In The Cloud – It's Just Like An Addiction, The More You Have, The More You Want To Have!

Archive for the ‘Workflow’ Category

(2016-10-09) How To Clear A Value (NULLing It) From An Attribute On An Object In The FIM/MIM Portal?

Posted by Jorge on 2016-10-09


It might be the case you want to flow a NULL value into some attribute, or in other words clearing an attribute value, when meeting some condition.

In the sync rules a "Null()" function exists, which might give you the idea that it flows a NULL value. Au contraire, mon ami! The "Null()" function basically means "do nothing". One of the examples of using that function is in combination with the "IIF()" function. The "IIF()" function translates into "If…Then…Else". Sometimes, you just want to have "If…Then" and you do not care about the “Else”, and that’s when you use the "Null()" function when using the “IIF()” function.

For example:

IIF(Eq(X,"1"),Y,Null()) ==> Z

means…..

If X=1 then Z=Y

So, how do you clear a value in the FIM/MIM Portal? It is not possible by default, therefore you need a custom workflow activity to do that for you.

On codeplex you will find Soren Granfeldt’s "FIM 2010 Granfeldt Workflow Activity Library". This Activity Library is a collection of generic custom workflows for use with FIM 2010 R1/R2 and MIM 2016. The purpose of this collection of workflow activities is to have activities that can solve the most common tasks in a traditional FIM installation – in one library.

As you can read in the documentation, it now supports an activity to clear an attribute value from the specified attribute. However, when downloading the activity, the old activity that does support this is still targeted for download. A workaround for this is to use the Code Run activity.

After adding the “Code Run” activity to the workflow:

  • Enter something in the “Title” field explaining what it does
  • In the “References (DLL’s)” field enter: System.dll
  • No need to specify anything in the “Parameters” field
  • In the “Code” field specify the following code:

using System;
public class FIMDynamicClass
{
            public static object FIMDynamicFunction()
            {
                    return null;
            }
}

  • In the “Destination” field specify the targeted attribute for which its value must be cleared using the format: [//Target/<Attribute>] where <Attribute> is replaced with the attribute you need to be cleared

image

Figure 1: Clearing An Attribute Using The Code Run Activity In Soren Granfeldt’s "FIM 2010 Granfeldt Workflow Activity Library"

You can also use the MIM WAL activity to do the same which is available on Github. The MIMWAL is a Workflow Activity Library (WAL) solution for configuring complex Workflows in the Microsoft Identity Manager (MIM) 2016 and Forefront Identity Manager (FIM) 2010 R2 solution.

After adding the “Update Resources” activity to the workflow:

  • Enter something in the “Activity Display Name” field explaining what it does
  • No need to use the advanced features of the activity
  • In the “Value Exprssion” field specify 2 quotes ""
  • In the “Target” field specify the targeted attribute for which its value must be cleared using the format: [//Target/<Attribute>] where <Attribute> is replaced with the attribute you need to be cleared
  • Make sure to check “Allow Null”

image

Figure 2: Clearing An Attribute Using The Update Resources Activity In The MIMWAL (MIM Workflow Activity Library)

Have fun!

Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
#########
http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————

Posted in Activities, Forefront Identity Manager (FIM) Portal, Workflow | Leave a Comment »

(2016-01-14) Public Availability Of The MIM WAL Project

Posted by Jorge on 2016-01-14


Announcing the public availability of the MIMWAL project, now available as an Open Source Project on GitHub.

The MIMWAL is a Workflow Activity Library (WAL) for building complex workflows in the Microsoft Identity Manager (MIM) 2016 and Forefront Identity Manager (FIM) 2010 R2 solution. The WAL is a powerful solution accelerator for MIM / FIM that provides foundational activities which can be combined to create complex workflows to implement business processes within a MIM / FIM solution simply by configuration instead of coding for days and months.

image

Figure 1: Available Activities Within FIM/MIM WAL

MIMWAL Features

  • Building-block Workflow Activities
  • Conditional Execution Capability for Building-block Activities
  • Support for Iteration Over a Collection of Values in Building-block Activities
  • Deep Resolution Capability for FIM Lookup Grammar
  • Rich Library of Workflow Functions
  • UI Framework for Building Additional Custom Workflow Activities
  • Support for ETW Event Tracing
  • Optimization of Update Requests
    • Combining multiple updates into a single request per resource per activity
    • Issuing update request only when resource is actually modified.

Supported Product Versions

  • Forefront Identity Manager (FIM) 2010 R2 – 4.1.3496 and above
  • Microsoft Identity Manager (MIM) 2016 – 4.3.1935 and above.

More information

Please visit the MIMWAL site at http://aka.ms/MIMWAL for information on project source code, releases and documentation, and discussion forums.

Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
#########
http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————

Posted in Forefront Identity Manager (FIM) Portal, Workflow | Leave a Comment »

(2015-02-28) FIM Fails With "Unable To Create New WorkflowInstance For WorkflowDefinition"

Posted by Jorge on 2015-02-28


Currently my AD/ADFS/FIM environment was running on one server including all other required software components such as Exchnage, SQL and Sharepoint. I wanted a more flexible configuration so I decided to split up the different roles and reinstalled the environment including everything in it. Configurations were either redone or migrated. In the case of FIM I migrated the configuration using the known migration tools/scripts/methods. At the same time I also reconfigured a few things (e.g. Workflows) in FIM. Because of the additional changes I tested the worflows that were impacted as those were using custom activities. Everything appeared to be fine! The FIM Portal in the new environment was running on Sharepoint Foundation 2013 and with regards to FIM the latest available build at the time of writing was being used.

To uniquely identity every object in the FIM Portal an wanted to assign a global ID to group and user objects. User objects already had that so I only needed to configure stuff for groups. For this task I was using OCG’s Function Evaluator to generate a GUID. As I already had that activity configured somewhere I decided to copy that specific configuration and put it in a new workflow which I configured with "Run On Policy Update (ROPU). Then I created a set and a transition based MPR. I disabled the MPR, committed that and re-enabled it again. Thinking to be done very quickly I checked all requests and I expected to see only completes. WRONG I only saw tons of PostProcessingErrors as shown below.

image

Figure 1: PostProcessing Errors For Requests

Looking at the one of the System Event Request

image

Figure 2: PostProcessing Errors For Requests

Looking at the event viewer

image

Figure 2: "Unable To Create New WorkflowInstance For WorkflowDefinition" Error In The "Forefront Event Viewer" Event Viewer Log

Microsoft.ResourceManagement: Microsoft.ResourceManagement.Workflow.Hosting.WorkflowManagerException: Unable to create new WorkflowInstance for WorkflowDefinition ‘cb6b64a3-9785-4dfe-aab2-5b4e8338eee2’. —> System.Workflow.ComponentModel.Compiler.WorkflowValidationFailedException: The workflow failed validation.
   at System.Workflow.Runtime.Hosting.DefaultWorkflowLoaderService.CreateInstance(XmlReader workflowDefinitionReader, XmlReader rulesReader)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.LoadRootActivity(String xomlText, String rulesText, Byte[] xomlHashCode, Boolean createDefinition, Boolean initForRuntime)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.MruCache.GetOrGenerateDefinition(Type type, String xomlText, String rulesText, Byte[] md5Codes, Boolean initForRuntime, Boolean& exist)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.GetRootActivity(String xomlText, String rulesText, Boolean createNew, Boolean initForRuntime)
   at System.Workflow.Runtime.WorkflowRuntime.InitializeExecutor(Guid instanceId, CreationContext context, WorkflowExecutor executor, WorkflowInstance workflowInstance)
   at System.Workflow.Runtime.WorkflowRuntime.Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)
   at System.Workflow.Runtime.WorkflowRuntime.GetWorkflowExecutor(Guid instanceId, CreationContext context)
   at System.Workflow.Runtime.WorkflowRuntime.InternalCreateWorkflow(CreationContext context, Guid instanceId)
   at System.Workflow.Runtime.WorkflowRuntime.CreateWorkflow(XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary`2 namedArgumentValues, Guid instanceId)
   at Microsoft.ResourceManagement.Workflow.Hosting.WorkflowManager.StartWorkflowInstance(Guid workflowInstanceIdentifier, KeyValuePair`2[] additionalParameters)
   — End of inner exception stack trace —
   at Microsoft.ResourceManagement.Utilities.ExceptionManager.ThrowException(Exception exception)
   at Microsoft.ResourceManagement.Workflow.Hosting.WorkflowManager.StartWorkflowInstance(Guid workflowInstanceIdentifier, KeyValuePair`2[] additionalParameters)

After seeing this error, I tried an already existing workflow using the same function evaluator and the same activity configuration. That worked perfectly, therefore there was nothing wrong with the AIC configuration of the activity and the corresponding DLLs.

Because the previous errors did not help in any way and to see if I could get more information I decided to enable tracing for the FIM Service as described through the following blog post "(2013-11-01) Advanced Logging, Event Tracing Or Troubleshooting Within FIM Components".

Basically you comment the default "Default Diagnostics configuration" and remove the comment from the "Advanced Diagnostics Configuration (Full Diagnostics configuration)" and restart the FIM service. Then retrigger the workflow. By the way: DO NOT forget to disable tracing afterwards!!!

REMARK: make sure to specify a path where the log files should be created!!!

In the trace log ("Microsoft.ResourceManagement.Service_tracelog.txt") I saw the following:

    ThreadId=4
    DateTime=2014-12-14T19:18:50.2133779Z
Microsoft.ResourceManagement Error: 3 : Microsoft.ResourceManagement: Microsoft.ResourceManagement.Workflow.Hosting.WorkflowManagerException: Unable to create new WorkflowInstance for WorkflowDefinition ‘cb6b64a3-9785-4dfe-aab2-5b4e8338eee2’. —> System.Workflow.ComponentModel.Compiler.WorkflowValidationFailedException: The workflow failed validation.
   at System.Workflow.Runtime.Hosting.DefaultWorkflowLoaderService.CreateInstance(XmlReader workflowDefinitionReader, XmlReader rulesReader)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.LoadRootActivity(String xomlText, String rulesText, Byte[] xomlHashCode, Boolean createDefinition, Boolean initForRuntime)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.MruCache.GetOrGenerateDefinition(Type type, String xomlText, String rulesText, Byte[] md5Codes, Boolean initForRuntime, Boolean& exist)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.GetRootActivity(String xomlText, String rulesText, Boolean createNew, Boolean initForRuntime)
   at System.Workflow.Runtime.WorkflowRuntime.InitializeExecutor(Guid instanceId, CreationContext context, WorkflowExecutor executor, WorkflowInstance workflowInstance)
   at System.Workflow.Runtime.WorkflowRuntime.Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)
   at System.Workflow.Runtime.WorkflowRuntime.GetWorkflowExecutor(Guid instanceId, CreationContext context)
   at System.Workflow.Runtime.WorkflowRuntime.InternalCreateWorkflow(CreationContext context, Guid instanceId)
   at System.Workflow.Runtime.WorkflowRuntime.CreateWorkflow(XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary`2 namedArgumentValues, Guid instanceId)
   at Microsoft.ResourceManagement.Workflow.Hosting.WorkflowManager.StartWorkflowInstance(Guid workflowInstanceIdentifier, KeyValuePair`2[] additionalParameters)
   — End of inner exception stack trace —

…….

Microsoft.ResourceManagement Verbose: 0 : Entered RequestDispatcher with Request Object; RequestIdentifier ’80cf1669-6933-4047-9db2-9c8032d95177′.
    ThreadId=12
    DateTime=2014-12-14T19:18:54.9869166Z
Microsoft.ResourceManagement Verbose: 0 : Add request ’80cf1669-6933-4047-9db2-9c8032d95177′ to cache with RequestStatus ‘Committed’.
    ThreadId=12
    DateTime=2014-12-14T19:18:54.9869166Z
Microsoft.ResourceManagement Information: 1 : RequestDispatcher enter processing pipeline;  RequestIdentifier ’80cf1669-6933-4047-9db2-9c8032d95177′; Operation ‘SystemEvent’; Object ‘Group’; RequestStatus ‘Committed’.
    ThreadId=12
    DateTime=2014-12-14T19:18:54.9869166Z
Microsoft.ResourceManagement Verbose: 0 : RequestDispatcher is processing RequestIdentifier ’80cf1669-6933-4047-9db2-9c8032d95177′ for a ‘SystemEvent’ operation on object ‘Group’ with RequestStatus ‘Committed’.
    ThreadId=12
    DateTime=2014-12-14T19:18:55.1744221Z
Microsoft.ResourceManagement Verbose: 0 : Request ’80cf1669-6933-4047-9db2-9c8032d95177′ status was updated in-memory from ‘Committed’ to ‘PostProcessing’.
    ThreadId=12
    DateTime=2014-12-14T19:18:55.1744221Z
Microsoft.ResourceManagement Verbose: 0 : Request ’80cf1669-6933-4047-9db2-9c8032d95177′ updates have been persisted to permanent storage.
    ThreadId=12
    DateTime=2014-12-14T19:18:57.5766555Z
Microsoft.ResourceManagement Error: 3 : WorkflowManager could not deserialize XOML definition: ‘<ns0:SequentialWorkflow ActorId="00000000-0000-0000-0000-000000000000" RequestId="00000000-0000-0000-0000-000000000000" x:Name="SequentialWorkflow" TargetId="00000000-0000-0000-0000-000000000000" WorkflowDefinitionId="00000000-0000-0000-0000-000000000000" xmlns:ns1="clr-namespace:T4FIM.FunctionEvaluator;Assembly=T4FIM.FunctionEvaluator, Version=4.0.0.2, Culture=neutral, PublicKeyToken=1cff8ccc43c5c5ec" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow&quot; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:ns0="clr-namespace:Microsoft.ResourceManagement.Workflow.Activities;Assembly=Microsoft.ResourceManagement, Version=4.1.3613.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
    <ns1:WorkflowPart CurrentRequest="{x:Null}" readTarget_Resource="{x:Null}" Destination="globalEmployeeID" DestinationType="Target" ControlTitle="Set GlobalEmployeeID" FunctionText="Replace(Right(Left(GUID(),37),36),&quot;-&quot;,&quot;&quot;)" WorkflowEnabled="True" resolveGrammarActivity_ResolvedExpression="{x:Null}" readReferenceAndAttributes_Resource="{x:Null}" LogMessage="GlobalEmployeeID" x:Name="authenticationGateActivity1" resolveGrammarActivity_GrammarExpression="{x:Null}">
        <ns2:ReceiveActivity.WorkflowServiceAttributes xmlns:ns2="clr-namespace:System.Workflow.Activities;Assembly=System.WorkflowServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <ns2:WorkflowServiceAttributes ConfigurationName="OCG.Workflow" Name="Workflow" />
        </ns2:ReceiveActivity.WorkflowServiceAttributes>
    </ns1:WorkflowPart>
</ns0:SequentialWorkflow>’.
    ThreadId=12
    DateTime=2014-12-14T19:18:57.6702055Z
Microsoft.ResourceManagement Information: 1 : 347 :  : Invalid Element ‘ReceiveActivity.WorkflowServiceAttributes’ found while deserializing an object of type ‘T4FIM.FunctionEvaluator.WorkflowPart’.
    ThreadId=12
    DateTime=2014-12-14T19:18:57.6702055Z
Microsoft.ResourceManagement Information: 1 : 347 :  : Invalid data found while deserializing an object of type ‘T4FIM.FunctionEvaluator.WorkflowPart’.
    ThreadId=12
    DateTime=2014-12-14T19:18:57.6702055Z
Microsoft.ResourceManagement Error: 3 : Microsoft.ResourceManagement.Workflow.Hosting.WorkflowManagerException: Unable to create new WorkflowInstance for WorkflowDefinition ‘cb6b64a3-9785-4dfe-aab2-5b4e8338eee2’. —> System.Workflow.ComponentModel.Compiler.WorkflowValidationFailedException: The workflow failed validation.
   at System.Workflow.Runtime.Hosting.DefaultWorkflowLoaderService.CreateInstance(XmlReader workflowDefinitionReader, XmlReader rulesReader)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.LoadRootActivity(String xomlText, String rulesText, Byte[] xomlHashCode, Boolean createDefinition, Boolean initForRuntime)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.MruCache.GetOrGenerateDefinition(Type type, String xomlText, String rulesText, Byte[] md5Codes, Boolean initForRuntime, Boolean& exist)
   at System.Workflow.Runtime.WorkflowDefinitionDispenser.GetRootActivity(String xomlText, String rulesText, Boolean createNew, Boolean initForRuntime)
   at System.Workflow.Runtime.WorkflowRuntime.InitializeExecutor(Guid instanceId, CreationContext context, WorkflowExecutor executor, WorkflowInstance workflowInstance)
   at System.Workflow.Runtime.WorkflowRuntime.Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)
   at System.Workflow.Runtime.WorkflowRuntime.GetWorkflowExecutor(Guid instanceId, CreationContext context)
   at System.Workflow.Runtime.WorkflowRuntime.InternalCreateWorkflow(CreationContext context, Guid instanceId)
   at System.Workflow.Runtime.WorkflowRuntime.CreateWorkflow(XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary`2 namedArgumentValues, Guid instanceId)
   at Microsoft.ResourceManagement.Workflow.Hosting.WorkflowManager.StartWorkflowInstance(Guid workflowInstanceIdentifier, KeyValuePair`2[] additionalParameters)
   — End of inner exception stack trace —

Based upon my experience, when I see something like "deserializing", I know something is wrong with the XOML definition of the new workflow. The question is WHY, as another workflow with the same configuration did work! Because of I decided to compare the XOML definition of workflow that worked and the one that failed

XOML Definition for working WFW

<ns0:SequentialWorkflow x:Name="SequentialWorkflow" ActorId="00000000-0000-0000-0000-000000000000" WorkflowDefinitionId="00000000-0000-0000-0000-000000000000" RequestId="00000000-0000-0000-0000-000000000000" TargetId="00000000-0000-0000-0000-000000000000" xmlns:ns1="clr-namespace:T4FIM.FunctionEvaluator;Assembly=T4FIM.FunctionEvaluator, Version=4.0.0.2, Culture=neutral, PublicKeyToken=1cff8ccc43c5c5ec" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow&quot; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:ns0="clr-namespace:Microsoft.ResourceManagement.Workflow.Activities;Assembly=Microsoft.ResourceManagement, Version=4.1.3508.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">

    <ns1:WorkflowPart x:Name="authenticationGateActivity16" WorkflowEnabled="True" CurrentRequest="{x:Null}" FunctionText="Replace(Right(Left(GUID(),37),36),&quot;-&quot;,&quot;&quot;)" resolveGrammarActivity_GrammarExpression="{x:Null}" ControlTitle="Set GlobalEmployeeID" LogMessage="GlobalEmployeeID" readTarget_Resource="{x:Null}" readReferenceAndAttributes_Resource="{x:Null}" resolveGrammarActivity_ResolvedExpression="{x:Null}" Destination="globalEmployeeID" DestinationType="Target">
        <ns2:ReceiveActivity.WorkflowServiceAttributes xmlns:ns2="clr-namespace:System.Workflow.Activities;Assembly=System.WorkflowServices, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <ns2:WorkflowServiceAttributes Name="Workflow" ConfigurationName="OCG.Workflow" />
        </ns2:ReceiveActivity.WorkflowServiceAttributes>
    </ns1:WorkflowPart>

</ns0:SequentialWorkflow>

XOML Definition for not working WFW

<ns0:SequentialWorkflow ActorId="00000000-0000-0000-0000-000000000000" RequestId="00000000-0000-0000-0000-000000000000" x:Name="SequentialWorkflow" TargetId="00000000-0000-0000-0000-000000000000" WorkflowDefinitionId="00000000-0000-0000-0000-000000000000" xmlns:ns1="clr-namespace:T4FIM.FunctionEvaluator;Assembly=T4FIM.FunctionEvaluator, Version=4.0.0.2, Culture=neutral, PublicKeyToken=1cff8ccc43c5c5ec" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow&quot; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:ns0="clr-namespace:Microsoft.ResourceManagement.Workflow.Activities;Assembly=Microsoft.ResourceManagement, Version=4.1.3613.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
    <ns1:WorkflowPart CurrentRequest="{x:Null}" readTarget_Resource="{x:Null}" Destination="globalEmployeeID" DestinationType="Target" ControlTitle="Set GlobalEmployeeID" FunctionText="Replace(Right(Left(GUID(),37),36),&quot;-&quot;,&quot;&quot;)" WorkflowEnabled="True" resolveGrammarActivity_ResolvedExpression="{x:Null}" readReferenceAndAttributes_Resource="{x:Null}" LogMessage="GlobalEmployeeID" x:Name="authenticationGateActivity1" resolveGrammarActivity_GrammarExpression="{x:Null}">
        <ns2:ReceiveActivity.WorkflowServiceAttributes xmlns:ns2="clr-namespace:System.Workflow.Activities;Assembly=System.WorkflowServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <ns2:WorkflowServiceAttributes ConfigurationName="OCG.Workflow" Name="Workflow" />
        </ns2:ReceiveActivity.WorkflowServiceAttributes>
    </ns1:WorkflowPart>
</ns0:SequentialWorkflow>

The differences are highlighted in yellow and green. The yellow difference is taken care of with redirect bindings in the "Microsoft.ResourceManagement.Service.exe.config" file. Instead of updating every workflow, the redirect binding is updated. So that’s not the problem.

The green difference is rather weird! Why is the working workflow using .NET version 3.5.0.0 and why is the not working working workflow using .NET 4.0.0.0?

After changing the XOML definition of the not working workflow from .NET version 4.0.0.0 to 3.5.0.0 the workflow started working again! Yeah!

After fixing the version, I reconfigured the XOML definition through the Normal View. It failed again. Damn! Looking at the XOML definition it reverted back to 4.0.0.0. WTF! This appeared to happen for every workflow with custom activities. Apparently every time I now edit a workflow through the normal View, I need to recheck the XOML definition through the Advanced View to make sure the .NET version is correctly configured to 3.5.0.0. This just makes me sad, as for sure this is forgotten to be checked and stuff breaks again.

So if you workflow suddenly stops working and throws a similar error this could be the reason!

After changing the .NET version in the XOML definition, committing that, disabling the MPR and re-enabling it, everything worked again!

image

Figure 3: Different Request Statuses While The FIM Service Is Executing The ROPU Enabled Workflow

image

Figure 4: Completed Request Status After The FIM Service Has Executed The ROPU Enabled Workflow

YEAH!

Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
#########
http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————

Posted in Forefront Identity Manager (FIM) Portal, Troubleshooting, Uncategorized, Workflow | 1 Comment »

(2013-10-03) Showing The MPRs A Specific WorkflowDefinition Object Is Being Used In

Posted by Jorge on 2013-10-03


As you know WorkflowDefinitions are only useful within Management Policy Rules (MPRs) and when referenced by SETs. If you want to see if WorkflowDefinitions are being used at all or not, you should have a look at this blog post. In this case we are interested to find out in WHICH MPRs a specific WorkflowDefinition is being used. By default you would need to use the MPR Explorer to find out. You can read more about the MPR Explorer in this blog. Before being able to use the MPR Explorer, you first need to know the name of the WorkflowDefinition. Then you open up the MPR Explorer, specify for what you want to find MPRs (in this case a WorkflowDefinition) and then you define criteria. Finally the results will be shown. Now is it possible to do this in an easier way? YES, it is!

Away silver! Smile

When looking at WorkflowDefinitions, those can be used by MPRs in the following way:

  • Request Based MPRs
    • As an authentication workflow
    • As an authorization workflow
    • As an action workflow
  • Transition Based MPRs
    • As an action workflow

The easiest way to find in which MPRs a specific WorkflowDefinition is being used, is through the GUI with very minimal input. In other words, by adjusting the RCDC of the WorkflowDefinition object. I only paid attention for the RCDC for editing WorkflowDefinitions. I’m showing this in picture 1. For the RCDC (edit mode) of the WorkflowDefinition object I added an additional TAB called “Referencing MPRs”. Within that TAB you will find 3 sections where MPRs can be listed is referencing that specific WorkflowDefinition. For each MPR I also specify if an MPR is disabled or not, and in the case of request based MPRs I also specify if the MPR is a permissions based MPR.

image

Figure 1: Listing The Request Based MPRs And The Transition Based MPRs Which The WorkflowDefinition Can Be Used In

In the picture above you see in which request based MPRs and in which transition based MPRs the WorkflowDefinition is being used.

OK, OK, of course you want to know HOW to do this?! After exporting the RCDC configuration for EDIT mode of WorkflowDefinition objects, you add the XML text below AFTER the “activitiesGrouping” grouping and BEFORE the “Summary” grouping. Save the XML file, and reimport it as a new RCDC configuration for EDIT mode. Either wait at least 15 minutes for the GUI to be refreshed or perform a manual IISRESET on every FIM Portal server.

<my:Grouping my:Name="ReferencingMPRs" my:Caption="Referencing MPRs" my:Enabled="true" my:Visible="true"> <my:Control my:Name="ActivityUsedInRequestMPRs" my:TypeName="UocListView" my:Caption="Activity Used In Request MPRs" my:Description="This Activity Is Used In The Following Request MPRs..."> <my:Properties> <my:Property my:Name="ColumnsToDisplay" my:Value="DisplayName,Disabled,GrantRight"/> <my:Property my:Name="ResultObjectType" my:Value="ManagementPolicyRule"/> <my:Property my:Name="EmptyResultText" my:Value="The Activity Is NOT Used In Any Request MPR..."/> <my:Property my:Name="ListFilter" my:Value="/ManagementPolicyRule[(ManagementPolicyRuleType='Request' and (AuthenticationWorkflowDefinition=/WorkflowDefinition[ObjectID='%ObjectID%'] or AuthorizationWorkflowDefinition=/WorkflowDefinition[ObjectID='%ObjectID%'] or ActionWorkflowDefinition=/WorkflowDefinition[ObjectID='%ObjectID%']))]"/> <my:Property my:Name="PageSize" my:Value="10"/> <my:Property my:Name="ShowTitleBar" my:Value="false"/> <my:Property my:Name="ShowActionBar" my:Value="false"/> <my:Property my:Name="ShowPreview" my:Value="false"/> <my:Property my:Name="ShowSearchControl" my:Value="false"/> <my:Property my:Name="EnableSelection" my:Value="false"/> <my:Property my:Name="SingleSelection" my:Value="false"/> <my:Property my:Name="ItemClickBehavior" my:Value="ModelessDialog"/> <my:Property my:Name="ReadOnly" my:Value="true"/> </my:Properties> </my:Control> <my:Control my:Name="ActivityUsedInTransitionInMPRs" my:TypeName="UocListView" my:Caption="Activity Used In TransitionIN MPRs" my:Description="This Activity Is Used In The Following TransitionIN MPRs..."> <my:Properties> <my:Property my:Name="ColumnsToDisplay" my:Value="DisplayName,Disabled,GrantRight"/> <my:Property my:Name="ResultObjectType" my:Value="ManagementPolicyRule"/> <my:Property my:Name="EmptyResultText" my:Value="The Activity Is NOT Used In Any TransitionIN MPR..."/> <my:Property my:Name="ListFilter" my:Value="/ManagementPolicyRule[(ManagementPolicyRuleType='SetTransition' and ActionType='TransitionIn' and ActionWorkflowDefinition=/WorkflowDefinition[ObjectID='%ObjectID%'])]"/> <my:Property my:Name="PageSize" my:Value="10"/> <my:Property my:Name="ShowTitleBar" my:Value="false"/> <my:Property my:Name="ShowActionBar" my:Value="false"/> <my:Property my:Name="ShowPreview" my:Value="false"/> <my:Property my:Name="ShowSearchControl" my:Value="false"/> <my:Property my:Name="EnableSelection" my:Value="false"/> <my:Property my:Name="SingleSelection" my:Value="false"/> <my:Property my:Name="ItemClickBehavior" my:Value="ModelessDialog"/> <my:Property my:Name="ReadOnly" my:Value="true"/> </my:Properties> </my:Control> <my:Control my:Name="ActivityUsedInTransitionOutMPRs" my:TypeName="UocListView" my:Caption="Activity Used In TransitionOUT MPRs" my:Description="This Activity Is Used In The Following TransitionOUT MPRs..."> <my:Properties> <my:Property my:Name="ColumnsToDisplay" my:Value="DisplayName,Disabled,GrantRight"/> <my:Property my:Name="ResultObjectType" my:Value="ManagementPolicyRule"/> <my:Property my:Name="EmptyResultText" my:Value="The Activity Is NOT Used In Any TransitionOUT MPR..."/> <my:Property my:Name="ListFilter" my:Value="/ManagementPolicyRule[(ManagementPolicyRuleType='SetTransition' and ActionType='TransitionOut' and ActionWorkflowDefinition=/WorkflowDefinition[ObjectID='%ObjectID%'])]"/> <my:Property my:Name="PageSize" my:Value="10"/> <my:Property my:Name="ShowTitleBar" my:Value="false"/> <my:Property my:Name="ShowActionBar" my:Value="false"/> <my:Property my:Name="ShowPreview" my:Value="false"/> <my:Property my:Name="ShowSearchControl" my:Value="false"/> <my:Property my:Name="EnableSelection" my:Value="false"/> <my:Property my:Name="SingleSelection" my:Value="false"/> <my:Property my:Name="ItemClickBehavior" my:Value="ModelessDialog"/> <my:Property my:Name="ReadOnly" my:Value="true"/> </my:Properties> </my:Control> </my:Grouping>

Et voila!

For other scenarios, see:

Cheers,

Jorge

———————————————————————————————

* This posting is provided "AS IS" with no warranties and confers no rights!

* Always evaluate/test yourself before using/implementing this!

* DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/

———————————————————————————————

############### Jorge’s Quest For Knowledge #############

######### http://JorgeQuestForKnowledge.wordpress.com/ ########

———————————————————————————————

Posted in Forefront Identity Manager (FIM) Portal, MPR, RCDC, Workflow | 4 Comments »

(2013-02-08) Unused SETs, Unused Workflows, Unused Mail Templates – Keeping FIM Portal Clean From Unused Configuration Objects

Posted by Jorge on 2013-02-08


As soon as you have installed FIM you start configuring it according to your application design, which is based upon the data model and the usage scenarios. In case of the FIM Portal you configure it with configuration objects (MPRs, SETs, Workflows, Mail Templates, etc.) that in the end will be the technical components that give you the desired logic to do whatever you need it to do. At least I hope so! Smile

During the usage of the FIM Portal, stuff changes because requirements change and logic change. Because of that objects are added and changed to accommodate the new requirements and therefore the required logic. BUT….. where’s the part about deleting unused objects, in other words CLEAN UP! By default there is nothing in FIM that will tell you if objects are not used. Is it impossible to get that information? No, but you need to do it yourself! I want to keep my FIM Portal configuration clean, therefore I have created the following PowerShell script to help me with that. And I do hope it helps you too!

# Jorge de Almeida Pinto [MVP-DS] # https://jorgequestforknowledge.wordpress.com/ # # +++ Finding UnUsed Objects In The FIM Portal +++ Param ( [string] $URI = "http://localhost:5725/resourcemanagementservice", [parameter(Mandatory=$true)] [string] $objectType ) # Clear The Screen Clear-Host # Import The FIM 2010 (R2) Snap-In If Available $SnapIn = "FIMAutomation" If(@(Get-PSSnapin | Where-Object {$_.Name -eq $SnapIn} ).count -eq 0) { If(@(Get-PSSnapin -Registered | Where-Object {$_.Name -eq $SnapIn} ).count -ne 0) { Add-PSSnapin $SnapIn Write-Host "" Write-Host "Snap-In '$SnapIn' Has Been Loaded..." -ForeGroundColor Green Write-Host "Continuing Script..." -ForeGroundColor Green Write-Host "" } Else { Write-Host "" Write-Host "Snap-In '$SnapIn' Is NOT Available To Load..." -ForeGroundColor Red Write-Host "Aborting Script..." -ForeGroundColor Red Write-Host "" Exit } } Else { Write-Host "" Write-Host "Snap-In '$SnapIn' Has Already Been Loaded..." -ForeGroundColor Green Write-Host "Continuing Script..." -ForeGroundColor Green Write-Host "" } # Convert a FIM ExportObject to a PowerShell PSObject # http://www.identitytrench.com/2011/07/convert-fim-exportobject-to-powershell.html Function Convert-FimExportToPSObject { Param ( [parameter(Mandatory=$true, ValueFromPipeline = $true)] [Microsoft.ResourceManagement.Automation.ObjectModel.ExportObject] $ExportObject ) Process { $psObject = New-Object PSObject $ExportObject.ResourceManagementObject.ResourceManagementAttributes | ForEach-Object { if ($_.Value -ne $null) { $value = $_.Value } elseif($_.Values -ne $null) { $value = $_.Values } else { $value = $null } $psObject | Add-Member -MemberType NoteProperty -Name $_.AttributeName -Value $value } Write-Output $psObject } } # Current Folder $currentFolder = (Get-Location).Path # Searching For Unused SETs # SETs Can Be Used In: # * MPRs # * Referenced By Other SETs # * Referenced By Search Scopes # * Referenced By RCDCs If ($objectType.ToUpper() -eq "SET") { Write-Host "" Write-Host "+++ CHECKING USAGE OF SETS +++" -ForeGroundColor Cyan Write-Host "" # Files $listOfSETsUsed = "List-Of-Sets-Used.txt" $listOfSETsUnUsed = "List-Of-Sets-UnUsed.txt" # Check Current Files If (Test-Path $($currentFolder + "\" + $listOfSETsUsed)) { Remove-Item $($currentFolder + "\" + $listOfSETsUsed) -Force } If (Test-Path $($currentFolder + "\" + $listOfSETsUnUsed)) { Remove-Item $($currentFolder + "\" + $listOfSETsUnUsed) -Force } # Get All The SETs $SETsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/Set" $SETsInFIMPSObject = $SETsInFIM | Convert-FimExportToPSObject # Get All The MPRs $MPRsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/ManagementPolicyRule" $MPRsInFIMPSObject = $MPRsInFIM | Convert-FimExportToPSObject # Get All The SearchScopes $SearchScopesInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/SearchScopeConfiguration" $SearchScopesInFIMPSObject = $SearchScopesInFIM | Convert-FimExportToPSObject # Get All The RCDCs $RCDCsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/ObjectVisualizationConfiguration" $RCDCsInFIMPSObject = $RCDCsInFIM | Convert-FimExportToPSObject # For Each SET Check If It Is Used Somewhere ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { $setDisplayName = $SETInFIMPSObject.DisplayName $setObjectID = $SETInFIMPSObject.ObjectID $setIsUsed = $false # For Each SET Check If It Is Used In Some MPR If (!$setIsUsed) { ForEach ($MPRInFIMPSObject In $MPRsInFIMPSObject) { If ($MPRInFIMPSObject.PrincipalSet -eq $setObjectID -Or $MPRInFIMPSObject.ResourceCurrentSet -eq $setObjectID -Or $MPRInFIMPSObject.ResourceFinalSet -eq $setObjectID) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # For Each SET Check If It Is Used In Some Other SET If (!$setIsUsed) { ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { If ($SETInFIMPSObject.Filter -match $($setObjectID.TrimStart("urn:uuid:")) -Or $SETInFIMPSObject.Filter -match $setDisplayName) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # For Each SET Check If It Is Used In Some Workflow If (!$setIsUsed) { ForEach ($SearchScopeInFIMPSObject In $SearchScopesInFIMPSObject) { If ($SearchScopeInFIMPSObject.SearchScope -match $($setObjectID.TrimStart("urn:uuid:")) -Or $SearchScopeInFIMPSObject.SearchScope -match $setDisplayName) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # For Each SET Check If It Is Used In Some RCDC If (!$setIsUsed) { ForEach ($RCDCInFIMPSObject In $RCDCsInFIMPSObject) { If ($RCDCInFIMPSObject.ConfigurationData -match $($setObjectID.TrimStart("urn:uuid:")) -Or $RCDCInFIMPSObject.ConfigurationData -match $setDisplayName) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # If The SET Is Used If ($setIsUsed) { Write-Host "In Use: '$setDisplayName'..." -ForeGroundColor Green Add-Content $($currentFolder + "\" + $listOfSETsUsed) $setDisplayName } # If The SET Is UnUsed If (!$setIsUsed) { Write-Host "Not In Use: '$setDisplayName'..." -ForeGroundColor Red Add-Content $($currentFolder + "\" + $listOfSETsUnUsed) $setDisplayName } } } # Searching For Unused WorkFlows # WorkFlows Can Be Used In: # * MPRs # * Referenced By SETs If ($objectType.ToUpper() -eq "Workflow") { Write-Host "" Write-Host "+++ CHECKING USAGE OF WORKFLOWS +++" -ForeGroundColor Cyan Write-Host "" # Files $listOfWorkflowsUsed = "List-Of-Workflows-Used.txt" $listOfWorkflowsUnUsed = "List-Of-Workflows-UnUsed.txt" # Check Current Files If (Test-Path $($currentFolder + "\" + $listOfWorkflowsUsed)) { Remove-Item $($currentFolder + "\" + $listOfWorkflowsUsed) -Force } If (Test-Path $($currentFolder + "\" + $listOfWorkflowsUnUsed)) { Remove-Item $($currentFolder + "\" + $listOfWorkflowsUnUsed) -Force } # Get All The Workflows $WorkflowsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/WorkflowDefinition" $WorkflowsInFIMPSObject = $WorkflowsInFIM | Convert-FimExportToPSObject # Get All The MPRs $MPRsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/ManagementPolicyRule" $MPRsInFIMPSObject = $MPRsInFIM | Convert-FimExportToPSObject # Get All The SETs $SETsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/Set" $SETsInFIMPSObject = $SETsInFIM | Convert-FimExportToPSObject # For Each Workflow Check If It Is Used Somewhere ForEach ($WorkflowInFIMPSObject In $WorkflowsInFIMPSObject) { $workflowDisplayName = $WorkflowInFIMPSObject.DisplayName $workflowObjectID = $WorkflowInFIMPSObject.ObjectID $workflowIsUsed = $false # For Each Workflow Check If It Is Used In Some MPR If (!$workflowIsUsed) { ForEach ($MPRInFIMPSObject In $MPRsInFIMPSObject) { If ($MPRInFIMPSObject.ActionWorkflowDefinition -contains $WorkflowObjectID -Or $MPRInFIMPSObject.AuthenticationWorkflowDefinition -contains $setObjectID -Or $MPRInFIMPSObject.AuthorizationWorkflowDefinition -contains $WorkflowObjectID) { # Object Is Used $workflowIsUsed = $true Break } Else { # Object Is NOT Used $workflowIsUsed = $false } } } # For Each Workflow Check If It Is Used In Some SET If (!$workflowIsUsed) { ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { If ($SETInFIMPSObject.Filter -match $($workflowObjectID.TrimStart("urn:uuid:")) -Or $SETInFIMPSObject.Filter -match $workflowDisplayName) { # Object Is Used $workflowIsUsed = $true Break } Else { # Object Is NOT Used $workflowIsUsed = $false } } } # If The Workflow Is Used If ($workflowIsUsed) { Write-Host "In Use: '$workflowDisplayName'..." -ForeGroundColor Green Add-Content $($currentFolder + "\" + $listOfWorkflowsUsed) $workflowDisplayName } # If The Workflow Is UnUsed If (!$workflowIsUsed) { Write-Host "Not In Use: '$workflowDisplayName'..." -ForeGroundColor Red Add-Content $($currentFolder + "\" + $listOfWorkflowsUnUsed) $workflowDisplayName } } } # Searching For Unused Mail Templates # Mail Templates Can Be Used In: # * Workflows # * Referenced By SETs If ($objectType.ToUpper() -eq "MailTemplate") { Write-Host "" Write-Host "+++ CHECKING USAGE OF MAIL TEMPLATES +++" -ForeGroundColor Cyan Write-Host "" # Files $listOfMailTemplatesUsed = "List-Of-MailTemplates-Used.txt" $listOfMailTemplatesUnUsed = "List-Of-MailTemplates-UnUsed.txt" # Check Current Files If (Test-Path $($currentFolder + "\" + $listOfMailTemplatesUsed)) { Remove-Item $($currentFolder + "\" + $listOfMailTemplatesUsed) -Force } If (Test-Path $($currentFolder + "\" + $listOfMailTemplatesUnUsed)) { Remove-Item $($currentFolder + "\" + $listOfMailTemplatesUnUsed) -Force } # Get All The Mail Templates $MailTemplatesInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/EmailTemplate" $MailTemplatesInFIMPSObject = $MailTemplatesInFIM | Convert-FimExportToPSObject # Get All The Workflows $WorkflowsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/WorkflowDefinition" $WorkflowsInFIMPSObject = $WorkflowsInFIM | Convert-FimExportToPSObject # Get All The SETs $SETsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/Set" $SETsInFIMPSObject = $SETsInFIM | Convert-FimExportToPSObject # For Each Mail Template Check If It Is Used Somewhere ForEach ($MailTemplateInFIMPSObject In $MailTemplatesInFIMPSObject) { $mailTemplateDisplayName = $MailTemplateInFIMPSObject.DisplayName $mailTemplateObjectID = $MailTemplateInFIMPSObject.ObjectID $mailTemplateIsUsed = $false # For Each Mail Template Check If It Is Used In Some Workflow If (!$mailTemplateIsUsed) { ForEach ($WorkflowInFIMPSObject In $WorkflowsInFIMPSObject) { If ($WorkflowInFIMPSObject.XOML -match $($mailTemplateObjectID.TrimStart("urn:uuid:"))) { # Object Is Used $mailTemplateIsUsed = $true Break } Else { # Object Is NOT Used $mailTemplateIsUsed = $false } } } # For Each Mail Template Check If It Is Used In Some SET If (!$mailTemplateIsUsed) { ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { If ($SETInFIMPSObject.Filter -match $($mailTemplateObjectID.TrimStart("urn:uuid:")) -Or $SETInFIMPSObject.Filter -match $mailTemplateDisplayName) { # Object Is Used $mailTemplateIsUsed = $true Break } Else { # Object Is NOT Used $mailTemplateIsUsed = $false } } } # If The Mail Template Is Used If ($mailTemplateIsUsed) { Write-Host "In Use: '$mailTemplateDisplayName'..." -ForeGroundColor Green Add-Content $($currentFolder + "\" + $listOfMailTemplatesUsed) $mailTemplateDisplayName } # If The Mail Template Is UnUsed If (!$mailTemplateIsUsed) { Write-Host "Not In Use: '$mailTemplateDisplayName'..." -ForeGroundColor Red Add-Content $($currentFolder + "\" + $listOfMailTemplatesUnUsed) $mailTemplateDisplayName } } }

The script supports the check for SET, Workflow and Mail Template objects. The script accepts two parameters, being -URI and -objectType. -URI is only mandatory if you are not running the script on the server with the FIM service. -objectType is always mandatory and accepts the values SET, Workflow or MailTemplate.

To find used and unused SETs, execute the following:

.\Finding-Unused-Objects-In-FIM-Portal.ps1 -objectType SET

The output can be seen below.

SNAGHTML352f4120

Figure 1: Finding Used And Unused SETS

To find used and unused Workflows, execute the following:

.\Finding-Unused-Objects-In-FIM-Portal.ps1 -objectType Workflow

The output can be seen below.

SNAGHTML353e7621

Figure 2: Finding Used And Unused Workflows

To find used and unused Mail Templates, execute the following:

.\Finding-Unused-Objects-In-FIM-Portal.ps1 -objectType MailTemplate

The output can be seen below.

SNAGHTML353f3aba

Figure 3: Finding Used And Unused Mail Templates

In addition to the output on screen, the script will also provide the output to a text file. For each object type 2 files are created when applicable. One file contains the objects used and the other file contains the unused objects.

SNAGHTML353e2b9b

Figure 4: Text Files Listing The Used And Unused Objects

Now, the script does NOT delete anything! It just enumerates the information and presents it to you. It is now up to you to delete an object or not based upon the information presented to you. As a suggestion, I would never delete an object that by default is in the FIM Portal.

Cheers,

Jorge

———————————————————————————————

* This posting is provided "AS IS" with no warranties and confers no rights!

* Always evaluate/test yourself before using/implementing this!

* DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/

———————————————————————————————

############### Jorge’s Quest For Knowledge #############

######### http://JorgeQuestForKnowledge.wordpress.com/ ########

———————————————————————————————

Posted in Forefront Identity Manager (FIM) Portal, Mail Template, SET, Workflow | 3 Comments »