Reporting on FIM SSPR

If you have installed FIM Self Service Password Reset (SSPR), chances are that management will want to know what sort of return they are getting on their investment. One way to determine ROI on FIM SSPR is to look at the number of phone calls the Help Desk receives for password resets before and after its deployment. However, management will likely want more concrete evidence that it’s the deployment of SSPR that is lowering the number of calls. In this blog posting I will show you how to report on SSPR use without the need for the full scale FIM Reporting feature.

This is a scripted solution that utilizes the FIMAutomation snap-in which is installed automatically when you install the FIM Service. Therefore, you must run the script from the server that hosts the FIM service or install the snap-in on another machine. If you would like to run from another machine, see the following link http://social.technet.microsoft.com/wiki/contents/articles/14550.how-to-run-fim-2010-powershell-cmdlets-on-non-fim-machine.aspx.

In this scenario, management has asked the following questions:

  1. How frequently is SSPR being used for password resets and password unlocks? Note: The ability to unlock is a feature that became available with MIM 2016.
  2. How many users have registered for SSPR?
  3. How many users have not registered for SSPR?
  4. Names of users not registered and any other relevant information about those users.

I’ve developed  a solution that will answer those questions by doing the following:

  • Send a weekly email to management to include the following:
    • An embedded HTML table that includes a list of users who have not registered for SSPR to include the user’s first name, last name, account name, employee ID, account type, manager, and email address
    • The number of users who have registered for SSPR
    • The number of users who have NOT registered for SSPR
    • The number of successful password resets/account unlocks in the past 30 days
    • An attachment that contains the same data found in the embedded table to allow management to sort and filter on the data
    • An attachment that contains all previous reported number of successful password reset/unlocks in the past 30 days. Each report as a separate line and date in the file.
  • Saves all data to a file directory of choice.

Here is a screen shot of the e-mail output:

Reporting on FIM SSPR Screenshot: FIM SSPR Email Report
FIM SSPR Email Report

Here is a screen shot of the attachment that contains all previous reports on the number of successful password reset or account unlocks in the past 30 days.

Reporting on FIM SSPR Screenshot: User Count CSV  Report
FIM SSPR User Count CSV  Report

Here is a screen shot of the attachment that lists the users who have NOT registered for SSPR.

Reporting on FIM SSPR Screenshot: User Not Registered CSV Report
FIM SSPR User Not Registered CSV Report

Now that we have seen what we can accomplish using the FIMAutomation Snap-in, we’ll step through the script that makes up the solution:

Set FIM Resource Management Service Address

First we set the FIM Resource Management Service address. The FIM cmdlet that we will be utilizing requires this “URI” parameter in order to connect to the FIM Service. Note:  If you are running the script remotely, you will need to use the server name in place of “localhost”.

set-variable -name URI -value "http://localhost:5725/resourcemanagementservice" -option constant

Add FIMAutomation PSSnapin

Next, we add the FIMAutomation PSSnapin (if not already loaded):

If(@(Get-PSSnapin | Where-Object {$_.Name -eq "FIMAutomation"} ).count -eq 0) {Add-PSSnapin FIMAutomation}

Get Object ID for the “Password Reset AuthN Workflow” Work Flow

The FIM Cmdlet that we will be utilizing requires that we use the FIM ObjectID when referencing objects we will be querying. We get the object IDs by searching on the FIM Display Name. The reason we need the object ID for the “Password Reset AuthN Workflow” is because we will be filtering for users who have this workflow associated with the “AuthN Workflow Registered” attribute on their user account. If the work flow is present (as in the screen shot below) it indicates that they have registered for SSPR.

Reporting on FIM SSPR Screenshot: AuthN Wofklow Required User Attribute
AuthN Wofklow Required User Attribute

The code to get the ObjectID for the “Password Reset” AuthN Workflow’ is below:

# Get Object ID for 'Password Reset AuthN Workflow' WF
$AuthN_Filter = "/WorkflowDefinition[DisplayName='Password Reset AuthN Workflow']" 
$AuthN_Export = export-fimconfig -uri $URI –onlyBaseResources -customconfig ($AuthN_Filter) -ErrorVariable Err -ErrorAction SilentlyContinue 
$AuthN_ObjectID = (($AuthN_Export.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "ObjectID"}).value).split(":")[2]

Get Object ID for the “_Standard Users” Set

We don’t want to report on all user objects in the portal because it will likely include user objects that would not register for SSPR like service accounts, administrator accounts, or shared mailboxes. Management will only want to know about accounts that should be registering for SSPR. So in the code below we are finding the ObjectID for our custom set that contains only standard user accounts.

