Public/Get-AduserLockoutInfo.ps1



Function Get-AduserLockoutInfo {
# .ExternalHelp .\Get-AduserLockoutInfo-help.xml

    [cmdletbinding(SupportsShouldProcess=$true)]
    param(
        [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true,HelpMessage="search for lockout events in seconds")]
        [int]$Timespan
    )
    
    

    BEGIN{
        Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] Starting: $($MyInvocation.MyCommand)"
        Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] PSVersion = $($PSVersionTable.PSVersion)"
        Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] OS = $((Get-CimInstance win32_OperatingSystem).Caption)"
        Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] User = $($env:userdomain)\$($env:USERNAME)"
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $IsAdmin = [System.Security.Principal.WindowsPrincipal]::new($id).IsInRole('administrators')
        Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] Is Admin = $IsAdmin"
        Import-module ActiveDirectory
        Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] Enumerating PDC Emulator"
        
        $DomainController = Get-ADDomain  | Select-Object PDCEmulator
        $DC = $DomainController.PDCEmulator
        

        try{
            $Session = New-CimSession -computerName $DC -ErrorAction Stop
            $OS = Get-CimInstance -CimSession  $Session -ClassName Win32_operatingSystem | Select-Object Caption
        }#TRY
        Catch{
            $ErrorMessage = $_.Exception.Message
            $ErrorMessage
            exit
        }#CATCH

        Switch -Wildcard($OS.Caption){

            "Microsoft Windows Server 2008 R2*"
            {
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] $($DC) is running $($OS.Caption)"
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] cannot run windows firewall check"
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] TestingPSRemotingStatus on $($DC)"
                $WSMANStatus = TestPSRemotingStatus -ComputerName $DC
                $FirewallStatus = $True
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] Cannot Test GPO Settings for $($OS.Caption) on $($DC)"
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] Ensure Audit Account Lockout and Audit User Account Management setting are configured"
                $ADAudtingEnabled = $True

            }
            "Microsoft Windows Server 2012 R2*"
            {
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] $($DC) is running $($OS.Caption)"
                $WSMANStatus = TestPSRemotingStatus -ComputerName $DC
                $FirewallStatus = TestFirewallRuleStatus -ComputerName $DC
                $ADAudtingEnabled = Get-ADAccountLockoutAuditPolicy -ComputerName $DC

            }

            "Microsoft Windows Server 2016*"
            {
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] $($DC) is running $($OS.Caption)"
                $WSMANStatus = TestPSRemotingStatus -ComputerName $DC
                $FirewallStatus = TestFirewallRuleStatus -ComputerName $DC
                $ADAudtingEnabled = Get-ADAccountLockoutAuditPolicy -ComputerName $DC

            }


            Default
            {
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] $($DC) is running $($OS.Caption) no condtion set"
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] TestingPSRemotingStatus on $($DC)"
                $WSMANStatus = $True
                $FirewallStatus = $True
                $ADAudtingEnabled = $True

            }
        }#SWITCH
        
    }#BEGIN


    PROCESS{
       if (($FirewallStatus -eq $true) -and ($WSMANStatus -eq $True) -and ($ADAudtingEnabled -eq $true)){ 
        TRY{
            if($pscmdlet.ShouldProcess($DC)){
                    
                    Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] Invoking: Examining event logs on $($DC)"
                    $Events = Get-WinEvent -ComputerName $DC  -FilterHashtable @{LOGNAME='Security';ID="4740"} -ErrorAction Stop
                        foreach ($event in $Events){
                            if($event.TimeCreated -ge (Get-Date).AddSeconds(-$Timespan) ){
                                Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] user $($event.Properties[0].value) is locked "
                                $Properties = [PSCustomObject][Ordered]@{

                                                    "Username" = $event.Properties[0].value 
                                                    "ReferenceComputer" = $Event.Properties[1].value
                                                    "LockOutTime" = $event.TimeCreated 
                                                    "Domain" = $Event.Properties[5].value
                                                    "DC" = $Event.Properties[4].value -replace "\$" 
                                                    
                                                }
                                $Properties
                            }#IF
                        }#Foreach
                }#IF
        }#TRY
        Catch [System.Exception] {
        Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] No Account lockout events found on $($DC)."
       }#CATCH
    
    }#IF

    }


    END{
        Remove-CimSession $Session -ErrorAction SilentlyContinue
        
    }





}#Function Get-AduserLockoutInfo (MAIN)

Function TestPSRemotingStatus {
    [cmdletbinding()]
    param(
    [String]$ComputerName
    )

    try{
        $WSMAN = New-PSSession -ComputerName $ComputerName -errorAction Stop
        
        if($WSMAN){
            Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] Powershell Remoting enabled on $($ComputerName)"
            Remove-PSSession $WSMAN.ID
            Return $true
        }
       
    }
    
    Catch
    {
        $ErrorMessage = $_.Exception.Message
        $ErrorMessage
        Write-error -message "Powershell remoting test error, enable powershell remoting to continue"
        exit
    }

}# Function TestPSRemotingStatus

