FIM 2010 – User RCDC to Add User to Groups

In FIM 2010, there is no way to use the current RCDC (Resource Control Display Configuration) to create a “user” interface, not group interface, that will allow a user to be added to a group. The current out-of-the-box interface for FIM only allows for group interfaces to be used for adding users to specific groups. In the world of self service, administrators should be moving away from group and user management. However, with FIM 2010 the interface is built for a more technical staff, which is a problem for the everyday user. Below is how I solved this problem in FIM 2010. The below explaination is technical and FIM 2010, Visual Basic, and XML knowledge is needed.

How did I use the “user” interface and achieve user addition or removal from groups?

  1. Changes to the schema
  2. Changes to the User RCDC
  3. Created a Custom WorkFlow in VB.NET

Step 1: Changes to the schema

I created a new resource type reference object which contains the names of the groups I wanted users to request or to be able to be added to.  This gave me a short, easy custom list for any admin to add a role/groups to without needing to search. I then created a reference attribute on the user resource type to view the new reference type groups in a drop down. (Attributes are added in the Schema Section in the FIM Portal).

Step 2: Changes to the User RCDC

To use this drop down in the RCDC for users, I added this to the User Edit RCDC:

<my:Control my:Name="GroupRoleName" my:TypeName="UocDropDownList" my:Caption="Access Role" my:Description="Access Role"  my:RightsLevel="{Binding Source=rights, Path=Group_Ref}" my:AutoPostback="true">
        <my:Property my:Name="Required" my:Value="{Binding Source=schema, Path=Group_Ref.Required}"/>
        <my:Property my:Name="Columns" my:Value="40"/>
        <my:Property my:Name="HintPath" my:Value="Hint"/>
        <!--The new user attribute which is a reference attribute-->
        <my:Property my:Name="ItemSource" my:Value="{Binding Source=search, Path=Group_Role_Ref}"/>
        <!--The new resource type attribute where my list of roles are located--> 
        <my:Property my:Name="SelectedValue" my:Value="{Binding Source=object, Path=Group_Ref, Mode=TwoWay}"/>

FYI, the reference attribute will only be stored as an ObjectID; I look up the display name in my workflow below.

Then, I created sets that would kick off an add or remove Management Policy Rule (MPR).  I used a custom boolean attribute that if selected would add/remove the user to the set, and then kick off an MPR, and finally run a WorkFlow activity.

Step 3: Created a Custom WorkFlow in VB.NET

Finally, I created a new custom WorkFlow where I used the new resource type display names for quering the groups with a dynamic XPath query in a EnumerateResourceActivity and then an UpdateResourceActivity which added/removed the user from a group.

Here is the important code when running an enumeration activity:

Enumeration Code

Make sure to add this above the Private Sub InitializeComponent():

Private codeActivity1 As CodeActivity

Make sure to add this in the Private Sub InitializeComponent() above the Me.CanModifyActivities = False:

Me.Name = "GroupActivity"
Me.codeActivity1 = New System.Workflow.Activities.CodeActivity()
Me.codeActivity1.Name = "codeActivity1"
AddHandler Me.codeActivity1.ExecuteCode, AddressOf Me.GetGroupEnum_ExecuteCode 'CodeActivity is the child of my enumerationresourceactivity Me.enumerateResourcesActivity1.Activities.Add(Me.codeActivity1)
Me.CanModifyActivities = False

Your activity design document should look like this afterwards for the enumerate activity or it will return a count but all other data will be NULL.

Now for some of the code for setting looking up the of the display name of the Resource Type using readresourceactivity:

Private Sub UpdateGroup_ExecuteCode(sender As System.Object, e As System.EventArgs)
    Me.Log("Starting Next Code ")
    Dim currentRequest As RequestType = currentRequestInformation_CurrentRequest1
    Me.Log("After Request")
    Dim RoleQuery As String = Me.Target_Resource1(Me.GUIinsert) 'GUI Insert Taken from the WorkFlow setup/GUI screen
    Me.Log("Role Name Returned1Ref1::" & RoleQuery & ". ")
    Me.GetDisplayName.ActorId = New System.Guid("00000000-0000-0000-0000-000000000000")
    Me.GetDisplayName.Name = "GetDisplayName"
    Me.GetDisplayName.Resource = Nothing
    Me.GetDisplayName.ResourceId = New System.Guid(RoleQuery)
    Me.GetDisplayName.SelectionAttributes = New String() {"DisplayName"}
