SCCM Script: Fix Kerberos Authentication Errors
Overview
At times, SCCM client machines may lose the ability to communicate properly with the SCCM site server due to Kerberos authentication errors. You will see these errors in Deployment Statuses or other times invoking PowerShell scripts on remote clients.
This script attempts to invoke a generic script remotely on an imported set of SCCM clients and determine if there is a Kerberos authentication error:
Invoke-Command -ComputerName $h -ScriptBlock { Test-Connection SCCMSERVER -Quiet -Count 1 } -ErrorAction Stop
If the invocation returns the exception error System.Management.Automation.Remoting.PSRemotingTransportException you can assume there is an error and we can remotely instruct a CLI through WinRM:
$command = "C:\ADMIN`\PSTools\PsExec.exe \\$h /s /accepteula /nobanner cmd /c `"Winrm quickconfig /q`""
Therefor it is a prerequisite that you have PsExec.exe in the C:\ADMIN\PSTools\ directory of the PC before running the script, as shown above.
The script will also try to resolve DNS issues that may be related to the error.
Fixing Kerberos Errors on an Imported List of Computers
You can import a generic list of computers via a CSV that is in the following format:
Fix-DGMKerberosError –CSV \\Pathto\the.csv
Logging Output
The function outputs its progress to a log file and is fully compatible with CMTrace.exe.
PowerShell Function
<#
.Synopsis
Fix SCCM Kerberos Errors
.DESCRIPTION
The tool, Fix-DMGKerberosError.ps1 was written by David Maiolo which will attempt to fix Kerberos Authentican Issues on remote computers.
.EXAMPLE
Fix-DMGKerberosError -CSVFile kerberos_error_import.csv
.EXAMPLE
Fix-DMGKerberosError -Hostname LT061222
#>
function LogIt
{
param (
[Parameter(Mandatory=$true)]
$message,
[Parameter(Mandatory=$true)]
$component,
[Parameter(Mandatory=$true)]
$type )
switch ($type)
{
1 { $type = "Info" }
2 { $type = "Warning" }
3 { $type = "Error" }
4 { $type = "Verbose" }
}
if (($type -eq "Verbose") -and ($Global:Verbose))
{
$toLog = "{0} `$$<{1}><{2} {3}>" -f ($type + ":" + $message), ($Global:ScriptName + ":" + $component), (Get-Date -Format "MM-dd-yyyy"), (Get-Date -Format "HH:mm:ss.ffffff"), $pid
$toLog | Out-File -Append -Encoding UTF8 -FilePath ("filesystem::{0}" -f $Global:LogFile)
Write-Host $message
}
elseif ($type -ne "Verbose")
{
$toLog = "{0} `$$<{1}><{2} {3}>" -f ($type + ":" + $message), ($Global:ScriptName + ":" + $component), (Get-Date -Format "MM-dd-yyyy"), (Get-Date -Format "HH:mm:ss.ffffff"), $pid
$toLog | Out-File -Append -Encoding UTF8 -FilePath ("filesystem::{0}" -f $Global:LogFile)
if ($type -eq 'Info') { Write-Host $message }
if ($type -eq 'Warning') { Write-Host $message -ForegroundColor Yellow}
if ($type -eq 'Error') { Write-Host $message -ForegroundColor Red}
}
if (($type -eq 'Warning') -and ($Global:ScriptStatus -ne 'Error')) { $Global:ScriptStatus = $type }
if ($type -eq 'Error') { $Global:ScriptStatus = $type }
if ((Get-Item $Global:LogFile).Length/1KB -gt $Global:MaxLogSizeInKB)
{
$log = $Global:LogFile
Remove-Item ($log.Replace(".log", ".lo_"))
Rename-Item $Global:LogFile ($log.Replace(".log", ".lo_")) -Force
}
}
function GetScriptDirectory
{
$invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $invocation.MyCommand.Path
}
function Fix-DMGKerberosError
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
Position=0,
ParameterSetName='Parameter Set 1')]
[ValidateScript({(Test-Path $_)})]
$CSVFile,
# Param2 help description
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
Position=0,
ParameterSetName='Parameter Set 2')]
[ValidateScript({(Get-ADComputer -Identity $_).objectclass -eq 'computer' })]
[String]$Hostname
)
Begin
{
$path = (get-item -Path .).FullName
if ($CSVFile -ne $null){
Write-Host Importing $CSVFile...
$csv = import-csv "$CSVFile"
}else{
$csv = [PSCustomObject]@{
Hostname = $Hostname}
}
Write-Host ==========================================
Write-Host SCCM Kerberos Remote Execution Fix Tool
Write-Host ==========================================
Write-Host "v0.1 (2017-12-20) by dmaiolo"
LogIt -message ("Starting Logging for Fix-DMGKerberosError") -component "Main()" -type 1
}
Process
{
$computers = @();
$csv | foreach-object {
$h = $_.Hostname
if(Test-Connection -ComputerName $h -Count 1 -Quiet){
Write-Host "$h`: Invoking Generic Command (Test-Connection SCCMSERVER -Quiet -Count 1)..."
Try{
Invoke-Command -ComputerName $h -ScriptBlock { Test-Connection SCCMSERVER -Quiet -Count 1 } -ErrorAction Stop
LogIt -message ("$h`: Generic Command (Test-Connection SCCMSERVER -Quiet -Count 1) Ran Succesfully. No Fix Required.") -component "Main()" -type 1
}
Catch [System.Management.Automation.Remoting.PSRemotingTransportException]{
LogIt -message ("$h`: Kerberos Issue Detected. Fix Required") -component "Main()" -type 2
Write-Host "$h`: Attempting to Repair WinRM for Kerberos Authentication..."
$command = "C:\ADMIN`\PSTools\PsExec.exe \\$h /s /accepteula /nobanner cmd /c `"Winrm quickconfig /q`""
if($expression = Invoke-Expression -Command:"$command" -ErrorAction Stop) {
LogIt -message ("$h`: WinRM Repair Ran Succesfully for Kerberos Authentication") -component "Main()" -type 1
}
else{
LogIt -message ("$h`: WinRM Repair NOT Succesfull for Kerberos Authentication") -component "Main()" -type 3
LogIt -message ("$h`: Attempting DNS Repair by running PsExec for ipconfig /registerdns against the IP Address... ") -component "Main()" -type 1
try{
$IPv4AddressPinged = (Test-Connection -ComputerName $h -Count 1 -ErrorAction SilentlyContinue).IPV4Address.IPAddressToString
LogIt -message ("$h`: Found a valid IP Address To Invoke-Expression against ($IPv4AddressPinged).") -component "Main()" -type 1
$RealHostName = (Resolve-DnsName $IPv4AddressPinged).NameHost
LogIt -message ("$h`: Your DNS has accociated $h to $IPv4AddressPinged, but it acually belongs to $RealHostName. This is part of your problem.") -component "Main()" -type 1
}
catch{
LogIt -message ("$h`: No Valid IP Address for this host could be determined.") -component "Main()" -type 3
$RealHostName = $false
$IPv4AddressPinged = $false
}
if ($IPv4AddressPinged){
$command2 = "C:\ADMIN\PSTools\PsExec.exe \\$IPv4AddressPinged /s /accepteula /nobanner cmd /c `"ipconfig /registerdns`""
if(Invoke-Expression -Command:"$command2"){
LogIt -message ("$h`: ($RealHostName) Succesfully Ran $command2.") -component "Main()" -type 1
Write-Host "$h`: ($RealHostName) Attempting to Repair WinRM for Kerberos Authentication against IP Address ($IPv4AddressPinged)..."
$command3 = "C:\ADMIN`\PSTools\PsExec.exe \\$IPv4AddressPinged /s /accepteula /nobanner cmd /c `"Winrm quickconfig /q`""
if($expression2 = Invoke-Expression -Command:"$command3" -ErrorAction Stop) {
LogIt -message ("$h`: ($RealHostName) WinRM Repair Ran Succesfully for Kerberos Authentication against IP Address ($IPv4AddressPinged)") -component "Main()" -type 1
}
else{
LogIt -message ("$h`: ($RealHostName) WinRM Repair NOT Succesfull for Kerberos Authentication against IP Address ($IPv4AddressPinged)") -component "Main()" -type 3
}
}
else{
LogIt -message ("$h`: ($RealHostName) Unable to Run $command2.") -component "Main()" -type 3
}
}
}
}
Catch{
LogIt -message ("$h`: Generic Command (Test-Connection SCCMSERVER -Quiet -Count 1) Ran Into a Non-Kerberos Issue. Fix Unknown.") -component "Main()" -type 3
}
}
else{
LogIt -message ("$h`: is offline.") -component "Main()" -type 2
}
}
}
End
{
Write-Host ===============================================================
Write-Host Log File of Results Generated at $Global:LogFile VIEW WITH CMTRACE.EXE
LogIt -message ("Ending Logging for Fix-DMGKerberosError") -component "Main()" -type 1
}
}
$VerboseLogging = "true"
[bool]$Global:Verbose = [System.Convert]::ToBoolean($VerboseLogging)
#$Global:LogFile = Join-Path (GetScriptDirectory) "Fix-DMGKerberosError_$(Get-Date -Format dd-MM-yyyy).log"
$Global:LogFile = Join-Path (GetScriptDirectory) "Fix-DMGKerberosError.log"
$Global:MaxLogSizeInKB = 10240
$Global:ScriptName = 'Fix-DMGKerberosError.ps1'
$Global:ScriptStatus = 'Success'
Leave a Reply
Want to join the discussion?Feel free to contribute!