functions/schemaLdif/Test-FMSchemaLdif.ps1
function Test-FMSchemaLdif { <# .SYNOPSIS Tests whether the configured ldif-file-based schema extension has been applied. .DESCRIPTION Tests whether the configured ldif-file-based schema extension has been applied. .PARAMETER Server The server / domain to work with. .PARAMETER Credential The credentials to use for this operation. .PARAMETER EnableException This parameters disables user-friendly warnings and enables the throwing of exceptions. This is less user friendly, but allows catching exceptions in calling scripts. .EXAMPLE PS C:\> Test-FMSchemaLdif Checks the current forest against all configured schema extension files #> [CmdletBinding()] Param ( [PSFComputer] $Server, [PSCredential] $Credential, [switch] $EnableException ) begin { $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential $parameters['Debug'] = $false Assert-ADConnection @parameters -Cmdlet $PSCmdlet Invoke-Callback @parameters -Cmdlet $PSCmdlet Assert-Configuration -Type SchemaLdif -Cmdlet $PSCmdlet try { $rootDSE = Get-ADRootDSE @parameters -ErrorAction Stop $forest = Get-ADForest @parameters -ErrorAction Stop } catch { Stop-PSFFunction -String 'Test-FMSchemaLdif.Connect.Failed' -StringValues $Server -ErrorRecord $_ -EnableException $EnableException -Exception $_.Exception.GetBaseException() return } $parameters["Server"] = $forest.SchemaMaster } process { $ldifMapping = ConvertTo-SchemaLdifPhase -LdifData (Get-FMSchemaLdif) $ldifSorted = Get-FMSchemaLdif | Sort-Object Weight $changes = @{ } $missingEntities = @() foreach ($ldifFile in $ldifSorted) { $changes[$ldifFile.Name] = @() } foreach ($distinguishedName in $ldifMapping.Keys) { $hasDefinedState = $ldifMapping[$distinguishedName].Values.State.Count -gt 0 $attributeName = '{0},{1}' -f $distinguishedName, $rootDSE.schemaNamingContext #region Retrieve AD Object ($adObject) try { $adObject = Get-ADObject @parameters -Identity $attributeName -ErrorAction Stop -Properties * } catch { if ($hasDefinedState) { foreach ($file in $ldifMapping[$distinguishedName].Keys) { $changes[$file] += [PSCustomObject]@{ DN = $distinguishedName Property = '<FailsToExist>' File = $file Setting = $ldifMapping[$distinguishedName][$file] ADObject = $null ValueS = $null ValueA = $null } } } else { if ($distinguishedName -notin ($ldifSorted.MissingObjectExemption | Write-Output)) { Write-PSFMessage -Level Warning -String 'Test-FMSchemaLdif.Missing.SchemaItem' -StringValues $attributeName -Tag 'panic' $missingEntities += $attributeName } } continue } #endregion Retrieve AD Object ($adObject) #region Compare configured with real state ($offStateLdifName) $offStateLdif = foreach ($ldifFile in $ldifSorted) { # Skip files that do not yet contain the taret object if (-not $ldifMapping[$distinguishedName][$ldifFile.Name]) { continue } $definedState = $ldifMapping[$distinguishedName][$ldifFile.Name] if ($definedState.State.Count -gt 0) { foreach ($propertyName in $definedState.State.Keys) { if (Compare-SchemaProperty -Setting $definedState.State -ADObject $adObject -PropertyName $propertyName -RootDSE $rootDSE) { [PSCustomObject]@{ DN = $distinguishedName Property = $propertyName File = $ldifFile.Name Setting = $definedState ADObject = $adObject ValueS = $definedState.State.$propertyName ValueA = $adObject.$propertyName } } } } else { foreach ($propertyName in $definedState.Add.Keys) { if (Compare-SchemaProperty -Setting $definedState.Add -ADObject $adObject -PropertyName $propertyName -RootDSE $rootDSE -Add) { [PSCustomObject]@{ DN = $distinguishedName Property = $propertyName File = $ldifFile.Name Setting = $definedState ADObject = $adObject ValueS = $definedState.Add.$propertyName ValueA = $adObject.$propertyName } } } foreach ($propertyName in $definedState.Replace.Keys) { if (Compare-SchemaProperty -Setting $definedState.Replace -ADObject $adObject -PropertyName $propertyName -RootDSE $rootDSE) { [PSCustomObject]@{ DN = $distinguishedName Property = $propertyName File = $ldifFile.Name Setting = $definedState ADObject = $adObject ValueS = $definedState.Replace.$propertyName ValueA = $adObject.$propertyName } } } } } #endregion Compare configured with real state ($offStateLdifName) $applicableLdif = $ldifSorted | Where-Object Name -in $ldifMapping[$distinguishedName].Keys $lastAppliedItem = $applicableLdif | Where-Object Name -notin $offStateLdif.File | Sort-Object Weight -Descending | Select-Object -First 1 foreach ($ldifFile in $applicableLdif) { if ($ldifFile.Weight -lt $lastAppliedItem.Weight) { continue } if ($lastAppliedItem.Name -eq $ldifFile.Name) { continue } foreach ($entry in $offStateLdif) { if ($entry.File -ne $ldifFile.Name) { continue } $changes[$ldifFile.Name] += $entry } } } $ldifResult = foreach ($schemaName in $changes.Keys) { if (-not $changes[$schemaName]) { continue } [PSCustomObject]@{ PSTypeName = 'ForestManagement.SchemaLdif.TestResult' Type = 'InEqual' ObjectType = 'SchemaLdif' Identity = $schemaName Changed = $changes[$schemaName] Server = $forest.SchemaMaster DeltaCount = $changes[$schemaName].Count ADObject = $null Configuration = ($ldifSorted | Where-Object Name -eq $schemaName) } } $ldifResult | Sort-Object { $_.Configuration.Weight } } } |