Problems setting up WinRM

I’m having trouble setting Ansible with WinRM. Here’s my environment:
10.10.50.4 - Win1 - the windows computer im trying to connect to from Ansible (i’ve added this to the hosts file on my ansible host)
10.10.50.6 - Win2 - another windows host
10.10.50.5 - Ansible host (running Ubuntu 12.04)

On Win1 I have setup a remoting endpoint using SSL (btw, the doc doesn’t state wether SSL is required or recommended. non-ssl http connections should be an option imho)
From 10.10.50.6 I can initiate a SSL-based PSremoting session to 10.10.50.4, which should prove that the remoting endpoint and ssl is correctly setup:

$cred = Get-credential
$options = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
New-PSSession -ComputerName “10.10.50.4” -UseSSL -Credential $cred -SessionOption $options

This opens a session without warnings.

Here’s my hosts file in ansible:
azureuser@th-ansible10:~/AnsibleTest/pstest$ cat hosts
[windows]
Win1

and here’s my windows groupvar file:
azureuser@th-ansible10:~/AnsibleTest/pstest/group_vars$ cat windows.yml

it is suggested that these be encrypted with ansible-vault:

ansible-vault edit group_vars/windows.yml

ansible_ssh_user: thadministrator
ansible_ssh_pass:
ansible_ssh_port: 5986
ansible_connection: winrm

Here’s the command I’m attempting:
azureuser@th-ansible10:~/AnsibleTest/pstest$ ansible windows -i hosts -m win_ping -vvvv
ESTABLISH WINRM CONNECTION FOR USER: thadministrator on PORT 5986 TO win1
WINRM CONNECT: transport=plaintext endpoint=https://win1:5986/wsman
WINRM CONNECTION ERROR: Bad HTTP response returned from server. Code 401
WINRM CONNECT: transport=plaintext endpoint=http://win1:5986/wsman
win1 | FAILED => Traceback (most recent call last):
File “/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/init.py”, line 526, in _executor
exec_rc = self._executor_internal(host, new_stdin)
File “/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/init.py”, line 628, in _executor_internal
return self._executor_internal_inner(host, self.module_name, self.module_args, inject, port, complex_args=complex_args)
File “/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/init.py”, line 799, in _executor_internal_inner
conn = self.connector.connect(actual_host, actual_port, actual_user, actual_pass, actual_transport, actual_private_key_file)
File “/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/connection.py”, line 34, in connect
self.active = conn.connect()
File “/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/connection_plugins/winrm.py”, line 130, in connect
self.protocol = self._winrm_connect()
File “/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/connection_plugins/winrm.py”, line 86, in _winrm_connect
protocol.send_message(‘’)
File “/usr/local/lib/python2.7/dist-packages/winrm/protocol.py”, line 160, in send_message
return self.transport.send_message(message)
File “/usr/local/lib/python2.7/dist-packages/winrm/transport.py”, line 63, in send_message
response = urlopen(request, timeout=self.timeout)
File “/usr/lib/python2.7/urllib2.py”, line 126, in urlopen
return _opener.open(url, data, timeout)
File “/usr/lib/python2.7/urllib2.py”, line 400, in open
response = self._open(req, data)
File “/usr/lib/python2.7/urllib2.py”, line 418, in _open
‘_open’, req)
File “/usr/lib/python2.7/urllib2.py”, line 378, in _call_chain
result = func(*args)
File “/usr/lib/python2.7/urllib2.py”, line 1207, in http_open
return self.do_open(httplib.HTTPConnection, req)
File “/usr/lib/python2.7/urllib2.py”, line 1180, in do_open
r = h.getresponse(buffering=True)
File “/usr/lib/python2.7/httplib.py”, line 1030, in getresponse
response.begin()
File “/usr/lib/python2.7/httplib.py”, line 407, in begin
version, status, reason = self._read_status()
File “/usr/lib/python2.7/httplib.py”, line 365, in _read_status
line = self.fp.readline()
File “/usr/lib/python2.7/socket.py”, line 447, in readline
data = self._sock.recv(self._rbufsize)
error: [Errno 104] Connection reset by peer

I don’t know why this is happening, and I realize that this is very much beta code. However, there are some (potentially important) points left out from the doc:

  1. Is SSL required, or should this work using http-based connections?
  2. What requirements are there on the ssl cert being used? Does the ansible node need the public key of the cert being used on the windows side?

