Private/UserLookupHelpers.ps1
|
function Get-NSPADForestDomainInfo { # Read every domain NC in the selected forest, excluding external references, application # partitions and pre-created (not yet active) domains. No GC partial attribute set is used. param([Parameter(Mandatory)][string]$Server, [int]$PageSize = 500) $seed = Get-NSPADDomainInfo -Server $Server if (-not $seed.ConfigurationDN) { throw 'The seed domain has no ConfigurationDN; forest discovery cannot continue.' } $refs = @(Read-NSPADLdap -Server $seed.Server -SearchBase "CN=Partitions,$($seed.ConfigurationDN)" -Scope OneLevel -Filter '(&(objectClass=crossRef)(systemFlags:1.2.840.113556.1.4.803:=3)(!(enabled=FALSE)))' -Property nCName,dnsRoot -PageSize $PageSize) if (-not $refs.Count) { throw 'No forest domain crossRefs are visible; refusing an empty forest inventory.' } $domains = @{} foreach ($ref in $refs) { $dn = [string]$ref['ncname'] $dns = [string]$ref['dnsroot'] if (-not $dn -or -not $dns) { throw 'A forest domain crossRef is missing nCName or dnsRoot.' } if ($domains.ContainsKey($dn)) { throw 'Multiple forest domain crossRefs have the same naming context.' } $dc = Find-NSPADDomainController -DomainName $dns $domain = Get-NSPADDomainInfo -Server $dc if ($domain.DistinguishedName -ne $dn -or $domain.DNSRoot -ne $dns -or $domain.ConfigurationDN -ne $seed.ConfigurationDN) { throw "Forest domain discovery resolved a different domain or forest for $dns." } $domains[$dn] = $domain } if (-not $domains.ContainsKey([string]$seed.DistinguishedName)) { throw 'The seed domain is absent from forest discovery.' } # Keep discovery order for predictable inventory output. foreach ($ref in $refs) { $domains[[string]$ref['ncname']] } } function ConvertTo-NSPADUser { param([Parameter(Mandatory)][hashtable]$Entry, [Parameter(Mandatory)]$DomainInfo) foreach ($required in 'distinguishedname', 'objectguid', 'objectsid', 'useraccountcontrol') { if (-not $Entry.ContainsKey($required) -or $null -eq $Entry[$required]) { throw "LDAP user result is missing $required; identity and enabled state must be readable." } } [pscustomobject]@{ PSTypeName = 'NSP.ActiveDirectory.User' DistinguishedName = [string]$Entry['distinguishedname'] SamAccountName = [string]$Entry['samaccountname'] UserPrincipalName = [string]$Entry['userprincipalname'] DisplayName = [string]$Entry['displayname'] GivenName = [string]$Entry['givenname'] Surname = [string]$Entry['sn'] Mail = [string]$Entry['mail'] ProxyAddresses = [string[]]@($Entry['proxyaddresses'] | Where-Object { $null -ne $_ }) ObjectGUID = [guid]::new([byte[]]$Entry['objectguid']) ConsistencyGuidBytes = if ($Entry['ms-ds-consistencyguid']) { , [byte[]]$Entry['ms-ds-consistencyguid'] } else { $null } ObjectSID = [Security.Principal.SecurityIdentifier]::new([byte[]]$Entry['objectsid'], 0).Value Enabled = [bool](-not ([int]$Entry['useraccountcontrol'] -band 2)) DomainDNSRoot = [string]$DomainInfo.DNSRoot Server = [string]$DomainInfo.Server } } |