End Sub

Enumeration Activity Code

Private Sub GetDisplay_ExecuteCode(sender As System.Object, e As System.EventArgs)
    Dim RoleQuery2 As String = Me.GetDisplayName_Resource1("DisplayName")
    Me.Log("Role Name Returned1Ref2:" & RoleQuery2 & ". ")
    Me.enumerateResourcesActivity1.ActorId = New System.Guid("00000000-0000-0000-0000-000000000000")
    Me.GetGroup.Name = "GetGroup"
    Me.enumerateResourcesActivity1.PageSize = 100
    Me.enumerateResourcesActivity1.Selection = New String() {"AccountName"}
    Me.enumerateResourcesActivity1.SortingAttributes = Nothing Me.enumerateResourcesActivity1.TotalResultsCount = 0 Me.enumerateResourcesActivity1.XPathFilter = "/Group[contains(" & Me.SearchScope & ",'" & RoleQuery2 & "')]" 'SearchScope is taken from WorkFlow GUI screen
    Me.Log("XPATH Name Returned1Ref2:" & Me.enumerateResourcesActivity1.XPathFilter & ". ")
End Sub

Enumeration and Update Code

Private Sub GetGroupEnum_ExecuteCode(sender As System.Object, e As System.EventArgs)
    Dim QueryGr As Guid = Nothing Me.Log("Role Name Returned1Ref3:. ")
    If Me.enumerateResourcesActivity1.TotalResultsCount > 0 Then
        Me.Log("Role Name Returned1Ref3:Inside. ")
        Me.Log("Role Name Returned1Ref4:seq. ")
        Dim currentItem As ResourceType = TryCast(EnumerateResourcesActivity.GetCurrentIterationItem(DirectCast(sender, CodeActivity)), ResourceType)
        If (currentItem Is Nothing) Then
            Me.Log("Role Name Returned1Ref5:Null.")
            Exit Sub
            Me.Log("Role Name Returned1Ref5:Not Null.")
                Me.Log("Number : " & Convert.ToString(Me.enumerateResourcesActivity1.TotalResultsCount))
                Me.Log("UID : " & currentItem.ObjectID.GetGuid().ToString())
            Catch ex As Exception
            End Try
            ReturnValue = currentItem.ObjectID.GetGuid().ToString()
        End If
    End If
    QueryGr = New Guid(ReturnValue)
    Dim GroupValue As Guid = Me.Target_ResourceId1
    Dim updateInstruction2 As Microsoft.ResourceManagement.WebServices.WSResourceManagement.UpdateRequestParameter = New Microsoft.ResourceManagement.WebServices.WSResourceManagement.UpdateRequestParameter() updateInstruction2.PropertyName = "ExplicitMember"
    If Me.AddRemoveGroup = "Add" Then 'Taken from WorkFlow GUI Screen if the workflow is remove or add
        updateInstruction2.Mode = UpdateMode.Insert
    ElseIf Me.AddRemoveGroup = "Remove" Then
        updateInstruction2.Mode = UpdateMode.Remove
    End If
        Me.update.UpdateParameters = New UpdateRequestParameter() {updateInstruction2}
        Me.update.ActorId = New System.Guid("00000000-0000-0000-0000-000000000000")
        Me.update.ResourceId = QueryGr
    Catch ex As Exception
        Me.Log("Role Name Returned16:" & ex.ToString() & ". ")
    End Try
End Sub
GUI Screen:
I hope this help others with an example of how to customize the “user” RCDC screen.

Identity Management and Active Directory Principal Engineer
Nathan Mertz | Bennett Adelson | Columbus