I'm having trouble setting Ansible with WinRM. Here's my environment:
10.10.50.4 - Win1 - the windows computer im trying to connect to from
Ansible (i've added this to the hosts file on my ansible host)
10.10.50.6 - Win2 - another windows host
10.10.50.5 - Ansible host (running Ubuntu 12.04)

On Win1 I have setup a remoting endpoint using SSL (btw, the doc doesn't
state wether SSL is required or recommended. non-ssl http connections
should be an option imho)

It's recommended, but I'd say "very very highly recommended".

From 10.10.50.6 I can initiate a SSL-based PSremoting session to
10.10.50.4, which should prove that the remoting endpoint and ssl is
correctly setup:

$cred = Get-credential
$options = New-PSSessionOption -SkipCACheck -SkipCNCheck
-SkipRevocationCheck
New-PSSession -ComputerName "10.10.50.4" -UseSSL -Credential $cred
-SessionOption $options

This opens a session without warnings.

Here's my hosts file in ansible:
azureuser@th-ansible10:~/AnsibleTest/pstest$ cat hosts
[windows]
Win1

and here's my windows groupvar file:
azureuser@th-ansible10:~/AnsibleTest/pstest/group_vars$ cat windows.yml
# it is suggested that these be encrypted with ansible-vault:
# ansible-vault edit group_vars/windows.yml
ansible_ssh_user: thadministrator
ansible_ssh_pass: <password>
ansible_ssh_port: 5986
ansible_connection: winrm

Here's the command I'm attempting:
azureuser@th-ansible10:~/AnsibleTest/pstest$ ansible windows -i hosts -m
win_ping -vvvv
<win1> ESTABLISH WINRM CONNECTION FOR USER: thadministrator on PORT 5986
TO win1
<win1> WINRM CONNECT: transport=plaintext endpoint=https://win1:5986/wsman
<win1> WINRM CONNECTION ERROR: Bad HTTP response returned from server.
Code 401
<win1> WINRM CONNECT: transport=plaintext endpoint=http://win1:5986/wsman
win1 | FAILED => Traceback (most recent call last):
  File
"/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/__init__.py",
line 526, in _executor
    exec_rc = self._executor_internal(host, new_stdin)
  File
"/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/__init__.py",
line 628, in _executor_internal
    return self._executor_internal_inner(host, self.module_name,
self.module_args, inject, port, complex_args=complex_args)
  File
"/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/__init__.py",
line 799, in _executor_internal_inner
    conn = self.connector.connect(actual_host, actual_port, actual_user,
actual_pass, actual_transport, actual_private_key_file)
  File
"/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/connection.py",
line 34, in connect
    self.active = conn.connect()
  File
"/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/connection_plugins/winrm.py",
line 130, in connect
    self.protocol = self._winrm_connect()
  File
"/usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/runner/connection_plugins/winrm.py",
line 86, in _winrm_connect
    protocol.send_message('')
  File "/usr/local/lib/python2.7/dist-packages/winrm/protocol.py", line
160, in send_message
    return self.transport.send_message(message)
  File "/usr/local/lib/python2.7/dist-packages/winrm/transport.py", line
63, in send_message
    response = urlopen(request, timeout=self.timeout)
  File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 400, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/urllib2.py", line 418, in _open
    '_open', req)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 1207, in http_open
    return self.do_open(httplib.HTTPConnection, req)
  File "/usr/lib/python2.7/urllib2.py", line 1180, in do_open
    r = h.getresponse(buffering=True)
  File "/usr/lib/python2.7/httplib.py", line 1030, in getresponse
    response.begin()
  File "/usr/lib/python2.7/httplib.py", line 407, in begin
    version, status, reason = self._read_status()
  File "/usr/lib/python2.7/httplib.py", line 365, in _read_status
    line = self.fp.readline()
  File "/usr/lib/python2.7/socket.py", line 447, in readline
    data = self._sock.recv(self._rbufsize)
error: [Errno 104] Connection reset by peer

Interesting... can you share the steps you performed to set things up?
(Or basically just following the docs? Any differences, etc?)

I don't know why this is happening, and I realize that this is very much
beta code. However, there are some (potentially important) points left out
from the doc:
1. Is SSL required, or should this work using http-based connections?

As above, it is not required.

2. What requirements are there on the ssl cert being used? Does the
ansible node need the public key of the cert being used on the windows
side?

It does not. This is just there to set up a self-signed cert to enable
the https:// listener.

Thanks Michael,