Function TestFirewallRuleStatus {
    [cmdletbinding()]
    param(
    [String]$ComputerName
    )
    do{
        try{   
            Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] Testing if RemoteEventLogSvc-In-TCP firewall rule is enabled"
            $FirewallStatus = Invoke-Command -ComputerName $ComputerName -ScriptBlock {(Get-NetFirewallRule -Name 'RemoteEventLogSvc-In-TCP').Enabled} -AsJob | Wait-Job | Receive-Job -ErrorAction Stop
                if($($FirewallStatus.value) -eq $false){
                 
                    Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] Attempting to enable RemoteEventLogSvc-In-TCP on $($ComputerName)"
                    $RemoteJob = Invoke-Command -ComputerName $ComputerName -ScriptBlock {(Enable-NetFirewallRule -Name 'RemoteEventLogSvc-In-TCP')} -AsJob | Wait-Job | Receive-Job -ErrorAction Stop
                    
                }#IF
                elseif($($FirewallStatus.value) -eq $true){
                    Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN ] RemoteEventLogSvc-In-TCP firewall Rule Enabled on $($ComputerName). Test Passed"
                    Return $true
                    $Count = 2
                }#ELSEIF
            
            }#TRY
            Catch{
                $ErrorMessage = $_.Exception.Message
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) BEGIN:ERROR ] Error $($FirewallStatus)" 
                write-error -Message $FirewallStatus
                Write-Error -Message $ErrorMessage
                write-error -message $RemoteJob
                exit
            }#CATCH
        }while($Count -lt 2)
        
    
}#Function TestFirewallRuleStatus


Function Get-ADAccountLockoutAuditPolicy {
    [cmdletbinding(SupportsShouldProcess)]
    param(
        [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true,HelpMessage="DomainContoller (FQDN)")]
        [String]$ComputerName
    )

   
    try{
        if($PSCmdlet.ShouldProcess($ComputerName)){
            Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] Getting domain information"
            $Domain = $ComputerName.Substring($ComputerName.IndexOf(".") + 1)
            [xml]$DDCP = Get-GPOReport -name "Default Domain Controllers Policy" -Domain $Domain -Server $ComputerName -ReportType xml -ErrorAction Stop
        
            Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] Checking Default Domain Controllers Policy for Audit Settings"
            $AAL = $DDCP.ChildNodes.Computer.Extensiondata.extension.AuditSetting | Where-Object {$_.SubcategoryName -eq "Audit Account Lockout"} | Select-Object SubcategoryName, SettingValue -ErrorAction stop
            $AUAM = $DDCP.ChildNodes.Computer.Extensiondata.extension.AuditSetting | Where-Object {$_.SubcategoryName -eq "Audit User Account Management"} | Select-Object SubcategoryName, SettingValue -ErrorAction stop
        
        
            if($AAL.SettingValue -eq 3 -and $AUAM.SettingValue -eq 3){
                Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] Audit Settings enabled. Test Passed"
                Return $true
            }#IF
            else{

                Write-Verbose "[$((get-date).TimeOfDay.ToString()) PROCESS ] Audit Settings not configured. enable Audit Account Lockout and Audit User Account Management."
                Write-host  "Audit settings required for ADAccountLockoutInfo not configured $($ComputerName) for $($Domain). Script terminated" -ForegroundColor Yellow
                Return $false
            }#Else
        }#IF
    }#TRY
    Catch{
        $ErrorMessage = $_.Exception.Message
        $ErrorMessage

    }#CATCH
   


}#Function Get-ADAccountLockoutAuditPolicy



