Hello Everyone.
I am working with FIM 2010 and need some help with a script.
Most of this is from the online community as I am trying to learn as fast as I can.
If you could review the script and provide any suggestions or feedback on lines 448 through 512.
Basically the goal is to search FIM via PowerShell and XPath and search for groups that do not meet a specific length in their name. For example, any group that has a name that is 8 characters or less in length, I would like to export the:
- Owner
- Security Group Name
- UUID (URL to FIM Managed Security Group)
a. This will be concatenated (ex: iam.jones.com/identitymanagement/xx_P1 ) - Description of the Security Group
Please note that on lines…
370 #Script starts
470 #Get Owner, DisplayName and Description based on ObjectID
472 #If DisplayName is less than 8, If Owner is not null - iterate each Owner
474 #Print Owner, DisplayName, Url, Description to CSV file.
The current script is listed below:
.\Update-FIMConfiguration.ps1 -ConfigurationFile .\Update-FIMConfiguration-20140108changes.ps1
.NOTES
#>
[CmdletBinding(SupportsShouldProcess=$True)]
param(
[string]$ConfigurationFile = “.\FIM-GetGroups-Cfg.ps1”,
[string]$Uri = “http://localhost:5725”,
[string]$VerboseLogPath
)
set-psdebug -strict
#=============================================================================
# FUNCTION LISTINGS
#*=============================================================================
function CreateOutput($MyText) {
If ($VerboseLogPath -eq “”) {
Write-Output ($MyText)
} else {
Write-Output ($MyText)
Out-File -filepath $VerboseLogPath -Encoding “ASCII” -Append -inputObject $MyText
}
} #CreateOutput
function Get-FIMObjectWithComparisonResults
{
param
(
[parameter(Mandatory=$true)]
[String]
$ObjectType,
[parameter(Mandatory=$false)]
[String]
$XPathPredicate,
[parameter(Mandatory=$false)]
$SourceObjectIdentifier = [Guid]::Empty,
[parameter(Mandatory=$false)]
$TargetObjectIdentifier = [Guid]::Empty,
[parameter(Mandatory=$true)]
[ValidateScript({$_ -is [Hashtable]})]
$KeyValuePair,
[parameter(Mandatory=$false)]
[ValidateScript({$_ -is [Microsoft.ResourceManagement.Automation.ObjectModel.ExportObject]})]
$CachedExportObject = $null,
[parameter(Mandatory=$false)]
[Switch]
$MultiValued = $false,
[String]
$Uri = "http://localhost:5725"
)
end
{
$Results = @{}
$Results.CompareResult = $false
$Results.LogData = @()
$Results.ExportObject = $null
$importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
$XPathFilter = "/" + $ObjectType + $XPathPredicate
If ($CachedExportObject -eq $null) {
$RetrievalType = "authoritative"
$Results.ExportObject = Export-FIMConfig -Uri $Uri -OnlyBaseResources -CustomConfig $XPathFilter -ErrorAction SilentlyContinue
} else {
$RetrievalType = "cached"
$Results.ExportObject = $CachedExportObject
}
if ($Results.ExportObject -eq $null) {
Write-Error ("An object was not found with this criteria: $XPathFilter")
$Results.LogData += ("An object was not found with this criteria: $XPathFilter")
}
else {
$Results.LogData += ("Retrieved $RetrievalType object: $XPathFilter")
$AttributeName = @($KeyValuePair.Keys)[0]
$exportedKVP = $Results.ExportObject.ResourceManagementObject.ResourceManagementAttributes | Where-Object { $_.AttributeName -eq $AttributeName }
If ($MultiValued) {
If ($exportedKVP -eq $null) {
$Results.LogData += ("Current values of {0} is NULL" -f $AttributeName)
} else {
$Results.LogData += ("Current values of {0} is {1}" -f $AttributeName, [string]::Join(",", $exportedKVP.Values))
}
If ($exportedKVP -ne $null){
ForEach ($value in $exportedKVP.Values) {
If ($value -eq $KeyValuePair[$AttributeName]) {
$Results.LogData += ("This contains value {0}" -f $KeyValuePair[$AttributeName])
$Results.CompareResult = $true
} ElseIf ($value.StartsWith("urn:uuid:")) {
If ($value.Substring(9) -eq $KeyValuePair[$AttributeName]) {
$Results.LogData += ("This contains value {0}" -f $KeyValuePair[$AttributeName])
$Results.CompareResult = $true
}
}
}
}
If (-not $Results.CompareResult) {
$Results.LogData += ("This does not contain value {0}" -f $KeyValuePair[$AttributeName])
}
} else {
If ($exportedKVP -eq $null) {
$Results.LogData += ("Current value of {0} is [null]" -f $AttributeName)
If ($KeyValuePair[$AttributeName] -eq $null) {
$Results.CompareResult = $true
}
} else {
$Results.LogData += ("Current value of {0} is {1}" -f $AttributeName, $exportedKVP.Value)
If ($exportedKVP.Value -eq ($KeyValuePair[$AttributeName] -Split "`r`n" -join "`n")) {
$Results.CompareResult = $true
} ElseIf ($exportedKVP.Value.StartsWith("urn:uuid:")) {
If ($exportedKVP.Value.Substring(9) -eq $KeyValuePair[$AttributeName]) {
$Results.CompareResult = $true
}
}
}
}
}
Write-Output $Results
}
} #Get-FIMObjectWithComparisonResults
function Get-FIMObjectIDUsingXPath($ObjectType, $XPathPredicate) {
$ObjectID = $null
CreateOutput ("In FIMObjectIDXpath " +$ObjectType + ","+$XPathPredicate)
#$XPathFilter = "/" + $ObjectType + $XPathPredicate
$XPathFilter = "/Group" + $XPathPredicate
CreateOutput ("In FIMObjectIDXpath " +$XPathFilter)
$ExportResults = Export-FIMConfig -Uri $Uri -OnlyBaseResources -CustomConfig $XPathFilter -ErrorAction SilentlyContinue
if ($ExportResults -eq $null) {
Write-Error ("An object was not found with this criteria: $XPathFilter")
}
else {
$exportedKVP = $ExportResults.ResourceManagementObject.ResourceManagementAttributes | Where-Object { $_.AttributeName -eq 'ObjectID' }
$ObjectID = $exportedKVP.Value
}
$ObjectID
} #Get-FIMObjectIDUsingXPath
function Update-FIMObjectIfNecessary($ObjectType, $XPathPredicate, $KeyValuePair) {
$ReachedDesiredState = $false
[string]$Key = $KeyValuePair.Keys
If ($KeyValuePair[$Key] -ne $null) {
[string]$Value = $KeyValuePair.Values
$KeyValuePair = @{$Key=$Value.Replace(“%FORESTROOTDN%”, $ForestRootDN).Replace(“%FORESTROOTNETBIOS%”, $ForestRootNetBIOS)}
}
Do {
CreateOutput (get-date -UFormat “%Y.%m.%d.%H.%M.%S”)
$ReturnValues = Get-FIMObjectWithComparisonResults -Uri $Uri -ObjectType $ObjectType -XPathPredicate $XPathPredicate -KeyValuePair $KeyValuePair
CreateOutput ($ReturnValues.LogData)
If ($ReturnValues.CompareResult) {
$ReachedDesiredState = $true
} else {
$ObjectID = $ReturnValues.ExportObject.ResourceManagementObject.ObjectIdentifier.Replace(‘urn:uuid:’,‘’)
CreateOutput (“Updating /$ObjectType$XPathPredicate”)
CreateOutput ($KeyValuePair)
#See if we’re updating to a value or null
$AttributeName = @($KeyValuePair.Keys)[0]
If ($KeyValuePair[$AttributeName] -eq $null) {
$Change = New-FimImportChange -Uri $Uri -Operation ‘Replace’ -AttributeName $AttributeName
} else {
$Change = New-FimImportChange -Uri $Uri -Operation ‘Replace’ -AttributeName $AttributeName -AttributeValue $KeyValuePair[$AttributeName]
}
$ImportObject = New-FimImportObject -Uri $Uri -ObjectType $ObjectType -State ‘Put’ -SourceObjectIdentifier $ObjectID -TargetObjectIdentifier $ObjectID -Changes $Change -PassThru
If ($pscmdlet.ShouldProcess(“/$ObjectType$XPathPredicate”)) {
$ImportObject | Import-FIMConfig -Uri $Uri
} else {
$ReachedDesiredState = $true
}
}
} While (-not $ReachedDesiredState)
} #Update-FIMObjectIfNecessary
function Update-FIMObjectMultiValueIfNecessary($ObjectType, $XPathPredicate, $ChangeType, $KeyValuePair) {
$ReachedDesiredState = $false
[string]$Key = $KeyValuePair.Keys
If ($KeyValuePair[$Key] -ne $null) {
[string]$Value = $KeyValuePair.Values
$KeyValuePair = @{$Key=$Value.Replace(“%FORESTROOTDN%”, $ForestRootDN).Replace(“%FORESTROOTNETBIOS%”, $ForestRootNetBIOS)}
}
Do {
CreateOutput (get-date -UFormat “%Y.%m.%d.%H.%M.%S”)
$ReturnValues = Get-FIMObjectWithComparisonResults -Uri $Uri -ObjectType $ObjectType -XPathPredicate $XPathPredicate -KeyValuePair $KeyValuePair -MultiValued $true
CreateOutput ($ReturnValues.LogData)
If ($ChangeType -eq 'Add') {
$DesiredComparisionResult = $true
} else {
$DesiredComparisionResult = $false
}
If ($ReturnValues.CompareResult -eq $DesiredComparisionResult) {
$ReachedDesiredState = $true
} else {
$ObjectID = $ReturnValues.ExportObject.ResourceManagementObject.ObjectIdentifier.Replace('urn:uuid:','')
CreateOutput ("Updating /$ObjectType$XPathPredicate $ChangeType")
CreateOutput ($KeyValuePair)
$AttributeName = @($KeyValuePair.Keys)[0]
$Change = New-FimImportChange -Uri $Uri -Operation $ChangeType -AttributeName $AttributeName -AttributeValue $KeyValuePair[$AttributeName]
$ImportObject = New-FimImportObject -Uri $Uri -ObjectType $ObjectType -State 'Put' -SourceObjectIdentifier $ObjectID -TargetObjectIdentifier $ObjectID -Changes $Change -PassThru
If ($pscmdlet.ShouldProcess("/$ObjectType$XPathPredicate")) {
$ImportObject | Import-FIMConfig -Uri $Uri
} else {
$ReachedDesiredState = $true
}
}
} While (-not $ReachedDesiredState)
} #Update-FIMObjectMultiValueIfNecessary
function Add-FIMObjectIfNecessary($ObjectType, $XPathPredicate, $CreationCommand) {
$ReachedDesiredState = $false
Do {
CreateOutput (get-date -UFormat “%Y.%m.%d.%H.%M.%S”)
$ReturnValues = Get-FIMObjectWithComparisonResults -Uri $Uri -ObjectType $ObjectType -XPathPredicate $XPathPredicate -KeyValuePair @{‘TestingForCreation’=‘IgnoreAttributeFailure’}
CreateOutput ($ReturnValues.LogData | Where-Object { $_ -ne ‘Current value of TestingForCreation is [null]’ })
If ($ReturnValues.ExportObject -ne $null) {
$ReachedDesiredState = $true
} else {
CreateOutput (“Creating /$ObjectType$XPathPredicate as $CreationCommand”)
If ($pscmdlet.ShouldProcess(“/$ObjectType$XPathPredicate”)) {
Invoke-Expression -Command $CreationCommand
} else {
$ReachedDesiredState = $true
}
}
} While (-not $ReachedDesiredState)
} #Add-FIMObjectIfNecessary
function Remove-FIMObjectIfNecessary($ObjectType, $XPathPredicate) {
$ReachedDesiredState = $false
Do {
CreateOutput (get-date -UFormat “%Y.%m.%d.%H.%M.%S”)
$ReturnValues = Get-FIMObjectWithComparisonResults -Uri $Uri -ObjectType $ObjectType -XPathPredicate $XPathPredicate -KeyValuePair @{‘TestingForCreation’=‘IgnoreAttributeFailure’}
CreateOutput ($ReturnValues.LogData | Where-Object { $_ -ne ‘Current value of TestingForCreation is [null]’ })
If ($ReturnValues.ExportObject -eq $null) {
$ReachedDesiredState = $true
} else {
CreateOutput (“Deleting /$ObjectType$XPathPredicate”)
$AttributeName = ($XPathPredicate.Split(“=”))[0].Replace(“[”, “”)
$AttributeValue = ($XPathPredicate.Split(“=”))[1].Replace(“]”, “”).Replace(“'”,“”)
If ($pscmdlet.ShouldProcess(“/$ObjectType$XPathPredicate”)) {
$deleteRequest = New-FimImportObject -Uri $Uri -ObjectType $ObjectType -State Delete -AnchorPairs @{$AttributeName=$AttributeValue} -PassThru
$deleteRequest | Import-FIMConfig
} else {
$ReachedDesiredState = $true
}
}
} While (-not $ReachedDesiredState)
} #Remove-FIMObjectIfNecessary
function Test-VariableDefinedAndNotNull ($MyVar) {
If (Test-Path variable:$MyVar) {
If ($MyVar -eq $null) {
$false
} else {
$true
}
} else {
$false
}
}
#=============================================================================
# SCRIPT BODY
#*=============================================================================
$ScriptVersion = “Date - Name”
$ThisScript = Get-Item $MyInvocation.MyCommand.Definition
If ($VerboseLogPath.Contains(“?”)) {
get-help $MyInvocation.MyCommand.Definition -detailed
exit
}
#The add-pssnapin in FimPowerShellModule.psm1 breaks the FIMAutomation cmdlets.
#The snapin MUST be added BEFORE the module is imported
if(-not (get-pssnapin | Where-Object {$.Name -eq ‘FIMAutomation’})) {
add-pssnapin FIMAutomation
}
if((get-pssnapin | Where-Object {$.Name -eq ‘FIMAutomation’})) {
}
$Imported = $false
If (-not $Imported) {
CreateOutput ("In Powrshell import module before " +$Imported)
Import-Module FimPowerShellModule -ErrorAction SilentlyContinue
If ((get-module | where-object { $_.Name -eq 'FimPowerShellModule' }) -ne $null) {
$Imported=$true
}
}
If (-not $Imported) {
Import-Module .\FimPowerShellModule.psm1 -ErrorAction SilentlyContinue
If ((get-module | where-object { $_.Name -eq 'FimPowerShellModule' }) -ne $null) {
$Imported=$true
}
}
If (-not $Imported) {
Import-Module FimPowerShellModule
Import-Module .\FimPowerShellModule.psm1
Write-Error "Module Import Failed"
exit 1
}
#Establish our replacement variable values
#%FORESTROOTDN% = $ForestRootDN
#%FORESTROOTNETBIOS% = $ForestRootNetBIOS
$RootDSE = ADSI
$ForestRootDN = $RootDSE.rootDomainNamingContext
$SearchConfigForObject = New-Object DirectoryServices.DirectorySearcher
$SearchConfigForObject.SearchRoot = “LDAP://” + $RootDSE.configurationNamingContext
$SearchConfigForObject.filter = “(&(objectclass=crossref)(ncname=$ForestRootDN))”
$SearchConfigForObject.PropertiesToLoad.Add(“netbiosname”) | out-Null
$CrossRef = $SearchConfigForObject.FindOne()
If ($CrossRef -ne $null) {
$ForestRootNetBIOS = $CrossRef.Properties.netbiosname.item(0)
}
#Read in and execute external configuration
If (-not (Test-Path -Path $ConfigurationFile -PathType Leaf)) {
exit 1
}
Load configuration file - comment out on 4/2/15
#. $ConfigurationFile
$GroupName= ‘SampleGroupName’
$ObjectType = ‘Group’
$XPathPredicate = “”
$XPathPredicate = “[DisplayName=‘$GroupName’]”
#$XPathPredicate = “[DisplayName.Length -eq 8]”
#ak-$XPathPredicate = “[(Type = ‘Security’) and ((DisplayName.Length 8) or (AccountName.Length -le 8))]”
#ak-$XPathPredicate = "[(Type = ‘Security’) and ((string-length(DisplayName()) < 8) or (string-length(AccountName()) < 8))]"
#$XPathPredicate = "[(Type = 'Security') and ((string-length(DisplayName()) <= 8) or (string-length(AccountName()) <= 8))]"
$AllGroupObjects = Get-FIMObjectIDUsingXPath $ObjectType $XPathPredicate
foreach ($GroupObject in $AllGroupObjects)
{
If ($GroupObject.XPathFilter.Length < 8)
{
{$objItem = $GroupObject.Properties
"Name: " + $objItem.name
"Title: " + $objItem.jobTitle
"Description: " + $objItem.description
"URI: " + $objItem.Uri
If($objItem.name not eq $null)
{
If ($FileExists -eq $True) {Write-Output $objItem "True"}
Else {Write-Output $objItem "False"}
| export-csv C:\scripts\output.csv -Append
}
else {} #else for the objItem.name not being null
}
}
else {} #else for the container being more than 8 characters
#Get Owner, DisplayName and Description based on ObjectID
#If DisplayName is less than 8, If Owner is not null - iterate each Owner
#Print Owner, DisplayName, Url, Description to CSV file.
https://powershell.org/forums/topic/ad-export-group-members-but-with-a-twist/
This will allow to you put all seven group names in and run it as a scheduled task.
It'll plop the timestamped csv file out onto a share of your choice for whoever you want to share it with.
Note: $ADUser.Manager returns a super long distinguished name so I used some crude string manipulation tricks
to get just the alias so I didn't have to do another Get-ADUser query.
$Groups = 'Group1','Group2','Group3','Group4','Group5','Group6','Group7'
$FileName = "ADGroupMem_$(Get-Date -Format "yyyyMMddmmss")"
$SavePath = "c:\ps$FileName.csv"
Foreach ($Group in $Groups){
$ADGroup = Get-ADGroup -Identity $Group
$ADGroupMem = Get-ADGroupMember -Identity $ADGroup
ForEach ($Member in $ADGroupMem){
$ADUser = $Member | Get-ADUser -Properties SamAccountName,Department,Title,Manager
if ($ADUser.Manager){
#$ManagerName = ($ADUser.Manager).Split(",") | Select-Object -Index 0 | ForEach-Object {$_ -replace "CN=",""}
$ManagerName = Get-ADUser -LDAPFilter "(DistinguishedName=$($ADUser.Manager))" -Properties DisplayName | Select-Object -Expand DisplayName
} else {
$ManagerName = "None listed"
}
[PSCustomObject]@{
GroupName = $ADGroup.Name
SAMAccountName = $ADUser.SamAccountName
Department = $ADUser.Department
Title = $ADUser.Title
Manager = $ManagerName
} | Export-Csv -Path $SavePath -Append -NoTypeInformation
}
}
}
#Boolean Expressions listed below https://msdn.microsoft.com/en-us/library/ms256081(v=vs.90).aspx
#< * Less than
* Greater than
#<= * Greater than or equal
#//*[string-length(DisplayName()) < 8]
#XPath Tutorial
#Get-FimObjectID -ObjectType 'Group' -Uri $Uri -AttributeName -AttributeName 'DisplayName' -AttributeValue 'SampleGroupName' -AttributeName 'Owner' -AttributeValue '