# Get Object ID for '_Standard Users' Set
$StandardUser_Filter = "/Set[DisplayName='_Standard Users']" 
$StandardUser_Export = export-fimconfig -uri $URI –onlyBaseResources -customconfig ($StandardUser_Filter) -ErrorVariable Err -ErrorAction SilentlyContinue 
$StandardUser_ObjectID = (($StandardUser_Export.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "ObjectID"}).value).split(":")[2]

Get Object ID for the “Anonymous users can reset their password” MPR

In order to count the number of users who have successfully reset or unlocked their accounts using SSPR, we will need to query the FIM Search History for requests where the applied policy rule is the “Anonymous users can reset their password” MPR. This is the MPR that gets applied only when a user attempts to reset their password or unlock their user account using SSPR.

# Get Object ID for 'Anonymous users can reset their password' MPR
$ResetPasswordMPR_Filter = "/*[DisplayName='Anonymous users can reset their password']" 
$ResetPasswordMPR_Export = export-fimconfig -uri $URI –onlyBaseResources -customconfig ($ResetPasswordMPR_Filter) -ErrorVariable Err -ErrorAction SilentlyContinue 
$ResetPasswordMPR_ObjectID = (($ResetPasswordMPR_Export.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "ObjectID"}).value).split(":")[2]

Establish Filters for Objects that will be Queried

Next we establish filters for our PowerShell query:

$RegisteredUsers_Filter = "/Person[AuthNWFRegistered = '$AuthN_ObjectID']"
$NotRegisteredUsers_Filter = "/Person[(ObjectID = /Set[ObjectID = '$StandardUser_ObjectID']/ComputedMember) and (not(AuthNWFRegistered = '$AuthN_ObjectID'))]"
$PasswordResetRequests_Filter = "/Request[ManagementPolicy='$ResetPasswordMPR_ObjectID'and RequestStatus='Completed']"

Export FIM Config

Then we export the data from FIM:

$UsersRegistered_Export = export-fimconfig -uri $URI –onlyBaseResources -customconfig ($RegisteredUsers_Filter) -ErrorVariable Err -ErrorAction SilentlyContinue
$UsersNotRegistered_Export = export-fimconfig -uri $URI –onlyBaseResources -customconfig ($NotRegisteredUsers_Filter) -ErrorVariable Err -ErrorAction SilentlyContinue 
$PasswordResetRequests_Export = export-fimconfig -uri $URI –onlyBaseResources -customconfig ($PasswordResetRequests_Filter) -ErrorVariable Err -ErrorAction SilentlyContinue

Build Array

Then we build an array which is essentially a table in PowerShell which will contain information about the users that we exported:

# Build a table of users containing Display Name, Account Name, and Account Type properties for users who have NOT registered for SSPR
[array]$UsersNotRegistered = $Null 
foreach($Object in $UsersNotRegistered_Export) 
{
 $ResetPassNotRegistered = New-Object PSObject
 $UserDisplayName = (($Object.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "DisplayName"}).Value)
 $UserAccountName = (($Object.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "AccountName"}).Value)
 $UserAccountType = (($Object.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "AccountType"}).Value)
 $UserEmployeeType = (($Object.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "EmployeeType"}).Value)
 $UserDepartment = (($Object.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "Department"}).Value)
 $UserEmail = (($Object.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "Email"}).Value)
 $ResetPassNotRegistered | Add-Member NoteProperty "Display Name" $UserDisplayName
 $ResetPassNotRegistered | Add-Member NoteProperty "Account Name" $UserAccountName
 $ResetPassNotRegistered | Add-Member NoteProperty "Account Type" $UserAccountType
 $ResetPassNotRegistered | Add-Member NoteProperty "Employee Type" $UserEmployeeType
 $ResetPassNotRegistered | Add-Member NoteProperty "Department" $UserDepartment
 $ResetPassNotRegistered | Add-Member NoteProperty "Email" $UserEmail
 $UsersNotRegistered += $ResetPassNotRegistered
}

Export Users Not Registered to CSV

The code below allows us to export the list of users who have not registered for SSPR. It appends the date and time to the end of the file name so that reports are not overwritten.

#Set variables
$TodaysDate = Get-Date -uformat "%Y_%m_%d_%H_%M"
$FileNameNotRegistered = "SSPR_NotRegistered_" + $TodaysDate + ".csv"
$CSV_Location_UsersNotRegistered = "C:\FIM_SSPR_Reporting\Reports\" + $FileNameNotRegistered

