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
This is the personal blog of Stefan van der Wiele, Infrastructure Engineer specialist in Security and Identity Management. This blog will mostly be about Forefront Identity Manager 2010
dinsdag 14 december 2010
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.
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.
woensdag 24 november 2010
Learning FIM (virtual labs)
If you want to try FIM but don't have a own testing enviorment, then you can use the Microsoft Virtual Labs. In this blogpost I will provide you links to the different types of Virtual Labs
Virtual labs
Virtual labs
- TechNet Virtual Lab: Forefront Identity Manager (FIM) 2010 Overview
- TechNet Virtual Lab: The FIM Experience
- TechNet Virtual Lab: Importing and Synchronizing Data
- TechNet Virtual Lab: Joining Data from Another MA and Provisioning AD LDS
- TechNet Virtual Lab: Managing Users in the FIM Portal
- TechNet Virtual Lab: Creating the FIM MA and Synchronizing
- TechNet Virtual Lab: Inbound Synchronization Rules
- TechNet Virtual Lab: Synchronizing Active Directory Users
- TechNet Virtual Lab: Password Self-service and Configuring PCNS
- Technet Virtual Lab: Distribution Groups and Provisioning Distribution Groups in Active Directory
- Technet Virtual Lab: Security Groups and Provisioning Security Groups in Active Directory
- TechNet Virtual Lab: Backup, Restore, and Disaster Recovery, MA Run Scripts, and Final Configuration
- TechNet Virtual Lab: Managing Groups- Lab A
- TechNet Virtual Lab: Managing Groups- Lab B
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
}
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:
- The entire <system.diagnostics>...<system.diagnostics> is commented out. You will need to un-comment that.
- 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.
- 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.
- For those traces that are being considered, they will be passed to each of the listeners:
- The XmlWriterTraceListener will write all the traces to the file C:\Logs\PwdMgmtProxy.svclog.
- 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:
- Uncomment <system.diagnostics>...<system.diagnostics>
- Change Warning to Verbose
- If you want everything to be written to event log as well, change Error to Verbose as well
- Create C:\Logs and grant NETWORK SERVICE full access on that folder so the file can be created.
- 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.
maandag 27 september 2010
Do you need a Unique Name Generator for Forefront Identity Manager 2010?
One thing that is not present by default in FIM 2010 is a unique name generate (Accountnames). You can create your own custom workflow activity or use an existing solution like:
http://www.tools4fim.com/function-evaluator.aspx
http://www.tools4fim.com/function-evaluator.aspx
dinsdag 21 september 2010
PowerShell Activity for FIM
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!
Welcome!
Hi Everybody!
On this blog I am going to share my experience with Forefront Identity Manager 2010. I hope it will help and entertain you :)
Greetings,
Stefan
On this blog I am going to share my experience with Forefront Identity Manager 2010. I hope it will help and entertain you :)
Greetings,
Stefan
Troubleshooting Common FIM Provisioning Errors
The objective of this article is to capture the most common synchronization errors and to provide troubleshooting steps to resolve them.
Synchronization errors addressed in this article:
- Microsoft.MetadirectoryServices.ProvisioningBySyncRuleException: An object with DN "ABC" already exists in management agent "DEF"
- Microsoft.MetadirectoryServices.ProvisioningBySyncRuleException: Object "ABC" does not have a parent object in management agent "DEF"
Abonneren op:
Posts (Atom)