vrijdag 18 november 2011

Directory Synchronization tool 64-bit support

Finally it's here! The Directory Sync tool for Office 365 based on FIM 2010. So there's 64bit support.

Source: http://community.office365.com/en-us/w/sso/555.aspx

Next thing I'm going to try in my lab environment is trying to extract the MA from the sync tool to use it in native FIM 2010. :-)

Keep you posted!

dinsdag 14 december 2010

Tools4FIM RCDC Editor - NOW AVAILABLE!

The RCDC editor is a WYSIWYG editor for Resource Control Display Configurations (RCDCs). This accelerates and supports FIM user interface customization, but saving heaps of time manually editing XML files. Once you have exported the Service configuration, you can browse through the RCDCs and configure them. You can then save the results and test them in FIM. As far as possible the RCDC Editor is designed not to allow illegal configurations, which is where so much time is normally wasted. Once you have used it, you won't go back to editing the configuration manually; and if you’ve never edited one manually, you’ll never need to!


Read more

dinsdag 30 november 2010

FIM 2010: Delete a user when the end date is reached (Expiration Workflow)

If you are using the FIM portal, you problaby have noticed the Expiration Workflow. This workflow can became very handy to delete users from the FIM portal if the end date is reaced.

But how do you use it? I will provide you with a little manual that will guide you through the steps.

1. First create a set that will contain all users with the end datum that is equal to today:




















 2. Then create a set that contains the Expiration Workflow, because you need to give the Expiration Workflow rights to delete a user object.


















3. Then you need to configure rights for the Expiration Workflow to delete a user object




































4. And then youb need to create a MPR to launch the Expiration Workflow when a user joins the set.






































After creating this MPR users will be deleted from the FIM portal if there end date is reached. If you want to delete them from other connected systems you need to configure the Object Deletion rules in the FIM Synchronisation Engine and configure deprovisining.

dinsdag 9 november 2010

PowerShell: Create a FIM user and add the SID from AD

Today I created a PowerShellscript that displays a inputbox where you can enter a username, after that the script will create a new user in the FIM portal and it will find the SID in the AD and add it to the user.

This scripts is a combination of two scripts found on the technet forum with a little bit custom code.

The code is a little bit "dirty", it needs some optimalisation.

The code is below:


