Skip Ribbon Commands
Skip to main content

Identity Management at CERN

:

Home
November 15
Unexpected behavior with null values if an object is deleted and recreated

Sometimes attributes configured with equal precedence in the MetaVerse do not behave as I would expect.

I tested the following case in my lab environment, with the latest hotfix (http://support.microsoft.com/kb/2520954) applied.

I add a new person to my HR database, and set his supervisor to myself:

add-john-doe.png
The "SUPERVISOR_PERSON_ID" property in HR maps to "manager" in the MV and to "Manager" in FIM. From MV to FIM there both an import and export flows defined, and "Allow Nulls" is checked on export:

mgr-eaf.png

The attribute is configured with equal precedence in the MV:

mgr-mv-prec.png

Now, if I import/synch from HR, export to FIM and import/synch back, I see in the MV that the new person has me as manager, and that the value is contributed by HR.

If I set the manager to null in the HR DB, then synchronize as before, the manger attribute is set to null in the DB and in FIM, as expected.

mod-john-doe.png

jdoe-mv2.png

Now, however, let's try a different case.
I put back John Doe's manager, I run the synchronization, and then I delete the entry in HR.

The manager is still "Paolo Tedesco", and the value is contributed by FIM, which is correct:

jdoe-mv3.png

Now I put back the entry for John Doe, but with no manager.
I run the usual synchronization profiles, and after that the value contributed by FIM is still present:

jdoe-mv4.png

I think that in this case, null should be treated like any other value, and the value contributed by FIM should be discarded.

Setting equal precedence in the MV is kind of the "official workaround" to allow nulls on attributes that have both an export and an import attribute flow.


March 21
Forefront Identity Manager Service Account is not in All People...
I just ran into a strange problem with an MPR not being triggered. The problem was, quite surprisingly for me, that the requestor was not in All People.
 
The MPR was a request-based MPR that should have been triggered by the change of an attribute. However, in some cases, the attribute changed, but the MPR was not triggered.
 
I tried to modify the attribute with the administrator account, and the MPR was triggered correctly, so it was obvious that request definition and set definitions before/after request were ok.
 
I checked the requests page, and found out a request called "System Event Request", whose requestor was "Forefront Identity Manager Service Account".
 
When I searched for that account among the users, I could not find it, so I searched it by ObjectID, and discovered that it's not an account, but just a resource.
 
That resource is used as requestor when a resource is modified by a Workflow triggered by a set transition.
 
I modified the definition of the MPR, changing the requestor from "All People" to "All Objects" and now everything works as expected.
January 26
Modifying objects with the FIMAutomation PowerShell snapin
The FIM Powershell snapin is very handy to create, modify and delete FIM objects through PowerShell scripts.
 
To perform an operation on a FIM object, first we need to create an ImportObject:
$importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
Then, we need to specify its parameters: the object type, the object identifier and the state.
The object type tells which kind of object we want to deal with: a person, a group etc.
The object identifier is the ObjectID of the object we want to modify. We must specify this only if we want to delete or modify an existing object; if we want to create a new object, the system will assign it an ID automatically.
The state, finally, indicates which operation we want to perform: create, modify or delete. This parameter is of type [Microsoft.ResourceManagement.Automation.ObjectModel.ImportState], which is rather long to type, so we can shorten it like this:
$ImportState = [Microsoft.ResourceManagement.Automation.ObjectModel.ImportState]
So, for example, if we wanted to delete a Person with ObjectID "urn:uuid:0661574e-4186-4e6d-aba1-9ee02f31e8b0" we would do something like this:
$importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
$importObject.ObjectType = "Person"
$importObject.TargetObjectIdentifier = "urn:uuid:0661574e-4186-4e6d-aba1-9ee02f31e8b0"
$importObject.SourceObjectIdentifier = "urn:uuid:0661574e-4186-4e6d-aba1-9ee02f31e8b0"
$importObject.State = $ImportState::Delete
To modify the same person we would write this:
$importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
$importObject.ObjectType = "Person"
$importObject.TargetObjectIdentifier = "urn:uuid:0661574e-4186-4e6d-aba1-9ee02f31e8b0"
$importObject.SourceObjectIdentifier = "urn:uuid:0661574e-4186-4e6d-aba1-9ee02f31e8b0"
$importObject.State = $ImportState::Put
And to create a new one we would not need to specify the object ID:
$importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
$importObject.ObjectType = "Person"
$importObject.State = $ImportState::Create
The delete example is ok, but of course, if we want to modify or create an object, we must also specify which attributes we want to set.
Attributes are specified with a list of ImportChange objects:
$importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange
The ImportChange object allows us to do three different operations:
  • Set (or unset) the value of a single-valued attribute.
  • Add a value to a multi-valued attribute.
  • Remove a value from a multi-valued attribute.
For example, to change the display name of a person (single-valued) we would do this:
# "shortcut" for the enum that defines the operation type
$ImportOperation = [Microsoft.ResourceManagement.Automation.ObjectModel.ImportOperation]

# Set the display name of a person
$importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange
$importChange.Operation = $ImportOperation::Replace
$importChange.AttributeName = "DisplayName"
$importChange.AttributeValue = "John Doe"
$importChange.FullyResolved = 1
$importChange.Locale = "Invariant"

# finally, we need to add the import change to the list of import changes of
# the import object that represents the operation we want to perform (e.g. 
# create or update a person).
$importObject.Changes = $importObject.Changes + $importChange
To unset an attribute, we would just need not to specify the AttributeValue property.
This works for single-valued attributes, but if we are dealing with multi-valued attributes, we need to specify different operation types. Here are a couple of examples using the multi-valued Owner attribute of the group class:
# Add an owner to a group
$importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange
$importChange.Operation = $ImportOperation::Add
$importChange.AttributeName = "Owner"
$importChange.AttributeValue = "urn:uuid:0661574e-4186-4e6d-aba1-9ee02f31e8b0"
$importChange.FullyResolved = 1
$importChange.Locale = "Invariant"

# Remove an owner from a group
$importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange
$importChange.Operation = $ImportOperation::Delete
$importChange.AttributeName = "Owner"
$importChange.AttributeValue = "urn:uuid:0661574e-4186-4e6d-aba1-9ee02f31e8b0"
$importChange.FullyResolved = 1
$importChange.Locale = "Invariant"
July 14
Simplifying the FIMAutomation snap-in: PsExportObject

The FIMAutomation PowerShell snap-in is a very useful tool to automate administrative tasks, as it allows you to perform queries and create, modify and delete objects in FIM. Check the FIM Scriptbox page on TechNet for many examples of what you can do with the snap-in.

The only problem with the tool, however, is that it was conceived primarily to migrate the FIM configuration from one server to another, and the syntax for manipulating objects with it is not really straightforward. This example shows how to read the attributes of a user:

$user=Export-FIMConfig -CustomConfig "/Person[AccountName='jdoe']" -OnlyBaseResources
foreach ($attribute in $user.ResourceManagementObject.ResourceManagementAttributes) {
    $name=$attribute.AttributeName
    if ($attribute.IsMultiValue) {
        $value=$attribute.Values
    } else {
        $value=$attribute.Value
    }
    "$name = $value"
}

This is not terrible either, but it's quite a lot of typing, especially if you are not running a script but just running commands in the prompt. This other example shows how to get a particular attribute, e.g. the DisplayName:

$user=Export-FIMConfig -CustomConfig "/Person[AccountName='jdoe']" -OnlyBaseResources
$displayName=$user.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "DisplayName"}
$displayName.Value

