QuestADTools.psm1

<#
    ===========================================================================
     Created with: SAPIEN Technologies, Inc., PowerShell Studio 2024 v5.8.238
     Created on: 3/11/2024 7:33 PM
     Created by: Gary Cook
     Organization: Quest
     Filename: QuestADTools.psm1
    -------------------------------------------------------------------------
     Module Name: QuestADTools
    ===========================================================================
#>




function Write-HelloWorld
{
    Write-Host "Hello World"
}

function Get-DomainsinForest ($ForestName, $Credential, $TargetServer)
{
    $Domains = Get-ADForest -Identity $ForestName -Server $TargetServer -Credential $Credential
    return $Domains.Domains
}

function Get-AllDomainControllers ($DomainName,$Credential)
{
    #find first DC for domain
    $FDC = Get-ADDomainController -DomainName $DomainName -Discover 
    $allDomainControllers = Get-ADDomainController -Server $FDC -Filter * -Credential $Credential
    return $allDomainControllers
}
function Verify-DomainControllerIP ($DomainController, $IP)
{
    #test that DNS agrees with AD IP
    $DNSIP = Resolve-DnsName -Name $DomainController -Type A
    $Match = $false
    foreach ($Address in $DNSIP)
    {
        if ($Address.IPAddress -eq $IP)
        {
            $Match = $true
        }
    }
    $Result = New-Object System.Management.Automation.PSObject
    $Result | Add-Member -MemberType NoteProperty -Name Match -Value $Match
    $Result | Add-Member -MemberType NoteProperty -Name DNSIP -Value $DNSIP.IPAddress
    #test to see if Computer responds to connection on all IP addresses
    $TempResult = @()
    foreach ($Address in $DNSIP.IPAddress)
    {
        
        $IPResult = New-Object System.Management.Automation.PSObject
        $IPResult | Add-Member -MemberType NoteProperty -Name IPAddress -Value $Address
        $ConnTestPing = Test-Connection -Count 1 -computername $Address -Quiet
        $ConnTestPort = Test-NetConnection -ComputerName $Address -Port 88 -InformationLevel Quiet
        if ($ConnTestPing -eq $true)
        {
            $IPResult | Add-Member -MemberType NoteProperty -Name PingTest -Value $true
        }
        else
        {
            $IPResult | Add-Member -MemberType NoteProperty -Name PingTest -Value $false
        }
        if ($ConnTestPort -eq $true)
        {
            $IPResult | Add-Member -MemberType NoteProperty -Name PortTest -Value $true
        }
        else
        {
            $IPResult | Add-Member -MemberType NoteProperty -Name PortTest -Value $false
        }
        $TempResult += $IPResult
    }
    $Result |Add-Member -MemberType NoteProperty -Name TestResults -Value $TempResult
    
    return $Result
}

function Get-DomainControllerUpTime($DomainController, $Credential)
{
    
    
    try
    {
        Write-Host "Getting DC WMI Object"
        $W32OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $DomainController -credential $Credential | select *
        Write-Host "Converting to proper format"
        
        $timespan = [System.Management.ManagementDateTimeConverter]::ToDateTime($W32OS.LocalDateTime).ToUniversalTime() - [System.Management.ManagementDateTimeConverter]::ToDateTime($W32OS.LastBootUpTime).ToUniversalTime()
        
        [double]$uptime = "{0:N2}" -f $timespan.TotalHours
    }
    catch [exception] {
        $uptime = 'WMI Failure'
    }
    
    
    
    
    return $uptime
}

