PowerShell Activity for FIM

September 4, 2010 at 8:31 AMHenrik Nilsson

Carol(MissMiis) has created a really nice activity for executing PowerShell scripts, both local and remote and it opens up for all kinds of possibilities! Check it out!

http://www.wapshere.com/missmiis/powershell-activity

Posted in: Forefront Identity Manager | Identity Management | Workflow

Tags: , ,

EnumerateResourcesActivity - the follow-up

November 16, 2009 at 10:13 PMHenrik Nilsson

A couple of months ago Joe Zamora (the CShark) was trying to solve the mysteries around the EnumerateResourcesActivity, a great activity that you could use from your own custom activities/workflows but not from the FIM workflow designer, read Joe’s post here. After a lot of work, some help from Nima in the product team and a couple of not that useful tips from me Joe got it working. See the forum post where me and Joe was trying to accomplish this here.

The EnumerateResourcesActivity is the only activity that could search for and return resources in FIM and it does so simply by you giving it an XPath query. It’s a really nice activity except it’s got limitations in that it can only contain a single child activity (actually not strange at all, the same goes for the ReplicatorActivity) and it has a got a designer that doesn’t allow for adding the child activity declaratively so you’re forced to add the single child using code. The EnumerateResourcesActivity work pretty much as the ReplicatorActivity in that it iterates bunch of values only in the case of the EnumerateResourcesActivity it finds the values (resources) before iterating them. An important aspect of workflow crafting is that an activity can’t be executed twice and that is handled by the EnumerateResourcesActivity by creating duplicates of the child activity objects (and descendant objects of the child activity) for each iteration before the iteration is started therefore you can’t use the original activity object references for getting activities within the iterations.

Joe used a CodeActivity as the single child but the solution I’m going to show you will use a SequenceActivity instead making it possible to add more than one single activity because you will probably want to do work suited for other activities like add a user to the group you have found or something like that.

I won’t go through all the stuff around activity crafting, for this you’ll have to turn to the Windows Workflow Foundation developer center , the Forefront Identity Manager 2010 Developer Reference or maybe the oracle scrapheap's named Google and Bing. First of all we need some code in the designer part of our custom Activity class (A custom activity is usually created from two partial classes when you create it in Visual Studio). In the InitializeComponent method I create a EnumerateResourcesActivity, add a SequenceActivity to it and to the SequenceActivity I add a CodeActivity but I leave for you to create more child activities to the SequenceActivity after the CodeActivity. Finally I add the EnumerateResourcesActivity to the custom activity I’m currently creating:

private void InitializeComponent()
{
    this.CanModifyActivities = true;

    // codeActivity
    this.codeActivity = new CodeActivity();
    this.codeActivity.ExecuteCode += new System.EventHandler(this.codeActivity_ExecuteCode);

    // sequenceActivity
    this.sequenceActivity = new SequenceActivity();
    this.sequenceActivity.Activities.Add(this.codeActivity);

    // enumResourcesActivity 
    this.enumResourcesActivity = new Microsoft.ResourceManagement.Workflow.Activities.EnumerateResourcesActivity();
    this.enumResourcesActivity.PageSize = 100;
    this.enumResourcesActivity.XPathFilter = "/Person";
    this.enumResourcesActivity.Activities.Add(this.sequenceActivity);
            
    // MyCustomActivity
    this.Activities.Add(this.enumResourcesActivity);
    this.Name = "MyCustomActivity";

    this.CanModifyActivities = false;
}

Did you notice the XPathFilter property of the EnumerateResourcesActivity that I’ve set to return all person objects? You might think it’s strange that I add a CodeActivity as the only child of the SequenceActivity but I use this for getting the resource for the current iteration and it also gives a method that you could use for assigning values to siblings further down the execution chain from the CodeActivity that I leave up to you to add.

Here’s how I extract the value from the EnumerateResourcesActivity:

void codeActivity_ExecuteCode(object sender, EventArgs e)
{
    SequenceActivity s = (SequenceActivity)((CodeActivity)sender).Parent;
    ResourceType resource = EnumerateResourcesActivity.GetCurrentIterationItem(s) as ResourceType;

    // Perform initialization of any sibling activities here but remember you must reference
// them as I’ve done above with the SequenceActivity
// and a good way of doing it could be for example...
// UpdateResourceActivity u = s.Activities.OfType<UpdateResourceActivity>().First();
// or other generic “queries”.
}