It would be nice to have a way to manipulate an ExportObject in a simpler way. This can be done using PowerShell's capability to extend objects. This filter will convert an ExportObject to a PSObject:

function PsExportObject() {
    process {
        $importObject = $_
        $psObject = New-Object PSObject
        foreach ($attribute in $importObject.ResourceManagementObject.ResourceManagementAttributes) {
            $name=$attribute.AttributeName
            if ($attribute.IsMultiValue) {
                $value=$attribute.Values
            } else {
                $value=$attribute.Value
            }
            Add-Member -InputObject $psObject -MemberType NoteProperty -Name $name -Value $value
        }
        $psObject
    }
}

We can use the filter simply piping the results of Export-FIMConfig to it:

PS > Export-FIMConfig -CustomConfig "/Person[AccountName='jdoe']" -OnlyBaseResources | PsExportObject
ObjectID                   : urn:uuid:b8144b57-5bac-4a29-b6f1-b36914d194c0
AccountName                : jdoe
Company                    : FIMTEST
CreatedTime                : 6/10/2010 2:57:00 PM
Creator                    : urn:uuid:fb89aefa-5ea1-47f1-8890-abe7797d6497
DisplayName                : John Doe

And now, we can access the user's properties with a more intuitive syntax:

$user=Export-FIMConfig -CustomConfig "/Person[AccountName='jdoe']" -OnlyBaseResources | PsExportObject
$user.DisplayName
June 30
Maximum length of attributes in Active Directory
Running some AD export tests, I got some constraint-violation errors. Clicking on the error did not provide more meaningful details: the error message was "a value for the attribute was not in the acceptable range of values", but it was not specified which attribute was out of range.
 
