Skip to main content

FIM 2010 R2 Self-Service Password Reset Auto-Registration

I have been working on our FIM 2010 R2 SP1 lab environment looking for ways to simplify some of the overly complicated scenarios we had to implement to workaround the limitations in FIM 2010. One of those workarounds was the auto-registration of SSPR for new employees. When we onboard a new employee, we want to create a simple SSPR for them to get their first-time password reset.

Prior to the R2 release we were using the client and PowerShell to complete the registration process on a daily schedule. I was working on converting this to use the R2 registration cmdlets and combined it with PowerShell 3.0 Workflows to get to a solution similar to this.
  1. [CmdletBinding()]  
  2. param()  
  4. begin {  
  5.     workflow Invoke-RegisterSSPR {  
  6.         InlineScript {  
  7.             Import-Module FIM  
  8.         }  
  10.         $workflow = InlineScript { Get-FIMResource -Filter '/WorkflowDefinition[DisplayName = "Password Reset AuthN Workflow for New Employees"]' }  
  11.         $members  = InlineScript { Get-FIMResource -Filter "/Person[not(AuthNWFRegistered = '$($using:workflow.ObjectID)') and ObjectID = /Set[DisplayName = 'Password Reset Users Set for New Employees']/ComputedMember]" }  
  13.         '------------------------------------------------------------'  
  14.         '- Registering New Employees for SSPR'  
  15.         "   -> Found $([int]@($members).Count) users that need to be registered"  
  16.         '------------------------------------------------------------'  
  18.         ForEach -Parallel ($person in $members) {   
  19.             InlineScript {  
  20.                 $person = $using:person  
  22.                 Add-PSSnapin FIMAutomation  
  24.                 $template = Get-AuthenticationWorkflowRegistrationTemplate -AuthenticationWorkflowName 'Password Reset AuthN Workflow for New Employees'  
  25.                 $template.GateRegistrationTemplates[0].Data[0].Value = ([int]$person.PIN).ToString('0000')  
  26.                 $template.GateRegistrationTemplates[0].Data[1].Value = ([DateTime]$person.HireDate).ToString('MM/dd/yyyy')  
  28.                 $person | Select-Object -Property Domain,AccountName,PIN,HireDate,@{Name='Status';Expression={Register-AuthenticationWorkflow -UserName '$($_.Domain)\$($_.AccountName)' -AuthenticationWorkflowRegistrationTemplate $template -ErrorAction Continue}}  
  29.             }  
  30.         }  
  31.     }  
  32. }  
  34. end {  
  35.     Invoke-RegisterSSPR -ErrorAction Stop -PSElapsedTimeoutSec (4*60*60)  
  36. }  
Well, I was playing around tweaking my workflows and suddenly realized since I have the PowerShell activity from working with R2 workflows, so I could just take the core of the above script and use a set transition MPR to auto-register the employees as they flow into FIM and eliminate the daily job.

I ended up using the users set for the SSPR configuration for new employees as the transition set on the MPR though I may switch this to a new set of unregistered set users so I can only reprocess the people not processed yet if I need to if there is an issue at a later date, but then again if data is updated I can process all new employees leaving it with the SSPR users set.

Anyway, here is the PowerShell activity script that can be used to do this; make sure you run the activity as a user that has rights to run the registration cmdlets.
  1. param($WorkflowDefinitionId$RequestId$ActorId$TargetId$WorkflowData)  
  3. $ErrorActionPreference = 'Stop'  
  5. Add-PSSnapin FIMAutomation  
  6. Import-Module FIM  
  8. $Person = Get-FIMResource -Filter "/Person[ObjectID = '$TargetId']"  
  9. $Domain = $Person.Domain  
  10. $AccountName = $Person.AccountName  
  11. $PIN = $Person.PIN  
  12. $HireDate = $Person.HireDate  
  14. $template = Get-AuthenticationWorkflowRegistrationTemplate -AuthenticationWorkflowName 'Password Reset AuthN Workflow for New Employees'  
  15. $template.GateRegistrationTemplates[0].Data[0].Value = ([int]$PIN).ToString('0000')  
  16. $template.GateRegistrationTemplates[0].Data[1].Value = ([DateTime]$HireDate).ToString('MM/dd/yyyy')  
  18. Register-AuthenticationWorkflow -UserName "${Domain}\${AccountName}" -AuthenticationWorkflowRegistrationTemplate $template  


Popular posts from this blog

PowerShell SupportsShouldProcess Worst & Best Practices

This has been a very big discussion within the Scripting Games 2013 community and I want to add my two cents in an official blog post.

I've left several people comments on how they might be misunderstanding how SupportsShouldProcess works, but I also realize, everyone of these individuals has given me more insight into its use and perhaps, how it should best be utilized.

For those of you that don't know, SupportsShouldProcess is a parameter on the CmdletBinding attribute you can place on your cmdlets that automatically adds the -WhatIf and -Confirm parameters. These will naturally flow into other cmdlets you use that also SupportsShouldProcess, e.g. New-Item, Move-Item.

The major discussion has been around, should you just let the other cmdlets handle the $PSCmdlet.ShouldProcess feature, and if not how should you implement it. ShouldProcess has the following definitions.

Generate Random SecureString Key

Ever need to encrypt a SecureString that can be used across multiple servers? I suggest storing this BASE64 value in a secure location only accessible by the account(s) that need to decrypt the SecureString.
$secret = 'secret1234'$key    = [Convert]::ToBase64String((1..32 |% { [byte](Get-Random -Minimum 0 -Maximum 255) }))  $encryptedSecret = ConvertTo-SecureString -AsPlainText -Force -String $secret | ConvertFrom-SecureString -Key ([Convert]::FromBase64String($key))  $encryptedSecret | Select-Object @{Name='Key';Expression={$key}},@{Name='EncryptedSecret';Expression={$encryptedSecret}} | fl  $ss = ConvertTo-SecureString -Key ([Convert]::FromBase64String($key)) -String $encryptedSecret(New-Object System.Management.Automation.PSCredential 'SECURESTRING',$ss).GetNetworkCredential().Password

PowerShell Error Handling Behavior Debunked

Note: I am using simple error messages as an example, please reference the best practices and guidelines I outlined on when to use custom error messages.

I have been churning in my mind for the last few days all the entries in the 2013 Scripting Games and how they handle errors, or lack thereof.

I am coming to the conclusion through some testing that the simple fact of seeing a try..catch or throw statements does not mean there is proper error handling.

I've been testing several variations and forms of error handling, so lets start with the basics.
function Test-WriteError {      [CmdletBinding()] param()  "Test-WriteError::ErrorActionPreference = $ErrorActionPreference"Move-Item -Path 'C:\Does\Not\Exists.log' -Destination 'C:\No\Where'"Test-WriteError::End"}   Test-WriteError::ErrorActionPreference = Continue
Move-Item : Cannot find path 'C:\Does\Not\Exists.log' because it does not exist.
At line:6 char:5
+     Move-Item -Path 'C:\Does\N…