As soon as you have installed FIM you start configuring it according to your application design, which is based upon the data model and the usage scenarios. In case of the FIM Portal you configure it with configuration objects (MPRs, SETs, Workflows, Mail Templates, etc.) that in the end will be the technical components that give you the desired logic to do whatever you need it to do. At least I hope so!
–
During the usage of the FIM Portal, stuff changes because requirements change and logic change. Because of that objects are added and changed to accommodate the new requirements and therefore the required logic. BUT….. where’s the part about deleting unused objects, in other words CLEAN UP! By default there is nothing in FIM that will tell you if objects are not used. Is it impossible to get that information? No, but you need to do it yourself! I want to keep my FIM Portal configuration clean, therefore I have created the following PowerShell script to help me with that. And I do hope it helps you too!
# Jorge de Almeida Pinto [MVP-DS] # https://jorgequestforknowledge.wordpress.com/ # # +++ Finding UnUsed Objects In The FIM Portal +++ Param ( [string] $URI = "http://localhost:5725/resourcemanagementservice", [parameter(Mandatory=$true)] [string] $objectType ) # Clear The Screen Clear-Host # Import The FIM 2010 (R2) Snap-In If Available $SnapIn = "FIMAutomation" If(@(Get-PSSnapin | Where-Object {$_.Name -eq $SnapIn} ).count -eq 0) { If(@(Get-PSSnapin -Registered | Where-Object {$_.Name -eq $SnapIn} ).count -ne 0) { Add-PSSnapin $SnapIn Write-Host "" Write-Host "Snap-In '$SnapIn' Has Been Loaded..." -ForeGroundColor Green Write-Host "Continuing Script..." -ForeGroundColor Green Write-Host "" } Else { Write-Host "" Write-Host "Snap-In '$SnapIn' Is NOT Available To Load..." -ForeGroundColor Red Write-Host "Aborting Script..." -ForeGroundColor Red Write-Host "" Exit } } Else { Write-Host "" Write-Host "Snap-In '$SnapIn' Has Already Been Loaded..." -ForeGroundColor Green Write-Host "Continuing Script..." -ForeGroundColor Green Write-Host "" } # Convert a FIM ExportObject to a PowerShell PSObject # http://www.identitytrench.com/2011/07/convert-fim-exportobject-to-powershell.html Function Convert-FimExportToPSObject { Param ( [parameter(Mandatory=$true, ValueFromPipeline = $true)] [Microsoft.ResourceManagement.Automation.ObjectModel.ExportObject] $ExportObject ) Process { $psObject = New-Object PSObject $ExportObject.ResourceManagementObject.ResourceManagementAttributes | ForEach-Object { if ($_.Value -ne $null) { $value = $_.Value } elseif($_.Values -ne $null) { $value = $_.Values } else { $value = $null } $psObject | Add-Member -MemberType NoteProperty -Name $_.AttributeName -Value $value } Write-Output $psObject } } # Current Folder $currentFolder = (Get-Location).Path # Searching For Unused SETs # SETs Can Be Used In: # * MPRs # * Referenced By Other SETs # * Referenced By Search Scopes # * Referenced By RCDCs If ($objectType.ToUpper() -eq "SET") { Write-Host "" Write-Host "+++ CHECKING USAGE OF SETS +++" -ForeGroundColor Cyan Write-Host "" # Files $listOfSETsUsed = "List-Of-Sets-Used.txt" $listOfSETsUnUsed = "List-Of-Sets-UnUsed.txt" # Check Current Files If (Test-Path $($currentFolder + "\" + $listOfSETsUsed)) { Remove-Item $($currentFolder + "\" + $listOfSETsUsed) -Force } If (Test-Path $($currentFolder + "\" + $listOfSETsUnUsed)) { Remove-Item $($currentFolder + "\" + $listOfSETsUnUsed) -Force } # Get All The SETs $SETsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/Set" $SETsInFIMPSObject = $SETsInFIM | Convert-FimExportToPSObject # Get All The MPRs $MPRsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/ManagementPolicyRule" $MPRsInFIMPSObject = $MPRsInFIM | Convert-FimExportToPSObject # Get All The SearchScopes $SearchScopesInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/SearchScopeConfiguration" $SearchScopesInFIMPSObject = $SearchScopesInFIM | Convert-FimExportToPSObject # Get All The RCDCs $RCDCsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/ObjectVisualizationConfiguration" $RCDCsInFIMPSObject = $RCDCsInFIM | Convert-FimExportToPSObject # For Each SET Check If It Is Used Somewhere ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { $setDisplayName = $SETInFIMPSObject.DisplayName $setObjectID = $SETInFIMPSObject.ObjectID $setIsUsed = $false # For Each SET Check If It Is Used In Some MPR If (!$setIsUsed) { ForEach ($MPRInFIMPSObject In $MPRsInFIMPSObject) { If ($MPRInFIMPSObject.PrincipalSet -eq $setObjectID -Or $MPRInFIMPSObject.ResourceCurrentSet -eq $setObjectID -Or $MPRInFIMPSObject.ResourceFinalSet -eq $setObjectID) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # For Each SET Check If It Is Used In Some Other SET If (!$setIsUsed) { ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { If ($SETInFIMPSObject.Filter -match $($setObjectID.TrimStart("urn:uuid:")) -Or $SETInFIMPSObject.Filter -match $setDisplayName) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # For Each SET Check If It Is Used In Some Workflow If (!$setIsUsed) { ForEach ($SearchScopeInFIMPSObject In $SearchScopesInFIMPSObject) { If ($SearchScopeInFIMPSObject.SearchScope -match $($setObjectID.TrimStart("urn:uuid:")) -Or $SearchScopeInFIMPSObject.SearchScope -match $setDisplayName) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # For Each SET Check If It Is Used In Some RCDC If (!$setIsUsed) { ForEach ($RCDCInFIMPSObject In $RCDCsInFIMPSObject) { If ($RCDCInFIMPSObject.ConfigurationData -match $($setObjectID.TrimStart("urn:uuid:")) -Or $RCDCInFIMPSObject.ConfigurationData -match $setDisplayName) { # Object Is Used $setIsUsed = $true Break } Else { # Object Is NOT Used $setIsUsed = $false } } } # If The SET Is Used If ($setIsUsed) { Write-Host "In Use: '$setDisplayName'..." -ForeGroundColor Green Add-Content $($currentFolder + "\" + $listOfSETsUsed) $setDisplayName } # If The SET Is UnUsed If (!$setIsUsed) { Write-Host "Not In Use: '$setDisplayName'..." -ForeGroundColor Red Add-Content $($currentFolder + "\" + $listOfSETsUnUsed) $setDisplayName } } } # Searching For Unused WorkFlows # WorkFlows Can Be Used In: # * MPRs # * Referenced By SETs If ($objectType.ToUpper() -eq "Workflow") { Write-Host "" Write-Host "+++ CHECKING USAGE OF WORKFLOWS +++" -ForeGroundColor Cyan Write-Host "" # Files $listOfWorkflowsUsed = "List-Of-Workflows-Used.txt" $listOfWorkflowsUnUsed = "List-Of-Workflows-UnUsed.txt" # Check Current Files If (Test-Path $($currentFolder + "\" + $listOfWorkflowsUsed)) { Remove-Item $($currentFolder + "\" + $listOfWorkflowsUsed) -Force } If (Test-Path $($currentFolder + "\" + $listOfWorkflowsUnUsed)) { Remove-Item $($currentFolder + "\" + $listOfWorkflowsUnUsed) -Force } # Get All The Workflows $WorkflowsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/WorkflowDefinition" $WorkflowsInFIMPSObject = $WorkflowsInFIM | Convert-FimExportToPSObject # Get All The MPRs $MPRsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/ManagementPolicyRule" $MPRsInFIMPSObject = $MPRsInFIM | Convert-FimExportToPSObject # Get All The SETs $SETsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/Set" $SETsInFIMPSObject = $SETsInFIM | Convert-FimExportToPSObject # For Each Workflow Check If It Is Used Somewhere ForEach ($WorkflowInFIMPSObject In $WorkflowsInFIMPSObject) { $workflowDisplayName = $WorkflowInFIMPSObject.DisplayName $workflowObjectID = $WorkflowInFIMPSObject.ObjectID $workflowIsUsed = $false # For Each Workflow Check If It Is Used In Some MPR If (!$workflowIsUsed) { ForEach ($MPRInFIMPSObject In $MPRsInFIMPSObject) { If ($MPRInFIMPSObject.ActionWorkflowDefinition -contains $WorkflowObjectID -Or $MPRInFIMPSObject.AuthenticationWorkflowDefinition -contains $setObjectID -Or $MPRInFIMPSObject.AuthorizationWorkflowDefinition -contains $WorkflowObjectID) { # Object Is Used $workflowIsUsed = $true Break } Else { # Object Is NOT Used $workflowIsUsed = $false } } } # For Each Workflow Check If It Is Used In Some SET If (!$workflowIsUsed) { ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { If ($SETInFIMPSObject.Filter -match $($workflowObjectID.TrimStart("urn:uuid:")) -Or $SETInFIMPSObject.Filter -match $workflowDisplayName) { # Object Is Used $workflowIsUsed = $true Break } Else { # Object Is NOT Used $workflowIsUsed = $false } } } # If The Workflow Is Used If ($workflowIsUsed) { Write-Host "In Use: '$workflowDisplayName'..." -ForeGroundColor Green Add-Content $($currentFolder + "\" + $listOfWorkflowsUsed) $workflowDisplayName } # If The Workflow Is UnUsed If (!$workflowIsUsed) { Write-Host "Not In Use: '$workflowDisplayName'..." -ForeGroundColor Red Add-Content $($currentFolder + "\" + $listOfWorkflowsUnUsed) $workflowDisplayName } } } # Searching For Unused Mail Templates # Mail Templates Can Be Used In: # * Workflows # * Referenced By SETs If ($objectType.ToUpper() -eq "MailTemplate") { Write-Host "" Write-Host "+++ CHECKING USAGE OF MAIL TEMPLATES +++" -ForeGroundColor Cyan Write-Host "" # Files $listOfMailTemplatesUsed = "List-Of-MailTemplates-Used.txt" $listOfMailTemplatesUnUsed = "List-Of-MailTemplates-UnUsed.txt" # Check Current Files If (Test-Path $($currentFolder + "\" + $listOfMailTemplatesUsed)) { Remove-Item $($currentFolder + "\" + $listOfMailTemplatesUsed) -Force } If (Test-Path $($currentFolder + "\" + $listOfMailTemplatesUnUsed)) { Remove-Item $($currentFolder + "\" + $listOfMailTemplatesUnUsed) -Force } # Get All The Mail Templates $MailTemplatesInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/EmailTemplate" $MailTemplatesInFIMPSObject = $MailTemplatesInFIM | Convert-FimExportToPSObject # Get All The Workflows $WorkflowsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/WorkflowDefinition" $WorkflowsInFIMPSObject = $WorkflowsInFIM | Convert-FimExportToPSObject # Get All The SETs $SETsInFIM = Export-FIMConfig -Uri $URI –OnlyBaseResources -CustomConfig "/Set" $SETsInFIMPSObject = $SETsInFIM | Convert-FimExportToPSObject # For Each Mail Template Check If It Is Used Somewhere ForEach ($MailTemplateInFIMPSObject In $MailTemplatesInFIMPSObject) { $mailTemplateDisplayName = $MailTemplateInFIMPSObject.DisplayName $mailTemplateObjectID = $MailTemplateInFIMPSObject.ObjectID $mailTemplateIsUsed = $false # For Each Mail Template Check If It Is Used In Some Workflow If (!$mailTemplateIsUsed) { ForEach ($WorkflowInFIMPSObject In $WorkflowsInFIMPSObject) { If ($WorkflowInFIMPSObject.XOML -match $($mailTemplateObjectID.TrimStart("urn:uuid:"))) { # Object Is Used $mailTemplateIsUsed = $true Break } Else { # Object Is NOT Used $mailTemplateIsUsed = $false } } } # For Each Mail Template Check If It Is Used In Some SET If (!$mailTemplateIsUsed) { ForEach ($SETInFIMPSObject In $SETsInFIMPSObject) { If ($SETInFIMPSObject.Filter -match $($mailTemplateObjectID.TrimStart("urn:uuid:")) -Or $SETInFIMPSObject.Filter -match $mailTemplateDisplayName) { # Object Is Used $mailTemplateIsUsed = $true Break } Else { # Object Is NOT Used $mailTemplateIsUsed = $false } } } # If The Mail Template Is Used If ($mailTemplateIsUsed) { Write-Host "In Use: '$mailTemplateDisplayName'..." -ForeGroundColor Green Add-Content $($currentFolder + "\" + $listOfMailTemplatesUsed) $mailTemplateDisplayName } # If The Mail Template Is UnUsed If (!$mailTemplateIsUsed) { Write-Host "Not In Use: '$mailTemplateDisplayName'..." -ForeGroundColor Red Add-Content $($currentFolder + "\" + $listOfMailTemplatesUnUsed) $mailTemplateDisplayName } } }
–
The script supports the check for SET, Workflow and Mail Template objects. The script accepts two parameters, being -URI and -objectType. -URI is only mandatory if you are not running the script on the server with the FIM service. -objectType is always mandatory and accepts the values SET, Workflow or MailTemplate.
–
To find used and unused SETs, execute the following:
.\Finding-Unused-Objects-In-FIM-Portal.ps1 -objectType SET
–
The output can be seen below.
Figure 1: Finding Used And Unused SETS
–
To find used and unused Workflows, execute the following:
.\Finding-Unused-Objects-In-FIM-Portal.ps1 -objectType Workflow
–
The output can be seen below.
Figure 2: Finding Used And Unused Workflows
–
To find used and unused Mail Templates, execute the following:
.\Finding-Unused-Objects-In-FIM-Portal.ps1 -objectType MailTemplate
–
The output can be seen below.
Figure 3: Finding Used And Unused Mail Templates
–
In addition to the output on screen, the script will also provide the output to a text file. For each object type 2 files are created when applicable. One file contains the objects used and the other file contains the unused objects.
Figure 4: Text Files Listing The Used And Unused Objects
–
Now, the script does NOT delete anything! It just enumerates the information and presents it to you. It is now up to you to delete an object or not based upon the information presented to you. As a suggestion, I would never delete an object that by default is in the FIM Portal.
–
Cheers,
Jorge
———————————————————————————————
* This posting is provided "AS IS" with no warranties and confers no rights!
* Always evaluate/test yourself before using/implementing this!
* DISCLAIMER: https://jorgequestforknowledge.wordpress.com/disclaimer/
———————————————————————————————
############### Jorge’s Quest For Knowledge #############
######### http://JorgeQuestForKnowledge.wordpress.com/ ########
———————————————————————————————