Nagios Issue - gwmi : The RPC server is unavailable - powershell

I'm struggling with a problem regarding the RPC server being unavailable specifically for a Nagios script written in PowerShell.
When the script is run locally, it runs perfectly and as expected. When it is called via the NRPE agent and run by the nscp service, it fails with this error:
gwmi : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At C:\Program Files\NSClient++\scripts\check_win_uptime.ps1:30 char:8
+ $wmi = gwmi Win32_OperatingSystem -computer $ServerName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands
.GetWmiObjectCommand
The guts of the script (or relevant parts) are this:
$wmi = gwmi Win32_OperatingSystem -computer $ServerName
$LBTime = $wmi.ConvertToDateTime($wmi.Lastbootuptime)
[TimeSpan]$uptime = New-TimeSpan $LBTime $(get-date)
No firewall is running and for testing purposes, all ports are open to the server.
Any suggestions are greatly appreciated.
Mike

RPC Server Unavailable is almost always not having enabled the right settings in Windows firewall. See this very old topic I got written for MSDN while on the WMI team to document the issue.
Connecting thru Windows Firewall

Get-wmiobject -computer is very finicky. This works for me:
$c = get-credential
Get-WmiObject -Class win32_computersystem -ComputerName comp001 -Credential $c
But other forms give the "Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" error:
Get-WmiObject win32_computersystem -ComputerName comp001 -Credential $c
Get-WmiObject -Class win32_computersystem -ComputerName comp001 # running as same domain user as creds
So it looks like -Class and -Credential are mandatory.
Sometimes only something like this works:
Get-WmiObject -ComputerName comp001 -Credential "dom\js" -Query "SELECT * FROM Win32_ComputerSystem"

I have encountered the problem alike but via CMD using tasklist to view remote processes. The answer is related to firework config. Convert this to a PowerShell command and it will solve your problem.
netsh advfirework firework set rule group="windows management instrumentation (wmi)" new enable=yes

Related

New-PSSession - WinRM cannot process the request

I am trying to list all the websites in IIS on a remote server using PowerShell scripting. Below is how I am trying to connect to the server:
$s = New-PSSession -ComputerName $Server
But when I run the script I am getting the following error:
New-PSSession : [Server] Connecting to remote server Server failed with the
following error message : WinRM cannot process the request. The following error
occurred while using Kerberos authentication: Cannot find the computer Server.
Verify that the computer exists on the network and that the name provided is
spelled correctly. For more information, see the about_Remote_Troubleshooting
Help topic.
At C:\AppServers\Application.ps1:8 char:8
+ $s = New-PSSession -ComputerName Server
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : NetworkPathNotFound,PSSessionOpenFailed
The server is already enabled to receive remote requests.
Update:
Below is the full function that i am trying to run:
function audit-servers {
if (Test-path "ApplicationsOnTheServer.txt") {Remove-Item "ApplicationsOnTheServer.txt"}
if (Test-Path "ServersList.txt") {
foreach ($server in Get-Content .\ServersList.txt) {
"Application Server : $server`n" | out-file -FilePath "ApplicationsOnTheServer.txt" -Append
"Applications list:" | out-file -FilePath "ApplicationsOnTheServer.txt" -Append
$s = New-PSSession -ComputerName $server -Credential domainabc\myname
Invoke-Command -Session $s -ScriptBlock {Import-Module WebAdministration;Get-iissite} | out-file -FilePath "ApplicationsOnTheServer.txt" -Append
}
} else {
"ServersList.txt file is missing"
break;
}
"`nAll Done!`n"}
The ServersList.txt has atstappvmabc.tsteag.com
The error message clearly states that you wanted to connect to the server named Server not to the server which name is stored in $Server variable (text in bold is actually the name of the server you try to connect to):
New-PSSession : [Server] Connecting to remote server Server failed
If you tried to connect to the server named for example MyServer01.example.com you'd receive the error like below (truncated):
PS C:\> New-PSSession -ComputerName "MyServer01.example.com"
New-PSSession : [MyServer01.example.com] Connecting to remote server MyServer01.example.com failed (...)
Even though you state that you try to execute
$s = New-PSSession -ComputerName $Server
You actually execute (notice missing dollar sign)
$s = New-PSSession -ComputerName Server
The above was also taken from the error message you pasted. I'd suggest to first skip the variable and try to enter server path in the command itself to verify it's working:
$s = New-PSSession -ComputerName "MyServer01.example.com"
And then, if it works, put the path in variable and test again.
The error you're receiving FullyQualifiedErrorId : NetworkPathNotFound generally means that the name you're passing to the -ComputerName parameter can't be resolved.
Perhaps try running Test-Connection $Server to troubleshoot what's happening there.
Your variable $Server contains wrong value. You have to assign valid computer name to $Server.

find service account on remote hosts

Could you please advise how to find all servers where a specific service account is being used to start Windows services?
I am trying this in PowerShell with these code:
Clear-Host
$address = Get-Content '.\asg connections.csv'
$serviceName = "startname='NT AUTHORITY\\LocalService'"
gwmi Win32_Service -Filter $serviceName -Computer $address
Above piece of code works for "localhost", but gives below error for the remote hosts:
gwmi : Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
At F:\Temp\powershell\play.ps1:30 char:1
+ gwmi win32_service -filter $serviceName -computer $address
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
When you use PowerShell remoting you implicitly trying to use the credentials your current Windows session is logged into your machine with on the target machines.
It looks like you do not have any rights with your current set of credentials on those machines.
Are the target machines joined into the same domain as your current user credentials?
If you have a set of working credentials you can log onto those machines with, you can add it in your command with:
Clear-Host
#Promts you for the username and password you wish to save to a credential object
$Cred = Get-Credential
$address = Get-Content '.\asg connections.csv'
$serviceName = "startname='NT AUTHORITY\\LocalService'"
gwmi Win32_Service -Filter $serviceName -Computer $address -Credential $Cred
If the script needs to run automated there are a few different ways to save credential passwords either into an encrypted textfile that can only be decrypted by the user account that encrypted it, or using the build in Windows Credential Vault.