function get-userADlastlogon ($UserName, $Credential, $Domain, $DCs)
{
    Write-Host "Getting lastlogon for user $($UserName)"
    $LastLogon = 0
    foreach ($DC in $DCs)
    {
        
        Write-Host "Processing DC:$($DC.hostname)"
        #$Result = Verify-DomainControllerIP -DomainController $DC.hostname
        #foreach ($R in $Result.testresults)
        #{
            #if ($R.porttest -eq $true)
            #{
                
                #$IP = $R.IPAddress
                #Write-Host "Using IP:$($IP.ipaddress)"
                $CurrentUser = Get-ADUser -identity $UserName -Server $DC.hostname -Credential $Credential | Get-ADObject -Server $DC.hostname -properties Lastlogon -Credential $Credential
                if ($CurrentUser.lastlogon -gt $LastLogon)
                {
                    $LastLogon = $CurrentUser.lastlogon
                }
            #}
        #}
    }
    
    $LastLogonDT = [DateTime]::FromFileTime($LastLogon)
    return $LastLogonDT
}

function Export-LastLogonReport ($Domain, $Credential, [array]$Fields, $OutputFile)
{
    $DCs = get-onlinedomaincontrollers -Domain $Domain -Credential $Credential
    $IP = Resolve-DnsName -Name $DCs[0].hostname
    
    $Users = Get-ADUser -Credential $Credential -Server $IP.ipaddress -Properties $Fields -Filter *
    foreach ($User in $Users)
    {
        Write-Host "Processing user: $($User.samaccountname)"
        $LL = get-userADlastlogon -UserName $User.samaccountname -Credential $Credential -Domain $Domain -DCs $DCs
        $Users | ?{$_.samaccountname -eq $User.samaccountname}|Add-Member -MemberType NoteProperty -Name LastlogonCorrected -Value $LL -force
    }
    $Users | Export-Csv -Path $OutputFile -NoTypeInformation
}

function get-onlinedomaincontrollers ($Domain, $Credential)
{
    Write-Host "Getting Online DCs for Domain: $($Domain)"
    $DCs = Get-AllDomainControllers -DomainName $Domain -Credential $Credential
    $returnDC = @()
    
    foreach ($DC in $Dcs)
    {
        Write-Host "Checking Domain Controller $($DC.hostname)"
        $alive = $false
        $result = Verify-DomainControllerIP -DomainController $DC.hostname
        foreach ($r in $result.testresults)
        {
            if ($R.porttest -eq $true)
            {
                $alive = $true
            }
        }
        if ($alive -eq $true)
        {
            Write-Host "DC is alive and responding."
            $returnDC += $DC
        }
    }
    return $returnDC
}

Function Get-ADUserLockouts
{
    [CmdletBinding(
                   DefaultParameterSetName = 'All'
                   )]
    param (
        [Parameter(
                   ValueFromPipeline = $true,
                   ParameterSetName = 'ByUser'
                   )]
        [Microsoft.ActiveDirectory.Management.ADUser]$Identity
         ,
        [datetime]$StartTime
         ,
        [datetime]$EndTime
    )
    Begin
    {
        $filterHt = @{
            LogName = 'Security'
            ID        = 4740
        }
        if ($PSBoundParameters.ContainsKey('StartTime'))
        {
            $filterHt['StartTime'] = $StartTime
        }
        if ($PSBoundParameters.ContainsKey('EndTime'))
        {
            $filterHt['EndTime'] = $EndTime
        }
        $PDCEmulator = (Get-ADDomain).PDCEmulator
        # Query the event log just once instead of for each user if using the pipeline
        $events = Get-WinEvent -ComputerName $PDCEmulator -FilterHashtable $filterHt
    }
    Process
    {
        if ($PSCmdlet.ParameterSetName -eq 'ByUser')
        {
            $user = Get-ADUser $Identity
            # Filter the events
            $output = $events | Where-Object { $_.Properties[0].Value -eq $user.SamAccountName }
        }
        else
        {
            $output = $events
        }
        foreach ($event in $output)
        {
            [pscustomobject]@{
                UserName       = $event.Properties[0].Value
                CallerComputer = $event.Properties[1].Value
                TimeStamp       = $event.TimeCreated
            }
        }
    }
    End { }
}