First of all we need to get the SequenceActivity of the current iteration and since we know it’s the parent of the CodeActivity we could get the Parent property object of the current CodeActivity object instance that we’ve got from the sender parameter. Then we call the static GetCurrentIterationItem method passing in the SequenceActivity object instance and this should return the resource for the current iteration.

Next I leave up to you to use the values of the found resources to do whatever you wish and that could be for example update the resources found, delete the resources found or maybe create new resources from whatever values the found resources contain.

Posted in: Forefront Identity Manager | Identity Management | Workflow

Tags: , ,

Using the Normalize Diacritic Characters Activity

May 11, 2009 at 10:13 AMHenrik Nilsson

I got a comment from Joe Stepongzi today and he didn’t like my Normalize Diacritic Characters Activity that is a part of my Cortego ILM 2 Workflow Activity Library:

I am not sure I like the Normalize Diacritic Characters Activity..
As certain values could be changed to multiple characters instead of one..
I think email addresses should be done at the source and not handled in ILM "2"

The use of the Normalize Diacritic Characters Activity is to normalize characters with different kinds of diacritics into pure characters or how I should define it? The main reason I've created this activity is that I'm from Sweden and must handle "ÅÄÖ" but I'm also working for a company that has a lot of employees in the eastern European countries and that is a nightmare when trying to create for example email addresses. This could be hard to understand for Britain’s and Americans since English is a language where diacritics are sparsely used and this wouldn't have been a problem if the Americans would have understood from the beginning there are other languages than English and a need for other standards than ASCII. Here are a couple of examples of what could be accomplished (I do hope your browser supports Unicode otherwise you'll probably see a lot of boxes):

As you see the activity is only normalizing diacritics by removing any Unicode spacing marks and this is how it works code wise using the System.Globalization namespace for normalization of diacritics:


public static string NormalizeDiacriticChars(string input)
{
   string formD = input.Normalize(NormalizationForm.FormD);
   StringBuilder sb = new StringBuilder();
   for (int i = 0; i < formD.Length; i++)
   {
      UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(formD[i]);
      if (uc != UnicodeCategory.NonSpacingMark)
      {
         sb.Append(formD[i]);
      }
   }
   return (sb.ToString().Normalize(NormalizationForm.FormC));
}

First of all the input string is normalized into Form D that decomposes characters in this way:

  • å –> aRing
  • Ё –> E + Umlaut
  • æ –> a + e (Used in Danish, Norwegian and old English more)
  • –>  ++ (Hangul letter used in Korea)

Then all characters defined as Unicode spacing marks are removed and in the example above the ring and the dots (umlaut) are removed. Finally the remaining string is normalized into Form C, composing characters back, for example:

  • a -> a (The ring is already removed)
  • E -> E (The umlaut is already removed)
  • a + e –> æ (Note: if the original input would have been “ae” it would not become “æ”)
  • + + –>

Normalizing a eastern European name like "Lāčkāja Lapiņš" would end up as "Lackaja Lapins" and a typical Swedish name like "Åsa Öberg" would end up as "Asa Oberg", a lot easier to handle for creating different kind of names and also widely accepted in the countries where diacritic characters are used.

As you can see, characters are not as Joe thought changed into multiple characters but he do have a point in that for example email addresses should be handled at the source and not in ILM2/FIM2010... But if you would like accounts and mailboxes to be automatically created from for example an HR system, one of the best practices of Identity Management... You might be forced to create the email addresses and other system names following your naming standards unless you trust your HR personnel having full control over all existing email addresses and names. It’s up to you to make sure input characters are valid but by using this activity you don’t have to worry about macrons, curls, dots, accents and so on but as you can see the  and æ characters is not changed or removed so they would still a be problem when creating email addresses.

A solution to make sure you get valid strings after normalization could be to use my Regex Replace Activity to remove or replace any remaining characters that isn’t valid in the context you’re using it. In order to get unique names or email addresses you could use my Unique Name Activity. Both these activities is contained in the Cortego ILM 2 Workflow Activity Library. The pattern "[^a-zA-Z0-9\s]" could be used in the Regex Replace Activity to find and remove or replace all characters that is not within a-z, A-Z, 0-9 and whitespace characters.  

If you would like to know more about Unicode Normalization this is a great guide: Unicode Normalization Forms. If you would like to know how different characters from different scripts including Cyrillic, Greek, Latin, Thai, Katakana, and so on are composed/decomposed you could have a look at these Normalization Charts. A description of different kinds of diacritics could be found at Diacritic - Wikipedia.

Finally, do you trust your HR personnel or do you have a Catbert at your company? Laughing

Posted in: Workflow | Forefront Identity Manager

Tags: , , , , ,

Cool feature using the RegexReplaceActivity

April 30, 2009 at 1:28 PMHenrik Nilsson

The RegexReplaceActivity that is introduced in the Cortego ILM 2 Workflow Activity Library is using the Regex class of System.Text.RegularExpressions namespace and by using the Replacement parameter of the Replace function we could actually do some real cool stuff. The Replacement parameter of the Replace function is translated into the Replacement property of the RegexReplaceActivity and there is no requirement the Replacement parameter must contain a plain text, it could in fact contain a replacement pattern as well and here is an example taken from the MSDN - Regular Expressions Examples used to change the format of dates. Please notice it's just an example, you're the one that must know how actual values are formatted and I don't know if using the EmployeeEndDate attribute with this example is appropriate.

Replace dates of the form mm/dd/yy with dates of the form dd-mm-yy.

Input value (from Expression): 04/30/09 or 04/30/2009 (there's a 2 to 4 characters quantifier for year in the Regex Pattern)
RegEx Pattern: \b(?<month>\d{1,2})/(?<day>\d{1,2})/(?<year>\d{2,4})\b
Replacement: ${day}-${month}-${year} 

Regex Replace MDYToDMY  

Output value (Destination expression): 30-04-09 or 30-04-2009 – isn’t that cooljQuery15207980085869857615_1318365216111?
What happens is that the input data is captured into variables that are then used to format a new value.

Realize what you could do with this, you could in fact simply extract parts from or format input data to what ever you like!
A good source for more info about regular Expressions is .NET Framework Regular Expressions.

Posted in: Forefront Identity Manager | Workflow

Tags: , , ,

How to use EnumerateResourcesActivity in RC0

April 29, 2009 at 6:56 AMHenrik Nilsson

I have been working with Joe Zamora by mail contact and this forum thread to try and find out how the EnumerateResourcesActivity that comes with ILM2 RC0 work and yesterday Joe managed to get it working with some additional help from Nima in the product team.

It is really great we have got some info about this activity and now know how it works since it could be used to find resources within ILM from workflows without having to use the WS client. My first use of this will be to extend my UniqueName Activity to be able to search the ILM DB for free names.

Here's Joe's blog post about it, check it out!!!
How to use EnumerateResourcesActivity in RC0

Posted in: Workflow | Forefront Identity Manager

Tags: , ,

Reverse shout out to Ensynch!

April 18, 2009 at 8:41 AMHenrik Nilsson

The Ensynch guys have posted their activity library and their branding definitely beats mine except they don't have a Cortego logo :-).
They've published the source code as well and I recommend everyone to have a look at it!

http://c--shark.blogspot.com/2009/04/source-code-posted.html

Posted in: Workflow | Forefront Identity Manager

Tags: ,

Cortego ILM 2 Workflow Activity Library

April 8, 2009 at 4:19 PMHenrik Nilsson

After a lot of work I’m confident these workflow activities work pretty satisfying therefore I’ve decided to release them to the public but without any guarantees. I wish to send my thanks to Brad Turner and the others at Ensynch that made the great walkthrough in making custom ILM2 activities - http://www.codeplex.com/ILM2WFActivity and to Mark Gabarra that made a video on the subject before he left Microsoft (sad!) - display-name-generation-activity-a-custom-ilm2-action-activity.

The Expression and Destination fields are common for almost all activities except the password generator activity that only have a destination and the Unique name activity that takes more than one expression that are evaluated one at a time. The expression field can take more than one input value and even string values so for example “[//Target/LastName], [//Target/FirstName]” is ok. The destination field only takes a single output of either the “[//WorkflowData/…]” or “[//Target/…]” types.

Update Value Activity

This is the simplest activity in the library, it takes any input and writes it to either the WorkflowDictionary - [//WorkflowData/…] or to a target attribute – [//Target/…]. The main usage for this activity is to write a value created by the Function activity that in RC0 only have the workflow dictionary as working destination.

UpdateValueActivity

Activity information configuration

Display Name Cortego Update Value Activity
Description Updates a Target value from an Expression
Activity Name Cortego.ILM.Workflow.Activities.UpdateValueActivity
Assembly Name Cortego.ILM.Workflow.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b88d7150cfc8f36b
Authentication, Action, Authorization Your choice.
Type Name Cortego.ILM.Workflow.Activities.UpdateValueActivitySettingsPart

Normalize Diacritic Characters Activity

This activity is almost the same as the Update Value Activity except it normalizes diacritic characters, for example ÄÖÅÜčȭ becomes AOAUco and this very useful for writing email addresses that can’t contain diacritics. Read more about diacritic characters at http://en.wikipedia.org/wiki/Diacritic.

NormalizeDiacritics

Activity information configuration

Display Name Cortego Normalize Diacritic Characters Activity
Description Normalizes Diacritic Characters like ÅÄÖ to AAO.
Activity Name Cortego.ILM.Workflow.Activities.NormalizeDiacriticCharactersActivity
Assembly Name Cortego.ILM.Workflow.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b88d7150cfc8f36b
Authentication, Action, Authorization Your choice.
Type Name Cortego.ILM.Workflow.Activities.NormalizeDiacriticCharactersActivitySettingsPart

Regex Replace Activity

This is almost the same as the Update Value Activity as well except it takes a Regular Expression Pattern and an optional replacement value that could be used for removing or replacing invalid characters from attribute values. A good example of this is the Active Directory sAMAccountName attribute that doesn’t support /\[]:;|=,+*?<>@ the regular expression for this would be… “[/:;\|=,\+\*\?<>@\[\]\\]”. If you’re not familiar with Regular Expressions, have a look at http://msdn.microsoft.com/en-us/library/hs600312(VS.71).aspx. The replacement value is used if you wish to replace characters with something else but just leave it empty for removing characters.

RegexreplaceActivity

Activity information configuration

Display Name Cortego Regex Replace Activity
Description Uses a Regular Expression to do string replacements.
Activity Name Cortego.ILM.Workflow.Activities.RegexReplaceActivity
Assembly Name Cortego.ILM.Workflow.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b88d7150cfc8f36b
Authentication, Action, Authorization Your choice.
Type Name Cortego.ILM.Workflow.Activities.RegexReplaceActivitySettingsPart

Generate Password Activity

This activity generates a strong password with at least one character from each category, upper case characters (A-Z), lower case characters (a-z), numeric characters (0-9) and special characters (!#%&/()=?-:;><@$,._*). It’s recommended that password values are written to a custom target attribute (hidden from UI) instead of directly with an outbound sync rule since the password in that case will end up fully readable in the Expected Rules Entry. Remember that passwords generated with this activity is hard to remember and only suitable as temporary passwords before the users can set it’s own, we don’t want to end up with passwords on paper notes under the keyboard.

GeneratePasswordActivity

Activity information configuration

Display Name Cortego Password Generator Activity
Description Generates strong passwords.
Activity Name Cortego.ILM.Workflow.Activities.PasswordGeneratorActivity
Assembly Name Cortego.ILM.Workflow.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b88d7150cfc8f36b
Authentication, Action, Authorization Your choice.
Type Name Cortego.ILM.Workflow.Activities.PasswordGeneratorActivitySettingsPart

Unique Name Activity

This is the most advanced activity in the library, it works almost the same as the Update Value Activity but there are two main differences, it takes any number of input expressions and the expressions are evaluated against an LDAP catalog from top to bottom and as soon as a unique value is found it’s written to the destination. It currently doesn’t support LDAPS and it has only been tested against Active Directory.

UniqueNameActivity

Activity information configuration

Display Name Cortego Unique Name Activity
Description Generates or takes value before it’s checked for uniqueness against LDAP catalog.
Activity Name Cortego.ILM.Workflow.Activities.UniqueNameActivity
Assembly Name Cortego.ILM.Workflow.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b88d7150cfc8f36b
Authentication, Action, Authorization Your choice.
Type Name Cortego.ILM.Workflow.Activities.UniqueNameActivitySettingsPart

As you can see from my previous blog post I’ve removed the normalize diacritics and regex remove functionality and put those functions as separate activities and it’s easy to chain activities, just write your output value (destination) from any activity including the Function activity that comes with ILM2 to the workflow dictionary and use that value as input (expression) value in the next activity.

LDAP Search Activity

This activity doesn’t have any user interface so it can’t be used directly within ILM2 but it’s included in the Unique Name activity. The reason I’ve chosen not to add a UI for it is because it returns a nested dictionary (Dictionary<string, Dictionary<string, object>>) that could be hard to use from other activities but you could of course use it in your own custom activities or workflows.

Summing up

You may freely use the activities and the code in any way but if you use the code without major changes I want you to keep the comment in top of each code file that references my blog and my company. It would also be nice if you could give me some feedback, report any problems and tell me about other cool features that could be useful within the library. Please drop a message if you wish be noticed when changes or additions are made to the library and I already have an interesting activity that will show up within the library soon.

In order to use the code you’ll have to strong name the assembly using your own key before putting it into the GAC and if you aren’t sure how to do that and how to deploy, have a look at the very good document Brad Turner and the other guys at Ensynch published, see link in the beginning of this post.

Download Cortego ILM2 Workflow Activity Library Here

Posted in: Forefront Identity Manager | Workflow

Tags: , , , , ,

ILM2 Unique Name Workflow Activity

March 31, 2009 at 2:29 PMHenrik Nilsson

I’m currently working with ILM2 for a customer and realized there was no way to ensure usernames are unique except by writing a custom workflow activity, my first except for the LDAP search activity that resides in the same library and is used by the unique name activity. It has been a struggle to complete this because of enormous problems with the Workflow Designer in VS2008 so I decided to go ahead write a code only activity. It turns out the problem with an evil MessageBox within the designer that showed up until I killed the VS2008 task was because I had set the DesignerSerializationVisibility attribute to DesignerSerializationVisibility.Content instead of DesignerSerializationVisibility.Visible.

Writing an activity for ILM2 isn’t rocket science, you first decide what information it needs and create Dependency properties and bind these to usual properties, you create a web UI with whatever logic it needs and finally you write the activity that does the work.

This is how it looks…

UniqueNameActivity

So what is is good for then…
Looking at the picture you see that it first take an ILM Target attribute, this is for example “AccountName” and this is where the first found unique value will be written.

The Expression Evaluator makes it possible to a number of different values to be evaluated from top to bottom, if the first attribute value shows up to already be existing in the target LDAP catalog the next one is tested for. After a little peeking inside the ILM2 assemblies I managed to find out how to add the lookup button that when pressed shows up this familiar dialog…

image  

The control is named ProcessParameterPicker and could easily be added to your activity UI by calling base.DesignerHostProvider.CreateParameterPickerControl() and then give it a TextBox object to write to.

The Remove Characters checkbox and the Remove Characters Regex Textbox allows you to remove special characters that might sneak into the source values, for example the sAMAccountName attribute doesn’t allow characters like /\@+*? and so on. Just check the checkbox and add a regular expression for finding the invalid characters and they are trimmed away before the evaluation is made.
The sAMAccountName attribute is also a little bit picky about the length that can’t exceed 20 characters but how to sort that out is up to you.

The Normalize Diacritics checkbox is especially useful in countries like Sweden where I live and where non ASCII characters like ÅÄÖ needs to be normalized before used in for example email addresses.

Then there are a bunch of LDAP attributes that are used to make up the search for the attribute value within a catalog…

  • LDAP Search Root – Where in the catalog you wish to begin you search.
  • LDAP Object Class – If you wish to filter your search to a special object type (currently only supports a single object class).
  • LDAP Target Attribute – The attribute you wish to check for uniqueness.
  • LDAP Server – Self explaining.
  • LDAP Server Port – Self explaining, 389 by default and currently there is no support for LDAPS.
  • LDAP User Name – Self explaining.
  • LDAP Password – Self explaining.
  • Last but not least a button that enables you to try LDAP connectivity.

I’ll publish the library with source code as soon as I been able to test it more but if you would like to help me test it out send me a mail from the contact page and I’ll send it to you.

Posted in: Forefront Identity Manager | Identity Management | Workflow

Tags: , , ,