# SIG # Begin signature block
# MIIIWAYJKoZIhvcNAQcCoIIISTCCCEUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUaxDVzxaiGXRtaR2dbzCZ0H5f
# 02+gggXTMIIFzzCCBLegAwIBAgIKI+alEgAAAAAMTzANBgkqhkiG9w0BAQUFADBA
# MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFjAUBgoJkiaJk/IsZAEZFgZwZXRlcnMx
# DzANBgNVBAMTBlJvb3RDQTAeFw0xNjA1MjUyMjQ5MjVaFw0yMTA1MjQyMjQ5MjVa
# MIGIMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFjAUBgoJkiaJk/IsZAEZFgZwZXRl
# cnMxFzAVBgNVBAsTDlBldGVycyBPYmplY3RzMQ4wDAYDVQQLEwVVc2VyczEUMBIG
# A1UECxMLQ29udHJhY3RvcnMxGDAWBgNVBAMTD1NoaWhhbiBQaWV0ZXJzejCCASIw
# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqjlVFhz2Jmijj+v6bTi4EiAOJA
# Dx9InjUSh3aN06eELeKMRjqc0B33dk04kkq6Rs0dy8vvvrmQlE/Etoqx+GRJiy6K
# JC34FLQI85YxHrGNhLM54EZwRHX+iDsXsmZvEQqDaUHRC9QzT77fYVQOe8AxojLh
# zilyIHIU2Ec+N0chNX77I5e76K6L6fZa92R7lWz+fbeJm6IJIXSpukGTSFPMvLcg
# LnflfnnDBDCsfHecY9ZFPEH8LLs+LzV5ta5w8fVFt1IzqAHmiXWEx70t2n1jqvpx
# zx4ykBjKORHaVV8IzfiCrICbGl1/082lcdlO/1GbJaJlicTRzFPtoW47/AECAwEA
# AaOCAoAwggJ8MDwGCSsGAQQBgjcVBwQvMC0GJSsGAQQBgjcVCIH7wgPJxmWHoZ0j
# hYmgYYPNihR3gqzMRYXVsj8CAWQCAQIwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDgYD
# VR0PAQH/BAQDAgeAMBsGCSsGAQQBgjcVCgQOMAwwCgYIKwYBBQUHAwMwHQYDVR0O
# BBYEFGyYZLBdWxaiOaYrLW+7v7Vzvy1XMB8GA1UdIwQYMBaAFKJt615sTsvKB+Vm
# TET+s9YiUd9lMIHKBgNVHR8EgcIwgb8wgbyggbmggbaGgbNsZGFwOi8vL0NOPVJv
# b3RDQSxDTj1QRVRNVUxTRVIwMTYsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNl
# cnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9cGV0ZXJzLERD
# PWxvY2FsP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFz
# cz1jUkxEaXN0cmlidXRpb25Qb2ludDCBuQYIKwYBBQUHAQEEgawwgakwgaYGCCsG
# AQUFBzAChoGZbGRhcDovLy9DTj1Sb290Q0EsQ049QUlBLENOPVB1YmxpYyUyMEtl
# eSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9cGV0
# ZXJzLERDPWxvY2FsP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0
# aWZpY2F0aW9uQXV0aG9yaXR5MDEGA1UdEQQqMCigJgYKKwYBBAGCNxQCA6AYDBZ2
# LXNwaWV0ZXJAcGV0ZXJzLmxvY2FsMA0GCSqGSIb3DQEBBQUAA4IBAQAYLtV27syc
# YJgAMf07HQJSZ39O5AZL7NrxBifKpXGryK5imi1zKOaJCYVY1KDrfu+gCLW2IYuB
# TeSjqg2HHgM1p3dgS+uufcPasgBJsYnsFSqlTOnezu2IH87d73YuhlpRfR2r649A
# 0QXvwYe4aLgENyy6k9N0bkqMWEFxlShIOVY/adlU+qKOP2sPBUC5p9STJ909IYtQ
# mN+3iybKr0HMiECBPBH/HxlVqjtIu7PtqYwEBr3socadSmhHp+HwhB74xJ3coegU
# CBeRHMpQNlBuu41fmAGExDunJsaCg87n6Kyx9qMguICj7sjU1IAHuouFuRx6UKac
# lRhThY4m3CDxMYIB7zCCAesCAQEwTjBAMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwx
# FjAUBgoJkiaJk/IsZAEZFgZwZXRlcnMxDzANBgNVBAMTBlJvb3RDQQIKI+alEgAA
# AAAMTzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq
# hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC
# NwIBFTAjBgkqhkiG9w0BCQQxFgQUPLKZCP125wcI/oRaN3RTsfpPX2MwDQYJKoZI
# hvcNAQEBBQAEggEAh0J+61KK1Fzkjsrpx5d6kPYZeCwpanphrWFyYUtR8MRcsaF8
# MW9LII040hI8W9p3pRGtz6MlxrrbjQeQO/HuvSWtQgyehh3vSaLndjQsEiDM52uB
# cu3h2teMvtyoSMBy0ASSPxcZymY4hEYm8Pn8M0zrNORQHbMyWWt4uKZfZdV4b2Z2
# nC42qx1vMVe+kpsK4j/HZGFRZwBvBQGVyloF7SrsE9t0GqAW3fCCpYNhxpIcGi+8
# QvU/sjvtSJCByIBtOJEEfS3k9h+Pgq5M5of0yHwbfpaIm0FFAhRuOouVkOmfknMt
# LxZsqzM/5O80O+azduSKtDm1bre0EY6oCIak3g==
# SIG # End signature block