Private/Get/Get-RootDSE.ps1
|
function Get-RootDSE { <# .SYNOPSIS Retrieves the RootDSE object for an Active Directory forest. .DESCRIPTION Connects to the RootDSE (Root Directory Service Entry) of the specified Active Directory forest. RootDSE contains metadata about the directory such as naming contexts, schema information, and forest capabilities. Uses module-level $script:Forest and $script:Credential variables set by Invoke-Locksmith2 via New-LDAPSearcher. .INPUTS None. This function does not accept pipeline input. .OUTPUTS System.DirectoryServices.DirectoryEntry Returns a DirectoryEntry object representing the RootDSE. .EXAMPLE Get-RootDSE Retrieves the RootDSE for the target forest using script-scope variables. .NOTES Requires script-scope variables set by Invoke-Locksmith2: - $script:Forest: Target forest FQDN - $script:Credential: AD authentication credentials The RootDSE is a special object that provides information about the directory service. The function uses New-LDAPSearcher which handles credential binding. .LINK https://learn.microsoft.com/en-us/windows/win32/adsi/rootdse #> [CmdletBinding()] param ( [string]$Forest, [System.Management.Automation.PSCredential]$Credential ) #requires -Version 5.1 # Use script-scoped variables if parameters not provided if (-not $Forest -and $script:Forest) { $Forest = $script:Forest } if (-not $Credential -and $script:Credential) { $Credential = $script:Credential } $maxRetries = 3 $attempt = 0 $connected = $false while (-not $connected -and $attempt -lt $maxRetries) { $attempt++ # Get the configuration naming context if ($Forest) { if ($Credential) { $rootDSE = New-Object DirectoryServices.DirectoryEntry( "LDAP://$Forest/RootDSE", $Credential.UserName, $Credential.GetNetworkCredential().Password ) } else { $rootDSE = [ADSI]"LDAP://$Forest/RootDSE" } $Solution = "Could not connect to Active Directory forest: $Forest. Check the value provided for -Forest and/or -Credential." } else { $rootDSE = [ADSI]"LDAP://RootDSE" $Forest = [System.Environment]::UserDomainName $Solution = 'The current user is not a member of a domain. Provide values for -Forest and -Credential.' } # Getting configNC fails silently, so we have to check this manually instead of a try/catch if (-not $rootDSE.Name) { Write-Warning "$Solution" if ($attempt -lt $maxRetries) { Write-Host "`nAuthentication failed. Please try again. (Attempt $attempt of $maxRetries)" -ForegroundColor Yellow # Prompt for corrected values $retryForest = Read-Host "Enter fully qualified domain controller/domain/forest name (or press Enter to keep '$Forest')" if ($retryForest) { $Forest = $retryForest $script:Forest = $retryForest } Write-Host "`nPowerShell credential request`nEnter your credentials." $User = Read-Host "Username in NTAccount format (DOMAIN\username)" $Password = Read-Host "Password for user $User" -AsSecureString $Credential = [System.Management.Automation.PSCredential]::New($User, $Password) $script:Credential = $Credential } else { $errorRecord = [System.Management.Automation.ErrorRecord]::new( [System.Exception]::new("$Solution Authentication failed after $maxRetries attempts."), 'ADConnectionFailed', [System.Management.Automation.ErrorCategory]::AuthenticationError, $Forest ) $PSCmdlet.WriteError($errorRecord) return } } else { $connected = $true $rootDSE } } } |