I’ve basically been trying to follow the docs - wondering if I should try and re-setup my ansible node from the beginning and document each step as I go. As you can see above i’m pretty sure there’s nothing wrong with my remoting endpoint :slight_smile:

These VMs live in Azure, so if it would help I’d absolutely be willing to let you guys have a look for yourselves. In the meantime I’ll just build a fresh ansible host.

Yeah if you want to start a clean one and let us know if you get stuck that would be great.

Thank you!

Hi guys, I have exactly the same setup and subsequent error as Trond.

My steps for setup were essentially the exact steps from the Windows Module setup page. I’m using EC2 boxes with my Control box on Ubuntu 14.04. The only thing i needed to so was to copy the self-signed SSL certificate from the Personal certificates folder to Trusted Root Certification Authorities to get it to this stage.

ESTABLISH WINRM CONNECTION FOR USER: Administrator on PORT 5986 TO ip-xxxxxxxx

WINRM CONNECT: transport=plaintext endpoint=https://ip-xxxxxxxx:5986/wsman
WINRM CONNECTION ERROR: Bad HTTP response returned from server. Code 401
WINRM CONNECT: transport=plaintext endpoint=http://ip-xxxxxxxx:5986/wsman

I can use the Test-WMan command to connect between the 2 windows boxes successfully - so like Trond i’m fairly sure the wsman connection is setup correctly on the Windows box i need to manage.

I’m a big fan of Ansible and would love to get the Windows connectivity to work!

cheers,
Jason

Here are my documented steps:

** Windows Host Setup

Note: Windows server is using Windows Server Datacenter 2008 with SP2 (Amazon EC2)

  1. Install Powershell - .NET 4.5 Framework - http://www.microsoft.com/en-us/download/details.aspx?id=30653
  2. Install Powershell 3.0 - Windows Management Framework 3.0 - http://www.microsoft.com/en-us/download/details.aspx?id=34595
  3. Run: pip install http://github.com/diyan/pywinrm/archive/master.zip#egg=pywinrm on Ubuntu Ansible Control box (Ubuntu 14.04)
  4. Setup Windows servername (ip-xxxxxxxx) in Ansible hosts file
  5. Setup group_vars/windows.yml with:

ansible_ssh_user: Administrator
ansible_ssh_pass: “Password”
ansible_ssh_port: 5986
ansible_connection: winrm

  1. Windows server - Powershell command: Enable-PSRemoting -Force
  2. Windows server - PowerShell command: Set-ExecutionPolicy RemoteSigned
  3. Windows server - cmd: NetSH ADVFirewall Set AllProfiles Settings remotemanagement Enable
  4. Created a self signed certificate using the following powershell script (Subject name is the server hostname: ip-xxxxxxxx) - http://social.technet.microsoft.com/wiki/contents/articles/4714.how-to-generate-a-self-signed-certificate-using-powershell.aspx
  • I answered Yes for both Server and Client Authentication (No to everything else)
  1. Copied certificate into Trusted Root Certification Authority

  2. Windows server - cmd: winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=“ip-xxxxxxxx”;CertificateThumbprint=“481asaflkdfj8bee1e44c44320598jdsklfj8ecb4a844d”}

  3. Windows server - cmd: winrm delete winrm/config/listener?Address=*+Transport=HTTP

  4. Windows server - cmd: netsh advfirewall firewall add rule Profile=public name=“Allow WinRM HTTPS” dir=in localport=5986 protocol=TCP action=allow

Hope that helps.

cheers,
Jason

Well I seemed to have got it working by running the following winrm command on the windows box:

winrm set winrm/config/service/auth @{Basic=“true”}

It looks like by default the winrm service basic authentication setting is set to false.

I also had some issues with ansible complaining that it couldnt find powershell.ps1 in a python module directory - “imported module support code does not exist”. Which is wierd as I have not installed Ansible any other way apart from using Git - I made sure it was a fresh build and ran source ./hacking/env-setup to make sure.

I simply copied the powershell.ps1 script to the folder it was looking for and it now works.

cp /home/ubuntu/ansible/lib/ansible/module_utils/powershell.ps1 /usr/local/lib/python2.7/dist-packages/ansible-1.7-py2.7.egg/ansible/module_utils/

Hope this helps you out Trond.

Thanks Jason, I’ll test your suggestions on my node(s) and report back.

Jason, you were right on the money on both counts.