Get-WmiObject doesn't work with IP but with FQDN

I have the following PowerShell script.
Code:
$User = "DOMAIN\user"
$PWord = ConvertTo-SecureString -String "somePassword" -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
$query=...
Get-WmiObject -Computer 192.168.172.10 -Class Win32_ComputerSystem -ErrorAction Stop # Fails
Get-WinEvent -FilterXML $query -ComputerName 192.168.172.10 -Credential $Credential -ea stop # Works
Situation: I'm on a AD server with an IP like 192.168.1.1 and executing my script. [AD has access rights for all subnets and there is no firewall blocking access]
Issue: I want to query the following computer: server1 with ip 192.168.172.10 then this:
Get-WmiObject -Computer 192.168.172.10 -Class Win32_ComputerSystem -ErrorAction Stop # Fails
fails with an "RPC-Server is unavailable" error but this:
Get-WmiObject -Computer server1 -Class Win32_ComputerSystem -ErrorAction Stop # Works
works and this works too:
Get-WinEvent -FilterXML $query -ComputerName 192.168.172.10 -Credential $Credential -ea stop # Works
The server is in the same domain like the AD and Windows Firewall is for testing purposes disabled.
And a different server "server2" with ip 192.168.172.11 is working both ways with FQDN and ip.
Does anyone have an idea why in some cases (5 out of hundrets) the Get-WmiObject fails with ip but works with FQDN?
I searched about similar issues but all are about WinRM and are using commands like Invoke-Command. For sure WinRM first needs to be configured right in that case, but as far as I understood Get-WmIObject does not need WinRM. (I have not done any configuration tasks on all the computers).
The issue what you are facing is because of the reverse DNS records.
In your case, you might have multiple RDNS records for the same IP, causing the problem to be intermittent.
Check your reverse lookup zone and the the corresponding PTR records.
That should solve your issue.
Hope it helps.

Get-WmiObject credentials not working when scheduled

I have a Powershell script to detect disk space on a network server that requires a user/password to access it.
I followed this: http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/440ab7ed-7727-4ff7-a34a-6e69e2dff251/
To get this code:
$password = get-content C:\creds.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "username",$password
Get-WmiObject -ErrorAction Stop Win32_LogicalDisk -ComputerName $deviceName -credential $cred -Filter "DeviceID='$darg'"
$deviceName and $darg are already correctly defined.
This works just fine when running the Powershell script manually. But when I set it up as a Windows schedule task, it fails thinking the user/pass is incorrect:
Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESS
DENIED))
$disks = Get-WmiObject <<<< -ErrorAction Stop Win32_LogicalDisk -ComputerName $deviceName -credential $cred -Filter
"DeviceID='$darg'"
+ CategoryInfo : NotSpecified: (:) [Get-WmiObject], Unauthorized AccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Why is this? (The account is a local user on the remote server. I've tried entering the credentials on the Schedule interface but it doesn't let me save it, saying invalid login; maybe due to being a local account) ServerName\LocalUser does not work in the Windows Schedule UI, still gives the incorrect login error.
Here is my comment, re-worded as an answer.
The convertto/from-securestring functions work on a per-user basis (if you don't provide a specific key value). IOW, one user can't read another user's data.
This pre-existing SO question seems relevant. There is also relevant discussion at Powershellcommunity.org.
why dont you set the task to run under the user account and run the wmi request without credential ?

PowerShell code works interactively, but not inside a script

Salutations!
So, I was just on my daily routine of some powershell programming and I got to this little fella:
Get-WmiObject : Invalid class
At line:184 char:19
+ $RECApp = gwmi <<<< Win32_product | ? {$_.Name.Contains($Application)}
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId: GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
The funny thing is that this error is only shown when the code is executed from a script, but when manually entered into the command line the same code works. I don't know if this has something to do with the remote machine which I'm executing the script on, but why should it, if it works when entered manually but not when executed from the script. I'll get you a piece of my code here:
Enter-PSSession -ComputerName $serverName
$App = gwmi Win32_product | ? {$_.Name.Contains($Application)}
$App.Uninstall();
exit
To summarize, why does this code work like a charm when entered manually to the command line, but when executed form a script I get the above error?
Thanks.
Enter-PSSession is for interactive use only. If you put that line in a script, the subsequent lines do not run in a remote session. If you want to run some script remotely, within a script, you would do something like this instead:
$session = New-PSSession -ComputerName $serverName
Invoke-Command -Session $session {
param($name)
$App = gwmi Win32_product | ? {$_.Name.Contains($name)}
$App.Uninstall();
} -arguments $application
There's a bit of a gotcha there as I have to pass $application as an argument to Invoke-Command because that variable does not exist on the remote session. Stepping back a bit, you could write the above a bit simpler like this:
$app = gwmi -computer $servername win32_product | ? {
$_.name.contains($application)
}
Now, the problem with this is that you are pulling all win32_product objects back from the server and filtering on the local machine. This is a lot of unneccessary network traffic. It would be faster if you could filter on the remote machine, so let's modify it a bit more:
$app = gwmi -computer $servername -query `
"select * from win32_product where name = '$application'"
$app.Uninstall()
Now only the win32_product you want will be retrieved from the remote machine. I haven't tested the above gwmi -computer variants, so it's more illustrative of technique and syntax. You may have to play a bit with it.