Looking at the objects causing the exception, I discovered that all of them had the same value for the company attribute, and that this value was longer than 64 characters, which is the upper limit for the company attribute in AD.
Here is a small PowerShell script to get the maximum length of an AD attribute:
param ([string]$attributeName = $(throw "Specify attribute name"))
$rootDSE=[ADSI]"LDAP://RootDSE"
$attribute=[ADSI]"LDAP://CN=$attributeName,CN=Schema,CN=Configuration,$($rootDSE.defaultNamingContext)"
if ($attribute.rangeUpper -eq $null) {
    "no limit"
} else {
    $attribute.rangeUpper
}
 
At this point, I just had to modify my export flow from 'company -> company' to 'Left(company,63) -> company'.
Note that I'm taking the first 63 - and not 64 - characters of the attribute, as the maximum length includes a null terminating character.
April 14
Strange "InvalidRepresentationException" error
Playing with FIM, I got a strange error of type Microsoft.ResourceManagement.WebServices.Exceptions.InvalidRepresentationException.
 
I couldn't find any documentation about the error, and the cause was rather hard to find, so I'm posting the solution here (so that when I'll do the same mistake again I'll be able to find a place with the solution).
 
The error was occurring since I was trying to modify a custom attribute of a person, but I had forgot to create the binding between the person type and the attribute I had just defined.
 
 
April 06
MVP Award
I've been given the MVP award 2010 for Identity Lifecycle Manager!
 
Dear Paolo Tedesco,
Congratulations! We are pleased to present you with the 2010 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in Identity Lifecycle Manager technical communities during the past year.
 
March 29
FIM Client on CodePlex
I started a project on CodePlex for the public FIM 2010 Resource Management Client.
 
It's a work in progress and needs some serious work, so whoever is interested is very welcome to contribute!
 
 
March 22
Error in Value property setter in RmAttributeValue class

In the RmAttributeValue class, the Value property setter is as follows:

 

        public IComparable Value {

            // get accessor omitted

            set {

                lock (this .values) {

                    if (this .values.Count > 0 ) {

                        if (value == null ) {

                            this .values.Clear();

                        } else {

                            this .values.Add(value );

                        }

                    } else {

                        this .values.Add(value );

                    }

                }

            }

        }

Thus, setting the value of an attribute whose value is already set incorrectly results in a new value being added to the internal collection, as shown by this example:

            RmAttributeValue value = new RmAttributeValue ();

            value.Value = "one" ;

            value.Value = "two" ;

            // now:

            // value.IsMultiValue == true

            // value.Values.Count == 2

The code should be modified as follows:

        public IComparable Value {

            // get accessor omitted

            set {

                lock (this .values) {

                    this .values.Clear();

                    if (value != null ) {

                        this .values.Add(value );

                    }

                }

            }

        }

March 18
Installing FIMAutomation on a FIM-less machine
It is possible to get the FIMAutomation snap-in running on a machine where FIM is not installed, which is useful for running queries or regenerating strongly typed classes without necessarily developing on the FIM server.
From the C:\Program Files\Microsoft Forefront Identity Manager\2010\Service folder on the FIM server, copy the following files:
  • Microsoft.ResourceManagement.Automation.dll
  • Microsoft.IdentityManagement.Logging.dll
  • Microsoft.ResourceManagement.dll
Then, from an elevated visual studio prompt, register the snapin and GAC-install the other assemblies:
(1) > InstallUtil.exe -i .\Microsoft.ResourceManagement.Automation.dll
(2) > gacutil -i Microsoft.ResourceManagement.dll
(3) > gacutil -i Microsoft.ResourceManagement.Logging.dll
If you are installing the FIM PowerShell snapin on a 64-bit machine, make sure that you are running the correct version of InstallUtil, which should be
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe
while the VS prompt picks by default the one in
C:\Windows\Microsoft.NET\Framework\v2.0.50727\
1 - 10Next