What was missing on the WinRM listener was the “basic” auth mechanism. Looks like the default config only has Kerberos and Negotiate authentication enabled (which was news for me). → This should be added to the documentation I guess.

I also needed to move that file like you did. Running Ubuntu 12.04.

Again, thanks for your help!

We’ve discussed the idea of having an installer or other kind of setup script for these kind of things.

Anyone with Powershell experience interested in helping in such an effort?

We could try to programatically include basic auth as well.

As for documentation, this all lives in docsite/rst in the checkout, if you want to add additions about how you changed them – this would be quite welcome!

I absolutely agree. I’m gona cook together something for auto-configuring my Azure lab VMs for Ansible, I’ll try and make it generic enough to work in most scenarios.

-Trond

On a Windows 2012 or 2012R2 host, this script should do the trick:
https://gist.github.com/trondhindenes/b9b5b25b11273cc35659

I need to stand up a 2008R2-based machine tomorrow and make the script compatible

I can simply invoke it by starting Powershell (as admin) and run the 2 following lines:

$VerbosePreference = “Continue”
iex ((new-object net.webclient).DownloadString(‘https://gist.githubusercontent.com/trondhindenes/b9b5b25b11273cc35659/raw/eb1f14ea65518fcd5e4a4159af4d68927c6e4fbf/configure-ansibletarget.ps1’))

I’d love to see some feedback on it!

Nice - we can do some digging/testing and I’d also welcome other suggestions, though this is likely something we can include in our example scripts dir to get people started!

I’m curious what might be required on older Windowseses (yes, that’s a word, I know it is!)

Cool! For one, the new-selfsignedcert isn’t present on pre-2012 computers. So I’m gonna have to use .net methods to generate a cert instead. I’ll do some variable stuff in there as well, so that the script can be controlled better, if the user wants to. I’ll update a new thread when I have a new version going.

Super super super super awesome*

  • = super super

This is outstanding. Thanks very much and looking forward to it. BTW, need to start another thread about Windows ideas soon. I’ll do this on ansible-project as previously ansible-devel was a bit quiet (smaller list).

Sorry to revive a somewhat old post, but I was following the basic guide from here: http://docs.ansible.com/intro_windows.html, and running the command Jason Rizio mentioned solved the 401 error for me as well:

`
winrm set winrm/config/service/auth @{Basic=“true”}

`

So I’m thinking, how about adding a debugging section to the bottom that page?

  1. Mentioning the Basic auth command (and any security concerns)

  2. As well as a note about -vvvv to get verbose feedback

  3. And possibly a third note about the account (currently) needing to be on the local machine; domain accounts seem like they’re still under development on a separate fork.

I know Ansible docs recommend you learn it first and then cross over to the dark side, but #2 would probably be huge on that page (in case there are others just like me that did a tutorial on linux:linux and then thought, wow, lets make this work with Windows!)

I’m completely new to Ansible but when I saw that Windows support is being added I had to jump right in this morning. So far my Ansible instance can talk to a test Linux host with no issues. For my Windows box I stumbled across your #1 and #2 items mentioned above but I’m not sure what you mean by #3. Can you elaborate?

Here is the error I am getting. Note that the Windows box is in a domain but I am using the local Administrator account to connect. I can try removing it from the domain if you think that is worth testing.

ansible myhost.mydomain.com -m win_ping --ask-vault-pass -vvvv
Vault password:
<myhost.mydomain.com> ESTABLISH WINRM CONNECTION FOR USER: Administrator on PORT 5985 TO myhost.mydomain.com
<myhost.mydomain.com> WINRM CONNECT: transport=plaintext endpoint=http://myhost.mydomain.com:5985/wsman
<myhost.mydomain.com> REMOTE_MODULE win_ping
<myhost.mydomain.com> EXEC (New-Item -Type Directory -Path $env:temp -Name “ansible-tmp-1406758554.1-201733087669750”).FullName | Write-Host -Separator ‘’;
<myhost.mydomain.com> WINRM EXEC ‘PowerShell’ [‘-NoProfile’, ‘-NonInteractive’, ‘-EncodedCommand’, ‘KABOAGUAdwAtAEkAdABlAG0AIAAtAFQAeQBwAGUAIABEAGkAcgBlAGMAdABvAHIAeQAgAC0AUABhAHQAaAAgACQAZQBuAHYAOgB0AGUAbQBwACAALQBOAGEAbQBlACAAIgBhAG4AcwBpAGIAbABlAC0AdABtAHAALQAxADQAMAA2ADcANQA4ADUANQA0AC4AMQAtADIAMAAxADcAMwAzADAAOAA3ADYANgA5ADcANQAwACIAKQAuAEYAdQBsAGwATgBhAG0AZQAgAHwAIABXAHIAaQB0AGUALQBIAG8AcwB0ACAALQBTAGUAcABhAHIAYQB0AG8AcgAgACcAJwA7AA==’]
Traceback (most recent call last):
File “/srv/ansible/lib/ansible/runner/connection_plugins/winrm.py”, line 147, in exec_command
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
File “/srv/ansible/lib/ansible/runner/connection_plugins/winrm.py”, line 118, in _winrm_exec
vvvv(‘WINRM RESULT %r’ % response, host=self.host)
File “/usr/lib/python2.6/site-packages/winrm/init.py”, line 12, in repr
self.status_code, self.std_out[:20], self.std_err[:20])
ValueError: zero length field name in format
myhost.mydomain.com | FAILED => failed to exec cmd PowerShell -NoProfile -NonInteractive -EncodedCommand KABOAGUAdwAtAEkAdABlAG0AIAAtAFQAeQBwAGUAIABEAGkAcgBlAGMAdABvAHIAeQAgAC0AUABhAHQAaAAgACQAZQBuAHYAOgB0AGUAbQBwACAALQBOAGEAbQBlACAAIgBhAG4AcwBpAGIAbABlAC0AdABtAHAALQAxADQAMAA2ADcANQA4ADUANQA0AC4AMQAtADIAMAAxADcAMwAzADAAOAA3ADYANgA5ADcANQAwACIAKQAuAEYAdQBsAGwATgBhAG0AZQAgAHwAIABXAHIAaQB0AGUALQBIAG8AcwB0ACAALQBTAGUAcABhAHIAYQB0AG8AcgAgACcAJwA7AA==

The local Administrator account should work, and you don’t need to remove it from the domain. I was trying to say a user account that’s registered on the domain doesn’t seem to be supported currently… or I did something wrong.

While I personally am an admin on these boxes, I don’t have the credentials for the local Admin account. So instead, I tried:

  • damon
  • damon@domainnamehere

And those both failed. I saw a post in here about a fork for supporting domain accounts, but it’s still in development, although it sounds like it’s progressing pretty well.

So then I:

  • created a local user account on the Windows client (cleverly named ansible)
  • put them in the administrators group on that client
  • updated /etc/ansible/group_vars/windows.yml with their creds
    And that did it (along with the basic auth from earlier).

As far as the issue you’re seeing, that probably should be a new topic; I was just bumping and clarifying this one to see if it should be in the intro page.

But, have you completed all of the steps on the Windows setup page? http://docs.ansible.com/intro_windows.html I ask because I had missed one or two steps on the Windows client, I just scrolled over them by accident. Here’s my summary of the steps I did to get the target client online and responding:

Prepare the target system(s)

  1. RDP into the host
  2. Launch Powershell
  3. Run the following commands:

Enable-PSRemoting -Force
Set-ExecutionPolicy RemoteSigned

  1. Poke a hole through the firewall:

Set-NetFirewallRule -Name “WINRM-HTTP-In-TCP-PUBLIC” -RemoteAddress Any

  1. Create the https certificate

  2. and then register a listener. Note that in
    order to register it, I had to first run PowerShell, then launch a cmd window from
    there, and THEN register the listener. Also I didn’t use the FQDN, only the output of hostname; also no spaces in the Cert

while in PowersHell, run…

hostname
cmd
winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=“yourhostnamehere”;CertificateThumbprint=“0e…21”}

  1. Deleting the HTTP transport worked fine from POSH

  2. Poke yet another hole in the firewall

netsh advfirewall firewall add rule Profile=public name=“Allow WinRM HTTPS” dir=in localport=5986 protocol=TCP action=allow

  1. Test it. 2-3 more steps and this is a 12step program, just like everything else
    on Windows.

I’ve just updated the docs to reference Trond’s helpful setup script:

https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1

Feedback and tweaks, if needed, would be very welcome as I like the idea of automating this as much as possible.

After spending much of the past day troubleshooting this on my Windows clients I decided to try setting up ansible on an Ubuntu box. Everything worked right the first time. In my corporate environment I need to use RHEL 6.4 so I blew away my host and will try the install again. Sorry for being a newb.

  • Aaron