Saturday, March 31, 2012

FIM PCNS And A Lack of Trust

If you read through the FIM documentation for setting up PCNS, you will find that either FIM and PCNS need to be in the same forest or be part of a forest trust. From http://technet.microsoft.com/en-us/library/cc720594(v=ws.10).aspx:

 

Forest trusts are only required if PCNS and ILM 2007 are located in different forests. If this is the case, a forest-level trust must be established. This is required for Kerberos mutual authentication for the ILM 2007 server to accept the request from a remote forest host.

This can become extremely limiting, especially if both forests do not have the proper forest and domain levels.  Theoretically, however, it’s possible to make Kerberos work over an External Trust (http://blogs.technet.com/b/activedirectoryua/archive/2010/08/04/conditions-for-kerberos-to-be-used-over-an-external-trust.aspx).  With an External Trust, we don’t have any of the same forest functional level restrictions, opening up PCNS as a viable option for more customers.  I would love to know if anyone has been able to get PCNS working in this configuration.  In the mean time, I will have to set up a lab and try it out.  I will report back on the results and let you know!

Friday, February 24, 2012

The Last FIM Workflow You Will Ever Need

Okay, probably not, but its still pretty cool.  I recently built a Workflow in FIM that will allow a user to define the code they want executed at run time.  The Workflow will compile the code and run it in a separate app domain when its initiated (http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm).  The UI will allow you to specify the input parameters and where the result of the code execution will go.  Here is a simple example, I am passing in the first and last name from the target of the request, I am also passing the the mail host that I have calculated in a previous step and saved to WorkflowData.  I am then using the code to calculate the user’s email address and save it to the email parameter on the target:

imageimage

You can add and remove input parameters as needed during design time and then refer to them in the code using their specified index. I expect in future releases to be allow the user to specify additional namespaces and code references to import. It currently won’t do any syntax checking or formatting at design time, but otherwise its extremely versatile and flexible! 

UPDATE: Check out Part 2 of this article for the latest information and download instructions!

Friday, January 13, 2012

Sun One Boolean Attributes

Recently while working with the Sun One MA, I came across a problem caused by how FIM interprets boolean data coming from the directory.  In this case, the Sun One directory stores its boolean data as “YES” or “NO”, however when imported by FIM, this data always gets converted to False in the connector space.  (http://social.technet.microsoft.com/Forums/en-US/identitylifecyclemanager/thread/8ffc112e-d945-4916-83b3-78fbba716705)

Now we can’t use an advance import flow to correctly convert the data as it comes into the Metaverse because we have already lost data integrity.  The data that’s in the connector space is basically useless.  This only leaves us with a couple of options, we can write an XMA to correctly handle the data, but this can be fairly complicated.  We can also update the directory schema and use a string instead of a boolean, however, this could cause other downstream issues with other systems that might be consuming this data.  There is one other option, but its completely unsupported.  You could update the FIM database to make the system think this attribute is a string. 

Begin by running the following SQL Statement using the SQL Server Management Studio against your FIM database:

SELECT CAST(ma_schema_xml AS XML)   
  FROM FIMSynchronizationService.dbo.mms_management_agent
 WHERE ma_name = '<Sun One MA Name Here>'

In the results window you will get a single record that can be clicked on to open an xml document containing the schema for your Sun MA. Each attribute in the directory will appear using this syntax:

<attribute-type id="system_assigned_id" single-value="true/false">
     <name>attribute_name</name>
     <syntax>LDAPv3_syntax_oid</syntax>
</attribute-type>

If you do a quick search (Ctrl+F) for your attribute, you can manually update the LDAP Syntax OID from a boolean (1.3.6.1.4.1.1466.115.121.1.7) to a string (1.3.6.1.4.1.1466.115.121.1.15).  In my case, the new XML looked like:

<attribute-type id="Ah" single-value="true">
     <name>isManager</name>
     <syntax>1.3.6.1.4.1.1466.115.121.1.15</syntax>
</attribute-type>

I then used an update statement to write this information back to the database.  After performing a full import on this MA the connector space now reflected this data as a string of “YES” or “NO” just as it appears in the directory.  Now that the connector space had data I could work with, I wrote a quick advanced import flow rule to transform this value to a boolean:

case "isManager":

   //perform conversion for isManager from yes/no to boolean value
   if (csentry["isManager"].IsPresent)
   {
      if (csentry["isManager"].Value.Equals("yes", StringComparison.InvariantCultureIgnoreCase))
      {
         mventry["isManager"].BooleanValue = true;
      }
      else
      {
         mventry["isManager"].BooleanValue = false;
      }
   }
   break;

This approach does have its risks.  It will need to be re-done after performing a schema refresh in FIM and there is no guarantee it will keep working after an upgrade/patch.   The following SQL query could be used to script out this update, just replace the attributeName and SunOneMA variables and you should be good to go:

DECLARE @attributeName AS Varchar(255) = '<Attribute Name Here>'
DECLARE @SunOneMA AS Varchar(255) = '<Sun One MA Name Here>'
DECLARE @newSchemaOID AS Varchar(255) = '1.3.6.1.4.1.1466.115.121.1.15' --Directory String

-- get schema data
DECLARE @schema AS XML

SELECT @schema = CAST(ma_schema_xml as xml)
  FROM FIMSynchronizationService.dbo.mms_management_agent
 WHERE ma_name = @SunOneMA

-- update schema type
SET @schema.modify('
   declare default element namespace http://www.dsml.org/DSML;
   replace value of
      (dsml/directory-schema/attribute-type[name=sql:variable("@attributeName")]/syntax/text())[1]
   with
      sql:variable("@newSchemaOID")
   ')

-- save back to table
UPDATE FIMSynchronizationService.dbo.mms_management_agent
   SET ma_schema_xml = CONVERT(nvarchar(MAX), @schema)
 WHERE ma_name = @SunOneMA