#Export CSV
$UsersNotRegistered | export-csv -NoTypeInformation -path $CSV_Location_UsersNotRegistered

Next we export the count of users registered and NOT registered for SSPR as well as the number of successful password resets and unlocks in the last 30 days and appends the output as a row to an existing CSV file.

#Set variables
$CSV_Location_Count = "C:\FIM_SSPR_Reporting\Reports\SSPR_UserCounts.csv"

#Export CSV
new-object PSObject -Property @{ Not_Registered = $UsersNotRegistered_Export.Count ; Registered = $UsersRegistered_Export.Count ; ResetRequestsLast30Days = $PasswordResetRequests_Export.count ; Date = $TodaysDate } | export-csv $CSV_Location_Count  -NoTypeInformation -append

Email to Management

And finally, we send emails containing the information collected. We use some HTML coding to give the email a professional appearance.

#Style formatting for HTML Table
$a = "<style>"
$a = $a + "BODY{background-color:#F5F5F5}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: #004987;border-collapse: collapse;width:100%;}"
$a = $a + "TH{border-width: 2px;padding: 10px;border-style: solid;border-color: #FFFFFF;background-color:#004987;font-size:large;color:#FFFFFF}"
$a = $a + "TD{border-width: 2px;padding: 10px;border-style: solid;border-color: #FFFFFF;background-color:#B0C4DE;}"
$a = $a + "</style>"

 

#Set variables
$SMTP = "corpdc01.corp.local" 
$to = "bla@blah.com"
$From = "NoReply@.corp.local" 
$Subject = "FIM SSPR Report"
$DateForEmail = get-date -DisplayHint Date
$DateForEmailTrimmed = ($DateForEmail | Out-String).Trim()
$Body = "<H2>FIM SSPR Report</H2>"
$CurObjectRegisteredCount = $CurObjectRegistered.Count | out-string
$CurObjectNotRegisteredCount = $CurObjectNotRegistered.Count | out-string
$CurObjectPasswordResetRequestsCount = $CurObjectPasswordResetRequests.Count | out-string
$Pre =  "This email report contains both metric and end user data related to FIM SSPR as of " + "$DateForEmailTrimmed." + "<br/><br/>" + `
        "<b>Number of users registered for SSPR:</b> " + "$CurObjectRegisteredCount" + "<br/>" + `
        "<b>Number of users not registered for SSPR:</b> " + "$CurObjectNotRegisteredCount" + "<br/>" + `
        "<b>Number of password resets in the last 30 days:</b> " + "$CurObjectPasswordResetRequestsCount" + "<br/><br/>" + `
        "The table below lists all users who have not registered for SSPR. There are two CSV files attached to this email. One contains the same data found " + `
        "in the table below and the other contains the historical metric data for trend analysis. " + `
        "All reports are stored on the FIM Sync Server at C:\FIM_SSPR_Reporting\Reports." + "<br/><br/>" |  out-string
$BodyHTML = $UsersNotRegistered | ConvertTo-Html -Head $a -PreContent $Pre -Body $Body
$BodyString = $BodyHTML | out-string

 

#Send mail
send-MailMessage -SmtpServer $SMTP -To $To -From $From -Subject $Subject -Body $BodyString -BodyAsHtml -Attachments $CSV_Location_UsersNotRegistered, $CSV_Location_Count

Testing HTML Output

Rather than send an email to test your HTML output, you can out to a local HTML file:

$BodyString | Out-File c:\temp\out.html

Download Complete Script

You may download the complete script here: FIM SSPR Reporting Script. Remember to change the file name to .ps1. Also, the user running the script must have read properties to all objects in FIM.

 

About Matthew Brooks

Over 15 years experience in the IdAM field.

One thought on “Reporting on FIM SSPR

  1. Hi Paulo,

    Thanks for script & it is working perfectly.

    Could you please help me with script to retrieve the user who registered to FIM self service with in last 30 days.

    # Get Object ID for ‘Password Reset AuthN Workflow’ WF
    $AuthNFilter = “/WorkflowDefinition[DisplayName=’Password Reset AuthN Workflow’]”
    $AuthNExport = export-fimconfig -uri $URI –onlyBaseResources -customconfig ($AuthN_Filter) -ErrorVariable Err -ErrorAction SilentlyContinue
    $AuthNObjectID = (($AuthN_Export.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq “ObjectID”}).value).split(“:”)[2]
    Kindly Help.

    Thanks in advance.

Leave a Reply

Your email address will not be published.