Public/Get-ADLockoutSource.ps1

<#
.SYNOPSIS
Retrieves the source of the most recent Active Directory account lockout for a specified user.
 
.DESCRIPTION
The Get-ADLockoutSource function fetches the most recent lockout event for a specified user from the
domain controller's security logs. It ensures the 'ActiveDirectory' module is available by using your
Get-TempModule/Temp-SetupModule helper and then verifies with Test-ModuleVersion/Verify-ModuleVersion
before continuing.
 
.PARAMETER Username
The username of the AD account for which you want to check the lockout source.
 
.PARAMETER RequiredADModuleVersion
Optional minimum version requirement for the ActiveDirectory module. Defaults to 1.0.0.0.
 
.EXAMPLE
Get-ADLockoutSource -Username "jdoe"
This retrieves the most recent lockout event for the user "jdoe".
#>


import-module Forthencho
function Get-ADLockoutSource1 {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Username,

        [Parameter()]
        [Version]$RequiredADModuleVersion = '1.0.0'
    )

    # --- Ensure 'ActiveDirectory' module is available using your helpers ---
    $adModuleName = 'RSAT'

    # Prefer your session installer if available

    try {
            # Helpers may output $true/$false; we don't strictly depend on it here
            Get-TempModule -ModuleName 'ActiveDirectory.Toolbox' -RequiredVersion '1.0.0'
        } catch {
            Write-Verbose "Temp module setup failed: $($_.Exception.Message)"
        } else {
        Write-Verbose "No Get-TempModule/Temp-SetupModule helper found; will try direct import."
    }

    # Verify availability with your version tester (boolean OR object w/ IsCompliant)
    $tester = Get-Command -Name Test-ModuleVersion -ErrorAction SilentlyContinue
    if (-not $tester) {
        $tester = Get-Command -Name Verify-ModuleVersion -ErrorAction SilentlyContinue
    }

    $isReady = $false
    if ($tester) {
        try {
            $testResult = & $tester -ModuleName $adModuleName -RequiredVersion $RequiredADModuleVersion
            if ($testResult -is [bool]) {
                $isReady = $testResult
            } elseif ($null -ne $testResult -and $testResult.PSObject.Properties['IsCompliant']) {
                $isReady = [bool]$testResult.IsCompliant
            } else {
                # Last-resort truthiness
                $isReady = [bool]$testResult
            }
        } catch {
            Write-Verbose "Module version test failed: $($_.Exception.Message)"
            $isReady = $false
        }
    } else {
        # Fallback: try to import directly
        try {
            Import-Module -Name $adModuleName -MinimumVersion $RequiredADModuleVersion -ErrorAction Stop
            $isReady = $true
        } catch {
            $isReady = $false
        }
    }

    # Final attempt if not ready: import directly (covers RSAT-only availability)
    if (-not $isReady) {
        try {
            Import-Module -Name $adModuleName -MinimumVersion $RequiredADModuleVersion -ErrorAction Stop
            $isReady = $true
        } catch {
            throw "Required module '$adModuleName' (>= $RequiredADModuleVersion) is not available. Install RSAT or ensure the module path is accessible."
        }
    }

    # --- Proceed only once the module is confirmed available ---
    # Fetch the lockout event from the local Security log (event 4740), matching the username in the message
    # Note: This reads the local machine's Security log; run against a DC or adjust to query DC(s) as needed.
    $lockoutEvent =
        Get-EventLog -LogName Security -InstanceID 4740 -Newest 2000 |
        Where-Object { $_.Message -like "*$Username*" } |
        Sort-Object TimeGenerated -Descending |
        Select-Object -First 1

    if ($lockoutEvent) {
        Write-Host "Lockout event found for user $Username"
        Write-Host "--------------------------------------"
        Write-Host "Locked Out On: $($lockoutEvent.TimeGenerated)"
        Write-Host "Locked Out By: $($lockoutEvent.MachineName)"
        Write-Host "Event ID: $($lockoutEvent.EventID)"
        Write-Host "Message: $($lockoutEvent.Message)"
    } else {
        Write-Host "No recent lockout event found for user $Username"
    }
}