PSPowerAdminTasks.psm1
#Region '.\Classes\01CLASS_COMPUTER.ps1' 0 class COMPUTER { #region <Properties> [System.String]$Name [System.DateTime]$CheckTime [System.String]$Status [System.String]$SamAccountName [System.String]$CN [System.String]$Operatingsystem [System.String]$Description [System.String]$IPv4Address [System.String]$Created [System.String]$LastLogontimestamp [System.String]$CanonicalName [System.String]$MemberOF [System.String]$HotFixDescription [System.String]$HotfixID [System.String]$HotFixInstalledBy [System.String]$HotFixInstalledOn [System.String]$LastBootUptime [System.String]$RebootNeeded HIDDEN [System.Management.Automation.PSCredential]$Credential #endregion <Properties> #region <Constructor> COMPUTER() { } COMPUTER([string]$ComputerName) { $This.CheckTime = Get-Date $this.Name = $ComputerName $this.TestIfComputerIsOnline($ComputerName) } COMPUTER([string]$ComputerName, [System.Management.Automation.PSCredential]$Credential) { $This.Credential = $Credential $this.Name = $ComputerName $this.TestIfComputerIsOnline($ComputerName) } #endregion <Constructor> #region <Methods> [void] GetALlInformation () { if ($this.Status -eq "Ping OK") { $This.CheckTime = Get-Date $this.TestIfComputerExistInAd() $this.GetComputerLastHotFix() $this.GetComputerLastBootUptime() $this.TestIfRebootNeeded() } } [void] TestIfComputerIsOnline([string]$ComputerName) { try { if (Test-Connection -ComputerName $ComputerName -Count 1 -ErrorAction Stop) { $this.Status = "Ping OK" } else { $this.Status = "Ping KO" } } catch { $this.Status = "Host Unknown" } } [Boolean] TestIfComputerExistInAd () { $Parameter = @{ Properties = 'Name', 'SamAccountName', 'CN', 'Operatingsystem', 'Description', 'IPv4Address', 'Created', 'LastLogontimestamp', 'CanonicalName', 'MemberOF' Filter = { Name -eq $This.Name } ErrorAction = "SilentlyContinue" } if ($null -ne $this.Credential) { $Parameter.Add('Credential', $this.Credential) } $Computer = Get-ADComputer @Parameter if ($Computer) { try { $this.SamAccountName = $Computer.SamAccountName $this.CN = $Computer.CN $this.Operatingsystem = $Computer.Operatingsystem $this.Description = $Computer.Description $this.IPv4Address = $Computer.IPv4Address $this.Created = $Computer.Created $this.LastLogontimestamp = [DateTime]::FromFileTime($Computer.LastLogontimestamp) $this.CanonicalName = $Computer.CanonicalName if ($Computer.MemberOF.Count -gt 0) { $this.MemberOF = ($Computer.MemberOf -like "*WSUS*").split("=")[1].split(",")[0] } else { $This.MemberOF = "No WSUS Group" } } catch [System.Management.Automation.MethodException] { Write-Output ('[{0:O}] ErrorID: {1}' -f (get-date),$_.Exception.Message) Write-Output ('[{0:O}] Exception: {1}' -f (get-date),$_.FullyQualifiedErrorId) Write-Output ('[{0:O}] Category: {1}' -f (get-date),(($_.Exception.GetType() | Select-Object -ExpandProperty UnderlyingSystemType).FullName)) } catch { Write-Output ('[{0:O}] ErrorID: {1}' -f (get-date),$_.Exception.Message) Write-Output ('[{0:O}] Exception: {1}' -f (get-date),$_.FullyQualifiedErrorId) Write-Output ('[{0:O}] Category: {1}' -f (get-date),(($_.Exception.GetType() | Select-Object -ExpandProperty UnderlyingSystemType).FullName)) } return $true } else { $this.SamAccountName = "Unknown" $this.CN = "Unknown" $this.Operatingsystem = "Unknown" $this.Description = "Unknown" $this.IPv4Address = "Unknown" $this.Created = "Unknown" $this.LastLogontimestamp = "Unknown" $this.CanonicalName = "Unknown" $this.MemberOF = "Unknown" return $false } } [Void] GetComputerLastHotFix () { try { $HotfixParameter = @{ ComputerName = $this.CN ErrorAction = "Stop" } if ($null -ne $this.Credential) { $HotfixParameter['Credential'] = $this.Credential } $hotfix = Get-HotFix @HotfixParameter | Sort-Object -Descending -Property InstalledOn | Select-Object -First 1 | Select-Object Description, HotfixID, InstalledBy, InstalledOn $this.HotfixID = $hotfix.HotfixID $this.HotFixDescription = $hotfix.Description $this.HotFixInstalledBy = $hotfix.InstalledBy $this.HotFixInstalledOn = $hotfix.InstalledOn } catch [System.UnauthorizedAccessException] { $this.HotfixID = "UnauthorizedAccessException" $this.HotFixDescription = "UnauthorizedAccessException" $this.HotFixInstalledBy = "UnauthorizedAccessException" $this.HotFixInstalledOn = "UnauthorizedAccessException" } catch { $this.HotfixID = "Unknown" $this.HotFixDescription = "Unknown" $this.HotFixInstalledBy = "Unknown" $this.HotFixInstalledOn = "Unknown" } } [Void] GetComputerLastBootUptime () { try { $Parameter = @{ ComputerName = $this.CN ErrorAction = "Stop" } if ($null -ne $this.Credential) { $Parameter['Credential'] = $this.Credential } $this.LastBootUptime = Invoke-Command @Parameter -ScriptBlock {(Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty LastBootUpTime)} } catch { Write-Output ('[{0:O}] ErrorID: {1}' -f (get-date),$_.Exception.Message) Write-Output ('[{0:O}] Exception: {1}' -f (get-date),$_.FullyQualifiedErrorId) Write-Output ('[{0:O}] Category: {1}' -f (get-date),(($_.Exception.GetType() | Select-Object -ExpandProperty UnderlyingSystemType).FullName)) $this.LastBootUptime = "Unknown" } } [void] TestIfRebootNeeded () { if ($this.Status -eq "Ping OK") { try { $CmdParameter = @{ ComputerName = $this.CN ErrorAction = "Stop" Authentication = "Kerberos" } if ($null -ne $this.Credential) { $CmdParameter['Credential'] = $this.Credential } $this.RebootNeeded = Invoke-Command @CmdParameter -ScriptBlock { if ((Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -ErrorAction SilentlyContinue) -or (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -ErrorAction SilentlyContinue) ) { write-output "YES" } else { Write-output "NO" } } } catch { $This.RebootNeeded = "Unknown" } } } #endregion <Methods> } #EndRegion '.\Classes\01CLASS_COMPUTER.ps1' 230 #Region '.\Private\Write-Log.ps1' 0 function Write-Log { <# .SYNOPSIS Write a log file .DESCRIPTION Write all operation passed as parameter to a log file .PARAMETER LogPath Path to logfile. By default, the logfile is created in the temp folder of the current user .PARAMETER Message Message to write in the log file .PARAMETER Severity Severity of the message. By default, the severity is set to Information .PARAMETER Console Show the message in the console .PARAMETER Force Forece the creation of the log file .EXAMPLE Write-log -Message 'Starting Set-ChangePasswordAtNextLogon' -Severity Information -Console .NOTES General notes #> [CmdletBinding()] param ( [Parameter()] [ValidateNotNullOrEmpty()] [System.String]$LogPath = "$env:Temp\LogFile.csv", [Parameter()] [ValidateNotNullOrEmpty()] [string]$Message, [Parameter()] [ValidateNotNullOrEmpty()] [ValidateSet('Information', 'Warning', 'Error')] [string]$Severity = 'Information', [Parameter()] [switch]$Console, [Parameter()] [switch]$Force ) $info = [pscustomobject]@{ Severity = "[$($Severity)]" Time = ((Get-Date).toString("yyyy/MM/dd HH:mm:ss")) Message = $Message } if ($Console) { Write-Output "$($info.Severity) $($info.Time) $($info.Message)" } if ($Force) { $info | Export-Csv -Path $LogPath -NoTypeInformation -Force } else { $info | Export-Csv -Path $LogPath -NoTypeInformation -Append } } #EndRegion '.\Private\Write-Log.ps1' 75 #Region '.\Public\Disable-CompromisedUser.ps1' 0 function Disable-CompromisedUser { <# .SYNOPSIS Disable compromised user .DESCRIPTION In case of compromission from some users, you can rapidly disable this users. You can pass to parameter : - a nominative list of user - a file with a nominative list of users (one user by line) - an OU to disable all users Check example for more details (get-help Disable-CompromisedUser -Examples) A log file is create in your temp directory ($env:temp) .PARAMETER Identity One or more user(s) to disable .PARAMETER FileName File with a list of users to disable. txt with one name by line .PARAMETER OU One or more OU(s) in which we want to disable all users .PARAMETER Check Only check if the users passed in parameter, whatever the way (Identity, Filename or OU), are disable .PARAMETER Credential Specifies the user account credentials to use when performing this task .PARAMETER Log Log information in a file (in $env:Temp ) .PARAMETER Console Show information in console (need Log parameter) .EXAMPLE Disable-CompromisedUser -Identity "User1" Disable the user account : User1 .EXAMPLE Disable-CompromisedUser -Identity "User1" -Log Disable the user account : User1 and log information in file in $env:temp .EXAMPLE Disable-CompromisedUser -Identity "User1" -Log -Console Disable the user account : User1, log information in file in $env:temp and log to console the same information .EXAMPLE Disable-CompromisedUser -Identity "User1" -Check Check if user account User1 is disable .EXAMPLE Disable-CompromisedUser -Identity "User1","User2","User3" Disable users account : User1, User2 and User3 .EXAMPLE Disable-CompromisedUser -Identity "User1","User2","User3" -Check Check if users account User1, User2 and User3 are disable .EXAMPLE Disable-CompromisedUser -FileName "c:\temp\CompromisedUser.txt" File template CompromisedUser.txt : User1 User2 User3 Disable users account : User1, User2 and User3 .EXAMPLE Disable-CompromisedUser -FileName "c:\temp\CompromisedUser.txt" -Check File template CompromisedUser.txt : User1 User2 User3 Check if users account User1, User2 and User3 are disable .EXAMPLE Disable-CompromisedUser -OU "OU=OU1,DC=contoso,DC=com" Disable all users present in OU1 .EXAMPLE Disable-CompromisedUser -OU "OU=OU1,DC=contoso,DC=com" -Check Check if all users present in OU1 are disable .EXAMPLE Disable-CompromisedUser -OU "OU=OU1,DC=contoso,DC=com","OU=OU2,DC=contoso,DC=com" Disable all users present in OU1 and OU2 .EXAMPLE Disable-CompromisedUser -OU "OU=OU1,DC=contoso,DC=com","OU=OU2,DC=contoso,DC=com" -check Check if all users present in OU1 and OU2 are disable .NOTES General notes #> [CmdletBinding(DefaultParameterSetName = "ByUser")] param ( [Parameter( ParameterSetName = "ByUser", HelpMessage = 'One or more user(s) to disable' )] [System.String[]]$Identity, [Parameter( ParameterSetName = "ByFileName", HelpMessage = 'File with a list of users to disable. txt with one name by line' )] [System.String]$FileName, [Parameter( ParameterSetName = "ByOu", HelpMessage = 'One or more OU(s) in which we want to disable all users' )] [System.String[]]$OU, [Parameter( HelpMessage = 'Only check if the users passed in parameter, whatever the way (Identity, Filename or OU), are disable' )] [Switch]$Check, [Parameter( HelpMessage = "Specifies the user account credentials to use when performing this task." )] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter( HelpMessage = 'Log information in a file' )] [switch]$log, [Parameter( HelpMessage = 'Show information in console' )] [switch]$Console ) begin { if ($log) { $LogPath = $env:Temp + '\Disable-CompromisedUser.csv' Write-Log -LogPath $LogPath -Message 'Starting Disable-CompromisedUser' -Severity Information -Console:$Console } $Users = @() switch ($PSCmdlet.ParameterSetName) { ByUser { if ($log) { write-log -LogPath $LogPath -Message "Retrieve AD User Account by user list" -Severity Information -Console:$Console} foreach ($User in $Identity) { try { $Users += Get-ADUser -Identity $User -Properties SamAccountName,DisplayName,Enabled -ErrorAction Continue | Select-Object SamAccountName,DisplayName,Enabled if ($log) { write-log -LogPath $LogPath -Message "User $($User) found" -Severity Information -Console:$Console} } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { if ($log) { write-log -LogPath $LogPath -Message "User $($User) not found" -Severity Error -Console:$Console} } } } ByFileName { if ($log) { write-log -LogPath $LogPath -Message "Retrieve AD User Account by file list" -Severity Information -Console:$Console} foreach ($User in (Get-Content -Path $FileName)) { try { $Users += Get-ADUser -Identity $User -Properties SamAccountName,DisplayName,Enabled -ErrorAction Continue | Select-Object SamAccountName,DisplayName,Enabled if ($log) { write-log -LogPath $LogPath -Message "User $($User) found" -Severity Information -Console:$Console} } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { if ($log) { write-log -LogPath $LogPath -Message "User $($User) not found" -Severity Error -Console:$Console} } } } ByOu { if ($log) { write-log -LogPath $LogPath -Message "Retrieve AD User Account by OU list" -Severity Information -Console:$Console} foreach ($Organ in $OU) { if ($log) { write-log -LogPath $LogPath -Message "Retrieve AD User Account in $($Organ)" -Severity Information -Console:$Console} $Users += Get-ADUser -Filter * -SearchBase $Organ -Properties SamAccountName,DisplayName,Enabled | Select-Object SamAccountName,DisplayName,Enabled } } } } process { $Arguments = @{} if ($PSBoundParameters.ContainsKey('Credential')) { $Arguments['Credential'] = $Credential } foreach ($user in $Users) { if ($Check) { if ($log) { write-log -LogPath $LogPath -Message "Check state for user $( $User.SamAccountName)" -Severity Information -Console:$Console} if ($user.Enabled -eq "True") { if ($log) { write-log -LogPath $LogPath -Message "user $($User.SamAccountName) is enabled" -Severity Information -Console:$Console} } else { if ($log) { write-log -LogPath $LogPath -Message "user $($User.SamAccountName) is disabled" -Severity Information -Console:$Console} } } else { $Arguments['Identity'] = $Users.SamAccountName Disable-ADAccount @Arguments -Confirm:$false if ($log) { write-log -LogPath $LogPath -Message "Disabeling user $($User.SamAccountName)" -Severity Information -Console:$Console} } } } end { if ($log) { write-log -LogPath $LogPath -Message "Ending Disable-CompromisedUser" -Severity Information -Console:$Console } } } #EndRegion '.\Public\Disable-CompromisedUser.ps1' 247 #Region '.\Public\Find-UserLockoutsInformation.ps1' 0 Function Find-UserLockoutsInformation { <# .SYNOPSIS Find information about locked user account .DESCRIPTION This fonction search for locked user on PDC Emulator and return the lock source return : User : User1 DomainController : PDCEmulator EventId : 4740 LockoutTimeStamp : 8/3/2023 6:18:12 AM Message : A user account was locked out. LockoutSource : SourceComputer To find the reason use : Get-UserLockoutReason -Computer SourceComputer -Identity User1 .PARAMETER Identity User to check (by default all) .PARAMETER DC Domain controller on which you want to look up information (by default PDC Emulator) .PARAMETER Credential Administrator credential to connect to the DC .EXAMPLE Find-UserLockoutsInformation -Credential (Get-Credential MyAdminAccount) Search information for all locked users in PDC Emulator .EXAMPLE Find-UserLockoutsInformation -Identity User1 -Credential (Get-Credential MyAdminAccount) Search information for user User1 in PDC Emulator .EXAMPLE Find-UserLockoutsInformation -Identity User1 -DC MyDC1 -Credential (Get-Credential MyAdminAccount) Search information for user User1 in specific domain controler MyDC1 .NOTES General notes #> [CmdletBinding( DefaultParameterSetName = 'All' )] param ( [Parameter( ValueFromPipeline = $true, ParameterSetName = 'ByUser' )] [System.String]$Identity, [System.String]$DC = (Get-ADDomain).PDCEmulator, # Specifies the user account credentials to use when performing this task. [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) Begin { Write-Verbose ('[{0:O}] Searching EventID : 4740 on Server : {1} ' -f (get-date), $DC) $WinEventArguments = @{ ComputerName = $DC FilterHashtable = @{LogName = 'Security'; Id = 4740 } } if ($PSBoundParameters.ContainsKey('Credential')) { $WinEventArguments['Credential'] = $Credential } try { $LockedOutEvents = Get-WinEvent @WinEventArguments -ErrorAction Stop | Sort-Object -Property TimeCreated -Descending } catch { if ($Error[-1].Exception.Message -like "*elevated user rights*") { throw ('[{0:O}] You need an admin account. Please provide with the -Credential parameter' -f (get-date)) } } if ($LockedOutEvents) { Write-Verbose ('[{0:O}] {1} event found' -f (get-date), $LockedOutEvents.Count) } else { throw ('[{0:O}] No event found' -f (get-date)) } } Process { switch ($PSCmdlet.ParameterSetName) { ByUser { Write-Verbose ('[{0:O}] Searching information for user : {1}' -f (get-date), $Identity) $UserInfo = Get-ADUser -Identity $Identity Foreach ($Event in $LockedOutEvents) { If ($Event | Where-Object { $_.Properties[2].value -match $UserInfo.SID.Value }) { $Event | Select-Object -Property @( @{Label = 'User'; Expression = { $_.Properties[0].Value } } @{Label = 'DomainController'; Expression = { $_.MachineName } } @{Label = 'EventId'; Expression = { $_.Id } } @{Label = 'LockoutTimeStamp'; Expression = { $_.TimeCreated } } @{Label = 'Message'; Expression = { $_.Message -split "`r" | Select-Object -First 1 } } @{Label = 'LockoutSource'; Expression = { $_.Properties[1].Value } } ) } } } All { Write-Verbose ('[{0:O}] Searching information for all user(s) ' -f (get-date)) Foreach ($Event in $LockedOutEvents) { $Event | Select-Object -Property @( @{Label = 'User'; Expression = { $_.Properties[0].Value } } @{Label = 'DomainController'; Expression = { $_.MachineName } } @{Label = 'EventId'; Expression = { $_.Id } } @{Label = 'LockoutTimeStamp'; Expression = { $_.TimeCreated } } @{Label = 'Message'; Expression = { $_.Message -split "`r" | Select-Object -First 1 } } @{Label = 'LockoutSource'; Expression = { $_.Properties[1].Value } } ) } } } } End { } } #EndRegion '.\Public\Find-UserLockoutsInformation.ps1' 134 #Region '.\Public\Get-BitLockerInformation.ps1' 0 function Get-BitLockerInformation { <# .SYNOPSIS Retreive BitLocker information from Active Directory .DESCRIPTION Retreive BitLocker information for computer pass as parameter from Active Directory .PARAMETER Computer Computer name .PARAMETER Credential Credential with permission to read bitlocker information in Active Directory .EXAMPLE Get-BitlockerInformation -Computer "ComputerName" -Credential $MyCredential Find bitlocker information for computer "ComputerName" with credential .NOTES General notes #> [CmdletBinding()] param( [Parameter(ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] [System.String[]]$Computer, [Parameter(Mandatory)] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { $Result = @() $Argument = @{ Filter = { ObjectClass -eq 'msFVE-RecoveryInformation' } Properties = 'msFVE-RecoveryPassword' } If ($PSBoundParameters.ContainsKey("Credential")) { $Argument.Add("Credential", $Credential) } } process { foreach ($Comp in $Computer) { Write-Verbose "Check computer : $($Comp)" $objComputer = Get-ADComputer -Identity $Comp $BitLockerObject = Get-ADObject @Argument -SearchBase $objComputer.DistinguishedName if ($BitLockerObject) { $Bitlock = $BitLockerObject | Sort-Object Name | Select-Object -last 1 $object = [PSCustomObject]@{ "Computer" = $Comp "Password ID" = $Bitlock.Name.split("{")[1].split("}")[0] "Date" = $Bitlock.Name.split("{")[0] "Recovery Key" = $Bitlock.'msFVE-RecoveryPassword' } $Result += $object } else { $object = [PSCustomObject]@{ "Computer" = $Comp "Password ID" = "null" "Date" = "null" "Recovery Key" = "null" } $Result += $object } } } end { return $Result } } #EndRegion '.\Public\Get-BitLockerInformation.ps1' 80 #Region '.\Public\Get-LastUpdateInformation.ps1' 0 function Get-LastUpdateInformation { <# .SYNOPSIS Retrieve update information .DESCRIPTION Retrieve update information for a server the data is : Name CheckTime Status SamAccountName CN Operatingsystem Description IPv4Address Created LastLogontimestamp CanonicalName MemberOF HotFixDescription HotfixID HotFixInstalledBy HotFixInstalledOn LastBootUptime RebootNeeded .PARAMETER ComputerName One or more computer(s) to check .PARAMETER Credential Administrator credential to connect to the computer .EXAMPLE Get-LastUpdateInformation -ComputerName MyServer -Credential (Get-Credential MyAdminAccount) -Verbose Search last update information foe server MyServer using credential to connect .NOTES General notes #> [CmdletBinding()] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true)] [System.String[]]$ComputerName, # Specifies the user account credentials to use when performing this task. [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()]$Credential ) begin { $result = @() } process { if ($null -ne $Credential) { foreach ($computer in $ComputerName) { Write-Verbose ('[{0:O}] Computer {1}' -f (get-date),$computer) $Infos = [COMPUTER]::new($computer, $Credential) $Infos.GetALlInformation() $result += $Infos } } else { foreach ($computer in $ComputerName) { Write-Verbose ('[{0:O}] Computer {1}' -f (get-date),$computer) $Infos = [COMPUTER]::new($computer) $Infos.GetALlInformation() $result += $Infos } } } end { return $result } } #EndRegion '.\Public\Get-LastUpdateInformation.ps1' 87 #Region '.\Public\Get-UserLockoutReason.ps1' 0 function Get-UserLockoutReason { <# .SYNOPSIS Search user lockout reason .DESCRIPTION You can search the reason of locked user on a specific computer To find the source you can use : Find-UserLockoutsInformation -Identity User1 -DC MyDC1 -Credential (Get-Credential MyAdminAccount) .PARAMETER Computer User lockout source computer .PARAMETER Identity Name of the user for whom we are looking for the source of the lock .PARAMETER Credential Administrator credential to connect to the computer .EXAMPLE Get-UserLockoutReason -Computer ComputerSource -Identity User1 -Credential (Get-Credential MyAdminAccount) .NOTES General notes #> [CmdletBinding( DefaultParameterSetName = 'All' )] [OutputType([System.Object[]])] param ( [System.String]$Computer, [Parameter( ValueFromPipeline = $true, ParameterSetName = 'ByUser' )] [System.String]$Identity, # Specifies the user account credentials to use when performing this task. [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { $LogonInfo = Import-PSFPowerShellDataFile -Path $PSScriptRoot/PSPowerAdminTasks.psd1 Write-Verbose ('[{0:O}] Searching EventID : 4625 on Computer : {1} ' -f (get-date), $Computer) $WinEventArguments = @{ ComputerName = $Computer FilterHashtable = @{LogName = 'Security'; Id = 4625 } } if ($PSBoundParameters.ContainsKey('Credential')) { $WinEventArguments['Credential'] = $Credential } $lockoutEvents = $null Write-Verbose ('[{0:O}] Test if computer : {1} is alive ' -f (get-date), $Computer) if (Test-Connection -ComputerName $Computer -Quiet -Count 2) { try { $lockoutEvents = Get-WinEvent @WinEventArguments -ErrorAction Stop } catch { if ($_.Exception.Message -match "No events were found that match the specified selection criteria") { Write-Verbose ('[{0:O}] No logs found' -f (get-date)) } if ($Error[-1].Exception.Message -like "*elevated user rights*") { throw ('[{0:O}] You need an admin account. Please provide with the -Credential parameter' -f (get-date)) } } } else { throw ('[{0:O}] computer {1} is not alive' -f (get-date), $Computer) } if ($lockoutEvents) { Write-Verbose ('[{0:O}] {1} event found' -f (get-date), $lockoutEvents.Count) } else { throw ('[{0:O}] No event found' -f (get-date)) } } process { switch ($PSCmdlet.ParameterSetName) { All { Write-Verbose ('[{0:O}] Searching information for all user(s) ' -f (get-date)) Foreach ($Event in $lockoutEvents) { $eventXML = [xml]$event.ToXml() $Event | Select-Object -Property @( @{label = 'LockedUserName' ; Expression = {$eventXML.Event.EventData.Data[5].'#text'}} @{label = 'LogonType' ; Expression = {$LogonInfo.PrivateData.LogonType."$($eventXML.Event.EventData.Data[10].'#text')"}} @{label = 'LogonProcessName' ; Expression = {$eventXML.Event.EventData.Data[11].'#text'}} @{label = 'ProcessName' ; Expression = {$eventXML.Event.EventData.Data[18].'#text'}} @{label = 'FailureReason' ; Expression = {$LogonInfo.PrivateData.FailureReason."$($eventXML.Event.EventData.Data[8].'#text')"}} @{label = 'FailureStatus' ; Expression = {$LogonInfo.PrivateData.FailureType."$($eventXML.Event.EventData.Data[7].'#text')"}} @{label = 'FailureSubStatus' ; Expression = {$LogonInfo.PrivateData.FailureType."$($eventXML.Event.EventData.Data[9].'#text')"}} ) } } ByUser { Write-Verbose ('[{0:O}] Searching information for user : {1}' -f (get-date), $Identity) Foreach ($Event in $lockoutEvents) { $eventXML = [xml]$event.ToXml() If ($Event | Where-Object { $eventXML.Event.EventData.Data[5].'#text' -match $Identity }) { $Event | Select-Object -Property @( @{label = 'LockedUserName' ; Expression = {$eventXML.Event.EventData.Data[5].'#text'}} @{label = 'LogonType' ; Expression = {$LogonInfo.PrivateData.LogonType."$($eventXML.Event.EventData.Data[10].'#text')"}} @{label = 'LogonProcessName' ; Expression = {$eventXML.Event.EventData.Data[11].'#text'}} @{label = 'ProcessName' ; Expression = {$eventXML.Event.EventData.Data[18].'#text'}} @{label = 'FailureReason' ; Expression = {$LogonInfo.PrivateData.FailureReason."$($eventXML.Event.EventData.Data[8].'#text')"}} @{label = 'FailureStatus' ; Expression = {$LogonInfo.PrivateData.FailureType."$($eventXML.Event.EventData.Data[7].'#text')"}} @{label = 'FailureSubStatus' ; Expression = {$LogonInfo.PrivateData.FailureType."$($eventXML.Event.EventData.Data[9].'#text')"}} ) } } } } } end { } } #EndRegion '.\Public\Get-UserLockoutReason.ps1' 147 #Region '.\Public\Remove-UserFromGroup.ps1' 0 #take a list of users and for each users, check if the user is in a list of groups. If user is found in a group then remove the user from the group. function Remove-UserFromGroup { <# .SYNOPSIS Remove a user from a group .DESCRIPTION Remove one or more users from one or more groups .PARAMETER Users One user or more users to remove from one or more groups .PARAMETER Groups One or more groups to remove one or more users from .PARAMETER FilePathUser Path to a file containing one user per line .PARAMETER FilePathGroup Path to a file containing one group per line .PARAMETER Credential Credentials to use when performing this task .PARAMETER Log Log the operation into a file (in $env:temp by default) .PARAMETER Console Show the message in the console .EXAMPLE Remove-UserFromGroup -Users 'User1' -Groups 'Group1' Remove USer1 from Group1 .EXAMPLE Remove-UserFromGroup -Users 'User1','User2" -Groups 'Group1' Remove User1 and User2 from Group1 .EXAMPLE Remove-UserFromGroup -Users 'User1','User2" -Groups 'Group1','Group2' Remove User1 and User2 from Group1 and Group2 .EXAMPLE Remove-UserFromGroup -FilePathUser 'C:\Users.txt' -FilePathGroup 'C:\Groups.txt' Users.txt contains one user per line Groups.txt contains one group per line Remove users from groups based on a file containing users and a file containing groups .NOTES General notes #> [CmdletBinding(DefaultParameterSetName = 'ByUser')] param ( [Parameter(ParameterSetName = 'ByUser')] [string[]]$Users, [Parameter(ParameterSetName = 'ByUser')] [string[]]$Groups, [Parameter(ParameterSetName = 'ByFile')] [System.String]$FilePathUser, [Parameter(ParameterSetName = 'ByFile')] [System.String]$FilePathGroup, # Specifies the user account credentials to use when performing this task. [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter()] [switch]$log, [Parameter()] [switch]$Console ) begin { if ($log) { $LogPath = $env:Temp + '\Remove-UserFromGroup.csv' Write-Log -LogPath $LogPath -Message 'Starting Remove-UserFromGroup' -Severity Information -Console:$Console } } process { if ($PSCmdlet.ParameterSetName -eq 'ByFile') { $Users = Get-Content -Path $FilePathUser $Groups = Get-Content -Path $FilePathGroup } try { # Loop through each user foreach ($user in $users) { # Loop through each group foreach ($group in $groups) { if ($log) { write-log -LogPath $LogPath -Message "Searching user $($user) in group $($group)" -Severity Information -Console:$Console} # Check if the user is a member of the group $isMember = (Get-ADGroupMember -Identity $group -ErrorAction Stop | Where-Object { $_.SamAccountName -eq $user }) # If the user is a member of the group, remove them if ($isMember) { if ($log) { write-log -LogPath $LogPath -Message "User $($user) found in group $($group) => remove it" -Severity Information -Console:$Console} $Arguments = @{ Identity = $group Members = $user Confirm = $false ErrorAction = "Stop" } if ($PSBoundParameters.ContainsKey('Credential')) { $Arguments['Credential'] = $Credential } Remove-ADGroupMember @Arguments } } } } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { if ($log) { write-log -LogPath $LogPath -Message "group $($group) not found...." -Severity Error -Console:$Console} Write-Error ('[{0:O}] group {1} not found....' -f (Get-Date),$group) } catch [Microsoft.ActiveDirectory.Management.ADException] { if ($log) { write-log -LogPath $LogPath -Message "Insufficient access rights to perform the operation" -Severity Error -Console:$Console} Write-Error ('[{0:O}] Insufficient access rights to perform the operation' -f (Get-Date)) } catch { Write-Output ('[{0:O}] ErrorID: {1}' -f (Get-Date), $_.Exception.Message) Write-Output ('[{0:O}] Exception: {1}' -f (Get-Date), $_.FullyQualifiedErrorId) Write-Output ('[{0:O}] Category: {1}' -f (Get-Date), (($_.Exception.GetType() | Select-Object -ExpandProperty UnderlyingSystemType).FullName)) } } end { if ($log) { Write-Log -LogPath $LogPath -Message 'Ending Remove-UserFromGroup' -Severity Information -Console:$Console } } } #EndRegion '.\Public\Remove-UserFromGroup.ps1' 153 #Region '.\Public\Set-ChangePasswordAtNextLogon.ps1' 0 function Set-ChangePasswordAtNextLogon { <# .SYNOPSIS Force user to change password at next logon .DESCRIPTION Force user(s) passed as parameter to change password at next logon .PARAMETER Identity Name of user(s) to force to change password at next logon .PARAMETER DomainController Domain controler on which to perform the operation .PARAMETER Credential Credentials to use when performing the operation .PARAMETER Log Log the operation into a file .PARAMETER Console Show the message in the console .EXAMPLE Set-ChangePasswordAtNextLogon -Identity user1,user2,user3 .EXAMPLE Set-ChangePasswordAtNextLogon -Identity user1,user2,user3 -DomainController dc1 .EXAMPLE Set-ChangePasswordAtNextLogon -Identity user1,user2,user3 -Credential (Get-Credential) .EXAMPLE Set-ChangePasswordAtNextLogon -Identity user1,user2,user3 -Log .EXAMPLE Set-ChangePasswordAtNextLogon -Identity user1,user2,user3 -Console -Log .NOTES General notes #> [CmdletBinding(SupportsShouldProcess)] param ( # UserName [Parameter()] [System.String[]]$Identity, # Parameter help description [Parameter()] [System.String]$DomainController = (Get-ADDomainController -Discover -Service PrimaryDC).HostName[0], # Specifies the user account credentials to use when performing this task. [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter()] [switch]$log, [Parameter()] [switch]$Console ) begin { if ($log) { $LogPath = $env:Temp + '\Set-ChangePasswordAtNextLogon.csv' Write-Log -LogPath $LogPath -Message 'Starting Set-ChangePasswordAtNextLogon' -Severity Information -Console:$Console } } process { $count = 1 $Arguments = @{ ChangePasswordAtLogon = $True ErrorAction = "Stop" Server = $DomainController } if ($PSBoundParameters.ContainsKey('Credential')) { $Arguments['Credential'] = $Credential } foreach ($user in $Identity) { if ($log) { write-log -LogPath $LogPath -Message "Processing user $($count) of $($Identity.Count)" -Severity Information -Console:$Console} if ($log) { write-log -LogPath $LogPath -Message "Processing user $($user)" -Severity Information -Console:$Console} $count++ $Arguments['Identity'] = $user try { if ($PSCmdlet.ShouldProcess($user, 'Set-ADUser')) { if ($log) { write-log -LogPath $LogPath -Message "Processing user $($user)" -Severity Information -Console:$Console} Set-ADUser @Arguments } } catch [Microsoft.ActiveDirectory.Management.ADException] { if ($log) { write-log -LogPath $LogPath -Message "Insufficient access rights to perform the operation" -Severity Error -Console:$Console} Write-Error ('[{0:O}] Insufficient access rights to perform the operation' -f (Get-Date)) } catch { if ($log) { write-log -LogPath $LogPath -Message "$($_.Exception.Message)" -Severity Error -Console:$Console write-log -LogPath $LogPath -Message "$($_.FullyQualifiedErrorId)" -Severity Error -Console:$Console write-log -LogPath $LogPath -Message "$($_.Exception.GetType() | Select-Object -ExpandProperty UnderlyingSystemType).FullName)" -Severity Error } Write-Output ('[{0:O}] ErrorID: {1}' -f (Get-Date), $_.Exception.Message) Write-Output ('[{0:O}] Exception: {1}' -f (Get-Date), $_.FullyQualifiedErrorId) Write-Output ('[{0:O}] Category: {1}' -f (Get-Date), (($_.Exception.GetType() | Select-Object -ExpandProperty UnderlyingSystemType).FullName)) } } } end { if ($log) { Write-Log -LogPath $LogPath -Message 'Ending Set-ChangePasswordAtNextLogon' -Severity Information -Console:$Console } } } #EndRegion '.\Public\Set-ChangePasswordAtNextLogon.ps1' 129 #Region '.\Public\Set-LocalUserPassword.ps1' 0 function Set-LocalUserPassword { <# .SYNOPSIS Set the password of a local user account .DESCRIPTION Set the password of a local user account. Password pass as a plain text string will be converted to a secure string. .PARAMETER Username UserName of the local user account to set the password .PARAMETER Password Password of the local user account to set. Pass as a plain text string will be converted to a secure string. .PARAMETER ComputerName ComputerName where the local user account is located. Default is the local computer. .PARAMETER Credential Specifies the user account credentials to use when performing this task. .EXAMPLE Set-LocalUserPassword -Username "MyUser" -Password "P@sswOrd" -Credential ($MyAdminAccount) -ComputerName Myserver Set password of the local user account "MyUser" on the computer "Myserver" with the credential stored in the variable $MyAdminAccount .NOTES General notes #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String]$Username, [Parameter(Mandatory = $true)] [System.String]$Password, [Parameter()] [System.String]$ComputerName = $env:COMPUTERNAME, # Specifies the user account credentials to use when performing this task. [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { $ErrorActionPreference = 'Stop' } process { $NewSecurePwd = $Password | ConvertTo-SecureString -AsPlainText -Force try { if ($ComputerName -ne $env:COMPUTERNAME) { $Session = New-PSSession -ComputerName $ComputerName -Credential $Credential Invoke-Command -Session $Session -ScriptBlock { Get-LocalUser -Name $Using:Username | Set-LocalUser -Password $Using:NewSecurePwd } Remove-PSSession -Session $Session return } else { Get-LocalUser -Name $Username | Set-LocalUser -Password $NewSecurePwd return } } catch [Microsoft.PowerShell.Commands.UserNotFoundException] { Write-Error ('[{0:O}] User {1} not found' -f (get-date),$Username) } catch [Microsoft.PowerShell.Commands.AccessDeniedException] { Write-Error ('[{0:O}] Access denied, use account with suffisant privilege' -f (get-date)) } catch { Write-Output ('[{0:O}] ErrorID: {1}' -f (get-date),$_.Exception.Message) Write-Output ('[{0:O}] Exception: {1}' -f (get-date),$_.FullyQualifiedErrorId) Write-Output ('[{0:O}] Category: {1}' -f (get-date),(($_.Exception.GetType() | Select-Object -ExpandProperty UnderlyingSystemType).FullName)) } } end { $ErrorActionPreference = 'Continue' } } #EndRegion '.\Public\Set-LocalUserPassword.ps1' 93 |