Permissions to access WMI remotely

Accessing WMI on a remote machine is pretty mundane for System Admins. They do not even think about it, they have Administrator rights, and it works (for the most part).

In my case, I needed to run a script with a service account and connect from one Windows 2008 R2 Server to another. I needed to figure out what permissions that account should have on the server, short of making the service account an admin. How difficult this can be? Well, it proved to be more difficult to find information on this than I thought it would be.

Here is what happens if the service (domain) account I use tries to access remote server, where it does not have any permissions:

PS> gwmi win32_ComputerSystem -ComputerName
gwmi : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
At line:1 char:1
+ gwmi win32_ComputerSystem -ComputerName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
I looked at several resources including venerable StackOverflow, where I have found several responses to this type of questions but none worked for my case.

There are many KB articles on the subject. This dated MSDN article claimed that you need to be admin on the target box. WMI Troubleshooting, Connecting to WMI on a Remote Computer by Using Windows PowerShell,

I asked in PowerShell Community Group chat, where Joel "Jaykul" Bennett pointed me to this article.

All of them helped, but in the end, I had to find my own solution to it:

1) Add the user to 'Distributed DCOM Users' group on the target server
2) Grant WMI permissions to user by following the steps below:

  • Launch compmgmt.msc and connect to target server
  • Right click on Services and Applications > WMI Control and select "Properties"
  • Click Root (CIMV2 did not seem to work but see update below) and then "Security"
  • Add the domain user and click on "Advanced"
  • Double click on user name
  • Change Applies to to "This namespace and subnamespaces"
  • Click on "Remote Enable" checkbox and hit "OK"
See screenshots below.

Note that I only needed read access. If you need to write or execute WMI methods, then additional checkboxes (Execute Methods, * write) will need to be added.

Update 2013-10-17:
I got an e-mail from Colyn, who had helped answering the question on StackOverflow thread asking me if  adding user to "WinRMRemoteWMIUsers__" group would work for me.

I did not have that option because that group did not exist on the server, which had PowerShell version 2. CIM cmdlets became available with PowerShell v3, so I guess that explained why.

However, I had access to another Windows 2008 R2 server with PowerShell3. Sure enough, that server had the group. the group definition says:
"Members of this group can access WMI resources over management protocols (such as WS-Management via the Windows Remote Management service). This applies only to WMI namespaces that grant access to the user."

On target server:
1) I added domain test user to  "WinRMRemoteWMIUsers__".
2) I granted both "Enable Account" & "Remote Enable" access to  Root/CIMV2 namespace

Get-WMIObject call failed with the same access denied error:

PS D:\> get-wmiobject win32_ComputerSystem -Computer TEST01
gwmi : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
At line:1 char:1
+ gwmi win32_ComputerSystem -Computer TEST01
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Similarly, Get-CimInstance with DCOM protocol fails as well

PS D:\> $cimoption = New-CimSessionOption -Protocol Dcom
PS D:\> new-cimsession -computername -SessionOption $cimoption
new-cimsession : Access is denied.
   + FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infrastructure .CimCmdlets.NewCimSessionCommand

But Get-CimInstance cmdlet which uses WS-MAN protocol succeeded:

PS D:\> get-ciminstance -classname win32_ComputerSystem -ComputerName TEST01

Name             PrimaryOwn Domain     TotalPhysi Model     Manufactu PSCompute
                 erName                calMemory            rer       rName
----             ---------- ------     ---------- -----     --------- ---------
TEST01    Windows...   4026064896 VMware... VMware... TEST01...

Here is another twist to this story. If I use the dns alias instead of actual hostname, Get-CimInstance too returned an error, but return code is different (0x80070035).

Another note: if you will be playing with the WMI permissions, you may sometimes see unexpected results if you do not restart WMI service (get-service winmgmt | restart-service -force)  after making a change. For example: I wanted to test removing "Remote Enable" permission and see if I would still be able to use Get-CimInstance. To my surprise it worked for a while...until I restarted the service. Then I started to get errors (HRESULT 0x80041004). I had to add back the "Remote Enable" and restart WMI service to get it back up.

Finally, here are a couple more useful links:

No comments: