Ansible managing Windows hosts with non admin user

2,925 views
Skip to first unread message

Julian Saunders

unread,
Feb 20, 2016, 11:35:17 AM2/20/16
to Ansible Project
Hello,

I use Ansible to manage Linux hosts and just recently had a requirement to manage Windows Servers.

I have Ansible working against a Windows 2012 R2 host using an account (test_user) that is part of the "administrators" group.

I would like reduce the rights of test_user, so it is no longer in the "administrators" group, but can still connect and copy files to its own homedrive, and basically run commands that a user that is part of the "Users" group can.

On removing the user Ansible provives the following error:

fatal: [servername] => 401 Unauthorized. basic auth failed

I did a bit of research and found the user needed to be part of the "Remote Management Users", this would allow test_user to run Powershell remotely.  I tested this from another Windows host, and yes it works.
 
PS> $options=New-PSSessionOption -SkipCACheck -SkipCNCheck
PS> Enter-PSSession -ComputerName servername -Credential servername\test_user -UseSSL -SessionOption $options

However via Ansible I get the following error:

fatal: [servername] => failed to exec cmd PowerShell -NoProfile -NonInteractive -EncodedCommand...

Does anyone know if it's possible to run Ansible against a Windows hosts with a non admin user?

Thanks.

J Hawkesworth

unread,
Feb 22, 2016, 5:31:33 AM2/22/16
to Ansible Project
From here it looks like this is possible, although you would have to tweak user rights:


I get the impression that the intention for WinRM is for admistrative access, however.  Have a look at the first paragraph of this page:  https://msdn.microsoft.com/en-us/library/windows/desktop/aa384295(v=vs.85).aspx

Hope this helps.

Please report back if you are able to get this working - knowing the minimal set of user rights would be useful for others I think,

Jon

Trond Hindenes

unread,
Feb 23, 2016, 4:51:25 AM2/23/16
to Ansible Project
Interesting. My guess would be that this works, as Ansible doesn't do anything outside the logged-on user's profile (until you start pushing tasks that require admin access, of course). What is the exact error you're getting? Can you use the "raw" module to do something simple like list the contents of your profile or something? I'd really like to see the full verbose log from your console aswell.

Julian Saunders

unread,
Feb 25, 2016, 6:13:22 PM2/25/16
to Ansible Project
I was using the win_ping module. I will try the raw module as suggested.

I will also play around with "allow on Execute Methods and Remote enable" once I work out what and where they are set.

Thanks guys. I will report back soon.

Julian Saunders

unread,
Feb 26, 2016, 1:33:01 PM2/26/16
to Ansible Project
I have since tried win_ping and raw, but I haven't had time to test "allow on Execute Methods and Remote enable" on the windows server.

Both modules work fine when I'm a local admin on the windows server.

Both fail at the "Gather Facts" when I'm not a local admin.

ansible windows -i inventory/dev/hosts -m win_ping
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 161, in exec_command
    result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 122, in _winrm_exec
    self.shell_id = self.protocol.open_shell()
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 121, in open_shell
    rs = self.send_message(xmltodict.unparse(rq))
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 193, in send_message
    return self.transport.send_message(message)
  File "/usr/lib/python2.6/site-packages/winrm/transport.py", line 136, in send_message
    raise WinRMTransportError('http', error_message)
WinRMTransportError: 500 WinRMTransport. Bad HTTP response returned from server.  Code 500
<servername> | FAILED => failed to exec cmd PowerShell -NoProfile -NonInteractive -EncodedCommand

I disabled gathering facts and get the same error message.

My output from the raw module:

ansible-playbook -i inventory/dev/hosts playbooks/test_windows.yml

PLAY [test script module] *****************************************************

TASK: [run ipconfig] **********************************************************
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 161, in exec_command
    result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 122, in _winrm_exec
    self.shell_id = self.protocol.open_shell()
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 121, in open_shell
    rs = self.send_message(xmltodict.unparse(rq))
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 193, in send_message
    return self.transport.send_message(message)
  File "/usr/lib/python2.6/site-packages/winrm/transport.py", line 136, in send_message
    raise WinRMTransportError('http', error_message)
WinRMTransportError: 500 WinRMTransport. Bad HTTP response returned from server.  Code 500
fatal: [<servername>] => failed to exec cmd ipconfig

FATAL: all hosts have already failed -- aborting

Julian Saunders

unread,
Feb 26, 2016, 2:14:14 PM2/26/16
to Ansible Project
I managed to find the root/CIMV2 namespace, and I set the security permissions of "Execute Methods" and "Remote Enable" and restarted the WMI and WinRM services.  Unfortunately I still receive the same error.

As I mentioned, I can use WinRM from another Windows server via Powershell session, without having to have an admin account.  Once I have connected I'm able to run cmd or ipconfig.

I wonder what Ansible is doing?  

J Hawkesworth

unread,
Feb 26, 2016, 2:46:40 PM2/26/16
to Ansible Project
could you try running playbook with -vvvvvv
this should show a bit more information about how ansible is connecting

also check the event log on the windows host to see if the login request is a success.

Something else you could try is to run the python pywinrm example here against your host:

https://github.com/diyan/pywinrm

Hopefully this should help isolate the problem.

Jon

Julian Saunders

unread,
Feb 27, 2016, 5:29:45 AM2/27/16
to Ansible Project
Thank you for your help.

win_ping module verbose, without local admin on remote windows hosts:

[<user>@<servername> winRM]$ ansible windows -i inventory/dev/hosts -m win_ping -vvvv
<<servernaem>> ESTABLISH WINRM CONNECTION FOR USER: test_user on PORT 5986 TO <servernaem>
<<servernaem>> WINRM CONNECT: transport=plaintext endpoint=https://<servernaem>:5986/wsman
<<servernaem>> REMOTE_MODULE win_ping
<<servernaem>> EXEC (New-Item -Type Directory -Path $env:temp -Name "ansible-tmp-1456562221.68-167539675202015").FullName | Write-Host -Separator '';
<<servernaem>> WINRM EXEC 'PowerShell' ['-NoProfile', '-NonInteractive', '-EncodedCommand', 'KABOAGUAdwAtAEkAdABlAG0AIAAtAFQAeQBwAGUAIABEAGkAcgBlAGMAdABvAHIAeQAgAC0AUABhAHQAaAAgACQAZQBuAHYAOgB0AGUAbQBwACAALQBOAGEAbQBlACAAIgBhAG4AcwBpAGIAbABlAC0AdABtAHAALQAxADQANQA2ADUANgAyADIAMgAxAC4ANgA4AC0AMQA2ADcANQAzADkANgA3ADUAMgAwADIAMAAxADUAIgApAC4ARgB1AGwAbABOAGEAbQBlACAAfAAgAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAtAFMAZQBwAGEAcgBhAHQAbwByACAAJwAnADsA']
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 161, in exec_command
    result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 122, in _winrm_exec
    self.shell_id = self.protocol.open_shell()
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 121, in open_shell
    rs = self.send_message(xmltodict.unparse(rq))
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 193, in send_message
    return self.transport.send_message(message)
  File "/usr/lib/python2.6/site-packages/winrm/transport.py", line 136, in send_message
    raise WinRMTransportError('http', error_message)
WinRMTransportError: 500 WinRMTransport. Bad HTTP response returned from server.  Code 500
<servernaem> | FAILED => failed to exec cmd PowerShell -NoProfile -NonInteractive -EncodedCommand KABOAGUAdwAtAEkAdABlAG0AIAAtAFQAeQBwAGUAIABEAGkAcgBlAGMAdABvAHIAeQAgAC0AUABhAHQAaAAgACQAZQBuAHYAOgB0AGUAbQBwACAALQBOAGEAbQBlACAAIgBhAG4AcwBpAGIAbABlAC0AdABtAHAALQAxADQANQA2ADUANgAyADIAMgAxAC4ANgA4AC0AMQA2ADcANQAzADkANgA3ADUAMgAwADIAMAAxADUAIgApAC4ARgB1AGwAbABOAGEAbQBlACAAfAAgAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAtAFMAZQBwAGEAcgBhAHQAbwByACAAJwAnADsA


raw module (ipconfig) verbose, without local admin on remote windows hosts:

[<user>@<servername> winRM]$ ansible-playbook -i inventory/dev/hosts playbooks/test_windows.yml -vvvv

PLAY [test script module] *****************************************************

TASK: [run ipconfig] **********************************************************
<<servernaem>> ESTABLISH WINRM CONNECTION FOR USER: test_user on PORT 5986 TO <servernaem>
<<servernaem>> WINRM CONNECT: transport=plaintext endpoint=https://<servernaem>:5986/wsman
<<servernaem>> EXEC ipconfig
<<servernaem>> WINRM EXEC 'ipconfig' []
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 161, in exec_command
    result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
  File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/winrm.py", line 122, in _winrm_exec
    self.shell_id = self.protocol.open_shell()
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 121, in open_shell
    rs = self.send_message(xmltodict.unparse(rq))
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 193, in send_message
    return self.transport.send_message(message)
  File "/usr/lib/python2.6/site-packages/winrm/transport.py", line 136, in send_message
    raise WinRMTransportError('http', error_message)
WinRMTransportError: 500 WinRMTransport. Bad HTTP response returned from server.  Code 500
fatal: [<servernaem>] => failed to exec cmd ipconfig

FATAL: all hosts have already failed -- aborting

I don't see any errors in the numerous windows logs, but I do see a successful logon:

An account was successfully logged on.

Subject:
Security ID: NETWORK SERVICE
Account Name: <servername>$
Account Domain: MHF
Logon ID: 0x3E4

Logon Type: 3

Impersonation Level: Impersonation

New Logon:
Security ID: <servernaem>\test_user
Account Name: test_user
Account Domain: <servername>
Logon ID: 0x19F85BC2C
Logon GUID: {00000000-0000-0000-0000-000000000000}


pywinrm:

The examples use http, which I haven't been using.  I therefore included transport over SSL.

Without admin:

import winrm
s = winrm.Session('<servername>', auth=('test_user', '**********'),transport='ssl')
r = s.run_cmd('ipconfig', ['/all'])
print r.std_out

Traceback (most recent call last):
  File "./process_remote_host.py", line 6, in <module>
    r = s.run_cmd('ipconfig', ['/all'])
  File "/usr/lib/python2.6/site-packages/winrm/__init__.py", line 29, in run_cmd
    shell_id = self.protocol.open_shell()
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 121, in open_shell
    rs = self.send_message(xmltodict.unparse(rq))
  File "/usr/lib/python2.6/site-packages/winrm/protocol.py", line 193, in send_message
    return self.transport.send_message(message)
  File "/usr/lib/python2.6/site-packages/winrm/transport.py", line 136, in send_message
    raise WinRMTransportError('http', error_message)
winrm.exceptions.WinRMTransportError: 500 WinRMTransport. Bad HTTP response returned from server.  Code 500

With admin:

Windows IP Configuration

   Host Name . . . . . . . . . . . . : <servername>
   Primary Dns Suffix  . . . . . . . : <domain>
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
...


Please note it is an identical error for "Run powershell on remote host"

You can see it's the same error when running via Ansible, as it is when I run directly from pywinrm. 

I can think of a couple more options:

Get pywinrm working without SSL, and see where that takes me.  I will need to make changes on the Windows host for this, because unencrypted traffic is currently not allowed.  This was intended, I wanted to use SSL only.
I tested this from another windows server:
"Message = The WinRM client cannot process the request. Unencrypted traffic is currently disabled in the client configuration. Change the client configuration and try the request again."

Or I take a closer look at pywinrm.

I don't have time to do either this weekend.  Hopefully I will get some time next week.

J Hawkesworth

unread,
Feb 27, 2016, 12:55:10 PM2/27/16
to Ansible Project
Thanks for this.

Since ansible and pywinrm are behaving the same, it occurs to me that the winrm configuration might not suit pywinrm.

From the above it appears you have created specific configuration for winrm, rather than using the settings that are applied if you run the ConfigureRemotingForAnsible.ps1.

I suggest you run the ConfigureRemotingForAnsible.ps1 script on a windows host and then compare the winrm configuration with your test machine.

You can see the winrm config by running

Winrm get winrm/config

From memory, pywinrm can not use credssp authorisation,

Is your test user a member of the WinRMRemoteWMIUsers__ group? I wouldn't expect anything to work if not but just trying to understand what you have in place.

Hope this helps,

Jon

Julian Saunders

unread,
Feb 29, 2016, 11:11:52 AM2/29/16
to Ansible Project
Yes you are right.  I tried running ConfigureRemotingForAnsible.ps1 but it failed.  I'm sorry I don't have the error message.

I have little experience of Powershell, but I managed to work through the script and run the individuals settings manually.  Of course I could have missed something, but it seemed to work fine with Ansible once I was part of the administrators group on the Windows host.

Luckily I have access to another Windows servers (server B), and for this the script ConfigureRemotingForAnsible.ps1 works.  Also I hadn't placed the user in the WinRMRemoteWMIUsers__ group.

Unfortunately I'm receiving the same errorr, and like with Server A, as soon as I add my user to the administrators group, all works fine. 

I've compared the WinRM settings across the two servers.  Server A was configured manually, and Server B via ConfigureRemotingForAnsible.ps1.  They are both the same:

Config
    MaxEnvelopeSizekb = 500
    MaxTimeoutms = 60000
    MaxBatchItems = 32000
    MaxProviderRequests = 4294967295
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = true
            Digest = true
            Kerberos = true
            Negotiate = true
            Certificate = true
            CredSSP = false
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        TrustedHosts
    Service
        RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
        MaxConcurrentOperations = 4294967295
        MaxConcurrentOperationsPerUser = 1500
        EnumerationTimeoutms = 240000
        MaxConnections = 300
        MaxPacketRetrievalTimeSeconds = 120
        AllowUnencrypted = false
        Auth
            Basic = true
            Kerberos = true
            Negotiate = true
            Certificate = false
            CredSSP = false
            CbtHardeningLevel = Relaxed
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        IPv4Filter = *
        IPv6Filter = *
        EnableCompatibilityHttpListener = false
        EnableCompatibilityHttpsListener = false
        CertificateThumbprint
        AllowRemoteAccess = true
    Winrs
        AllowRemoteShellAccess = true
        IdleTimeout = 7200000
        MaxConcurrentUsers = 10
        MaxShellRunTime = 2147483647
        MaxProcessesPerShell = 25
        MaxMemoryPerShellMB = 1024
        MaxShellsPerUser = 30


Do we know if anyone that has got this working with a user that is not part of the administrators group? 

helpde...@gmail.com

unread,
Jun 6, 2016, 3:16:17 PM6/6/16
to Ansible Project
Hello,
Just to share my tests, I face exactly the same issues with the same configuration (same user on a windows box can run remote Powershell commands even when not in administrators group).
I tried with local user and basic auth and domain user with Kerberos. As soon as the user is member of the local Administrators group he can run remote shell commands, if not (I even created a dedicated groupe POSH-RemoteUsers in the domain and provided it with appropriate rights) I get the "winrm.exceptions.WinRMTransportError: 500 WinRMTransport. Bad HTTP response returned from server.  Code 500" error.

Will try to debug a bit further but with little hope.

Patrick

Matt Davis

unread,
Jun 6, 2016, 4:57:32 PM6/6/16
to Ansible Project
The default WinRM ACL (at least on 2012R2- only thing I have booted to look at right now) only includes the local Administrators group (and INTERACTIVE, but not in a usable way). If you do a

winrm configSDDL default

on the host in question, you can add any user you want to that ACL (they only need Read and Execute to get logged in via WinRM). I usually just add the local "Remote Management Users" group, then add users to that (not sure why it's not already included, since that was arguably its purpose). You can set this ACL in an automated fashion as well if you're good with SDDL.

helpde...@gmail.com

unread,
Jun 7, 2016, 3:30:50 AM6/7/16
to Ansible Project
Thanks a lot,
That was it !!!!

Have a nice day.

Patrick

Zubair Saeed

unread,
Mar 5, 2017, 5:36:08 PM3/5/17
to Ansible Project
Hi,

I've added my non-admin user to winrm configSDDL default and when I win_ping my windows host, I can get a reply. But when I run win_reboot command, it gives me access denied error.

Do any one have any idea on this?

Regards,
Zubair

Matt Davis

unread,
Mar 6, 2017, 6:04:44 PM3/6/17
to Ansible Project
You have to grant the non-admin user/group "Shut down the system" privileges on the machine(s) in question- default setting only allows that for Administrators and Backup Operators.
Reply all
Reply to author
Forward
0 new messages