[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')

#----------------------------------------------------------------------------------------------------------
 set-variable -name URI -value "http://localhost:5725/resourcemanagementservice' " -option constant
#----------------------------------------------------------------------------------------------------------
 function SetAttribute
 {
    PARAM($object, $attributeName, $attributeValue)
    END
    {
        $importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange
        $importChange.Operation = 1
        $importChange.AttributeName = $attributeName
        $importChange.AttributeValue = $attributeValue
        $importChange.FullyResolved = 1
        $importChange.Locale = "Invariant"
        if ($object.Changes -eq $null) {$object.Changes = (,$importChange)}
        else {$object.Changes += $importChange}
    }
}
#----------------------------------------------------------------------------------------------------------
 function CreateObject
 {
    PARAM($objectType)
    END
    {
       $newObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
       $newObject.ObjectType = $objectType
       $newObject.SourceObjectIdentifier = [System.Guid]::NewGuid().ToString()
       $newObject
     }
 }
#----------------------------------------------------------------------------------------------------------
 function CreateUser
{

 if(@(get-pssnapin | where-object {$_.Name -eq "FIMAutomation"} ).count -eq 0) {add-pssnapin FIMAutomation}
 clear-host

 if($args.count -ne 1) {throw "You need to specify your attribute values as parameter"}
 $attributes = ($args[0]).split("|")

 if(0 -ne [String]::Compare(($attributes[0]).split(":")[0],"displayname", $true))
 {throw "You need to specify a display name"}

 $objectName = ($attributes[0]).split(":")[1]
 $exportObject = export-fimconfig -uri $URI `
                                  –onlyBaseResources `
                                  -customconfig "/Person[DisplayName='$objectName']"
 if($exportObject) {throw "L:User $objectName already exists"}

 $newUser = CreateObject -objectType "Person"
 foreach($attribute in $attributes)
 {
    $attrData = $attribute.split(":")
    SetAttribute -object $newUser `
                 -attributeName  $($attrData[0]) `
                 -attributeValue $($attrData[1])
 }            

 $newUser | Import-FIMConfig -uri $URI
 write-host "`nUser created successfully`n"
}
#----------------------------------------------------------------------------------------------------------
 trap
 {
    $exMessage = $_.Exception.Message
    if($exMessage.StartsWith("L:"))
    {write-host "`n" $exMessage.substring(2) "`n" -foregroundcolor white -backgroundcolor darkblue}
    else {write-host "`nError: " $exMessage "`n" -foregroundcolor white -backgroundcolor darkred}
    Exit
 }
#----------------------------------------------------------------------------------------------------------
 function GetSidAsBase64
{
    PARAM($AccountName, $Domain)
    END
    {
        $sidArray = [System.Convert]::FromBase64String("AQUAAAAAAAUVAAAA71I1JzEyxT2s9UYraQQAAA==") # This sid is a random value to allocate the byte array
        $args = (,$Domain)
        $args += $AccountName
        $ntaccount = New-Object System.Security.Principal.NTAccount $args
        $desiredSid = $ntaccount.Translate([System.Security.Principal.SecurityIdentifier])
write-host " -Account SID : ($Domain\$AccountName) $desiredSid"
        $desiredSid.GetBinaryForm($sidArray,0)
        $desiredSidString = [System.Convert]::ToBase64String($sidArray)
        $desiredSidString
    }
}

function fixSid
{
PARAM([string]$AccountName,[string]$Domain)
cls
#------------------------------------------------------------------------------------------------------
 set-variable -name URI    -value "http://localhost:5725/resourcemanagementservice"    -option constant

#------------------------------------------------------------------------------------------------------
 write-host "`nFix Account ObjectSID"
 write-host "=========================="
#------------------------------------------------------------------------------------------------------
#Retrieve the Base64 encoded SID for the referenced user
 $accountSid = GetSidAsBase64 $AccountName $Domain
#------------------------------------------------------------------------------------------------------
#Export the account configuration from the service:
 write-host " -Reading Account information"
 if(@(get-pssnapin | where-object {$_.Name -eq "FIMAutomation"} ).count -eq 0)
 {add-pssnapin FIMAutomation}

 $exportObject = export-fimconfig -uri $URI `
                                -onlyBaseResources `
                                -customconfig ("/Person[AccountName='$AccountName']")
 if($exportObject -eq $null) {throw "Cannot find an account by that name"}
 $objectSID = $exportObject.ResourceManagementObject.ResourceManagementAttributes | `
                 Where-Object {$_.AttributeName -eq "ObjectSID"}

 Write-Host " -New Value = $accountSid"
 Write-Host " -Old Value =" $objectSID.Value

 if($accountSid -eq $objectSID.Value)
  {
Write-Host "Existing value is correct!"
}
 else
  {
$importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange
$importChange.Operation = 1
$importChange.AttributeName = "ObjectSID"
$importChange.AttributeValue = $accountSid
$importChange.FullyResolved = 1
$importChange.Locale = "Invariant"
$importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
$importObject.ObjectType = $exportObject.ResourceManagementObject.ObjectType
$importObject.TargetObjectIdentifier = $exportObject.ResourceManagementObject.ObjectIdentifier
$importObject.SourceObjectIdentifier = $exportObject.ResourceManagementObject.ObjectIdentifier
$importObject.State = 1
$importObject.Changes = (,$importChange)
write-host " -Writing Account information ObjectSID = $accountSid"
$importObject | Import-FIMConfig -uri $URI -ErrorVariable Err -ErrorAction SilentlyContinue
if($Err){throw $Err}
Write-Host "Success!"
}
#------------------------------------------------------------------------------------------------------
 trap
 {
    Write-Host "`nError: $($_.Exception.Message)`n" -foregroundcolor white -backgroundcolor darkred
    Exit
 }
#------------------------------------------------------------------------------------------------------
}
$c=[Microsoft.VisualBasic.Interaction]::InputBox("Enter the admin account that need access to FIM","Create FIM admin account")

if ($c.Trim()) {
createUser "DisplayName:$c|AccountName:$c"
fixSid $c
}

donderdag 4 november 2010

FIM 2010 Self-Service Password Reset Now Supports All Domain Password Policies


FIM 2010 Self-Service Password Reset now supports all domain password policies.  It was a joint effort between the Windows Active Directory and FIM development teams to provide this new functionality. 
Details of this change can be found in http://support.microsoft.com/KB/2443871.

woensdag 29 september 2010

Troubleshooting FIMService / FIMPortal / Password Reset Client


FIM is a complex product. Once a while, I find myself just clueless why something does not work. I have the advantage of having access to the source code and be able to debug. Attaching a debugger isn't a 5-second task and very often the answer is actually in the log. In this blog post, I would talk about how to enable tracing.
Warning: you should always backup your config file before making any change.

Let's start with the easiest - Password Reset Client.

The following is the config file for the client at C:\Program Files\Microsoft Forefront Identity Manager\2010\Password Reset Client Service\PwdMgmtProxy.exe.config.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section
            name="resourceManagementClient"
            type="Microsoft.ResourceManagement.WebServices.Client.ResourceManagementClientSection, Microsoft.ResourceManagement"/>
    </configSections>
    <resourceManagementClient
        resourceManagementServiceBaseAddress="http://localhost:5725"
        timeoutInMilliseconds="60000" />
    <appSettings>
        <add key="NamedPipeTimeout" value="10000"/>
    </appSettings>
<!--
    <system.diagnostics>
        <sources>
            <source name="Microsoft.ResourceManagement" switchValue="Warning">
                <listeners>
                    <add type="System.Diagnostics.DefaultTraceListener" name="Default">
                        <filter type="" />
                    </add>
                    <add initializeData="C:\Logs\PwdMgmtProxy.svclog"
                        type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                        name="ResourceManagementListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack">
                        <filter type="" />
                    </add>
                    <add initializeData="Application" type="System.Diagnostics.EventLogTraceListener"
                        name="myEventListener">
                        <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" />
                    </add>
                    <add type="System.Diagnostics.ConsoleTraceListener" name="myConsoleListener"
                        traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack">
                        <filter type="System.Diagnostics.EventTypeFilter" initializeData="Information" />
                    </add>
                </listeners>
            </source>
        </sources>
        <trace autoflush="true" indentsize="0" />
    </system.diagnostics>
-->
</configuration>
FIM uses standard .NET Tracing and Instrumenting libraries. I have highlighted a few important things in the config file:
  1. The entire <system.diagnostics>...<system.diagnostics> is commented out. You will need to un-comment that.
  2. The managed part of FIM (FIMService / FIMPortal / Pwd Reset Client) shares the same tracing library and all traces are written to a source Microsoft.ResourceManagement. You should not change this part.
  3. The Warning switch means for all FIM specific traces, only traces of warning level and above will be considered. Notice nothing has been logged so far.
  4. For those traces that are being considered, they will be passed to each of the listeners:
    1. The XmlWriterTraceListener will write all the traces to the file C:\Logs\PwdMgmtProxy.svclog.
    2. The EventLogTraceListener will further filter only trace with Error level and above, and write them to event log.
So to enable tracing for Password Reset Client, you will need to:
  1. Uncomment <system.diagnostics>...<system.diagnostics>
  2. Change Warning to Verbose
  3. If you want everything to be written to event log as well, change Error to Verbose as well
  4. Create C:\Logs and grant NETWORK SERVICE full access on that folder so the file can be created.
  5. Restart FIMPasswordReset service

FIMService and FIMPortal are really the same

The FIMService config file already contains inline comment on how to enable tracing. You can follow those steps.
If you want to log everything, you can replace t<system.diagnostics> section with the following. Warning, the trace file gets really huge.
<system.diagnostics>
  <sources>
    <source name="System.ServiceModel.MessageLogging" switchValue="ActivityTracing">
      <listeners>
        <add type="System.Diagnostics.DefaultTraceListener" name="Default">
          <filter type="" />
        </add>
        <add name="ServiceModelMessageLoggingListener">
          <filter type="" />
        </add>
      </listeners>
    </source>
    <source name="System.ServiceModel" switchValue="Critical,ActivityTracing"
      propagateActivity="true">
      <listeners>
        <add type="System.Diagnostics.DefaultTraceListener" name="Default">
          <filter type="" />
        </add>
        <add name="ServiceModelTraceListener">
          <filter type="" />
        </add>
      </listeners>
    </source>
    <source name="Microsoft.ResourceManagement" switchValue="Verbose,ActivityTracing">
      <listeners>
        <add type="System.Diagnostics.DefaultTraceListener" name="Default">
          <filter type="" />
        </add>
        <add name="ServiceModelTraceListener">
          <filter type="" />
        </add>
      </listeners>
    </source>
  </sources>
  <sharedListeners>
    <add initializeData="C:\Logs\Microsoft.ResourceManagement.Service_messages.svclog"
      type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      name="ServiceModelMessageLoggingListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack">
      <filter type="" />
    </add>
    <add initializeData="C:\Logs\Microsoft.ResourceManagement.Service_tracelog.svclog"
      type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      name="ServiceModelTraceListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack">
      <filter type="" />
    </add>
  </sharedListeners>
  <trace autoflush="true" /> 
</system.diagnostics>
For FIMPortal, you need to change the highlighted filename to something else. For example, use:
  • ILMPortal.Client_messages.svclog
  • ILMPortal.Client_tracelog.svclog
The *_tracelog.svclog contains all the FIM specific traces instrumented by the FIM team (you will spend 99% of your time with this file). On the other hand, *_messages.svclog contains WCF specific traces.

How to Get Rid of the Generic FIMPortal Error Page?

When there is an error in FIMPortal, you will see the follow screen which absolutely contains no useful information at all.
Thomas Vuylsteke has blogged about how to get rid of hat to get a full stack trace which is usually enough for you to troubleshoot FIMPortal issues.