vagrant
vagrant copied to clipboard
Ansible provisioner does not set ansible_winrm_scheme in generated inventory file, resulting in connection errors
Vagrant version
Vagrant 2.2.4
Host operating system
Linux
Guest operating system
Windows 10
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "senglin/win-10-enterprise-vs2015community"
config.vm.box_version = "1.0.0"
config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
end
end
# playbook.yml
- hosts: "*"
# uncomment this for a workaround
# vars:
# ansible_winrm_scheme: http
tasks:
- win_command: whoami
Debug output
(not provided for privacy reasons)
Expected behavior
vagrant provision
should succeed.
Actual behavior
vagrant provision
fails with:
fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ssl: HTTPSConnectionPool(host='127.0.0.1', port=2202): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(1, u'[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:726)'),))", "unreachable": true}
Running
$ cat .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory
# Generated by Vagrant
default ansible_connection=winrm ansible_host=127.0.0.1 ansible_port=2202 ansible_user='vagrant' ansible_password='vagrant'
reveals that the generated inventory file uses the HTTP port for winrm without setting ansible_winrm_scheme=http
. Ansible defaults to https
and the connection fails with an SSL error.
It is possible to work around this by modifying playbook.yaml
(see comment above).
I'm not aware of a way to work around this in the Vagrantfile
, but if it is possible I would be eager to learn how.
Steps to reproduce
- Create the given
Vagrantfile
andplaybook.yaml
- Run
vagrant up
and/orvagrant provision
@sol thank you for reporting this issue here (❤️for taking time to fill the template and add Vagrantfile
+ playbook.yml
files 👍).
I'm not aware of a way to work around this in the Vagrantfile, but if it is possible I would be eager to learn how.
You actually have "tons" of ways to pass/override ansible variables from Vagrantfile
settings (keeping your Playbook and Roles defaults clean ;-). Here is a list of options to define ansible_winrm_scheme
as you wish/need:
- The groups or host_vars options
- The extra_vars option (to pass the variable as an
ansible-playbook
command line argument) - The raw_arguments option (to pass the variable as an
ansible-playbook
command line argument)
reveals that the generated inventory file uses the HTTP port for winrm without setting ansible_winrm_scheme=http. Ansible defaults to https and the connection fails with an SSL error.
At first glance, the generated inventory surprises me because we get
- ansible_connection=winrm (Recent Vagrant versions seems to auto-detect the WinRM capabilty of the base box, this is new to my knowledge ;-)
- ansible_port=2202 (I am not sure whether this connection port is really correct, as this corresponds to a position in the SSH range used by vagrant)
I haven't use Vagrant+Ansible+WindowsServers for many time now, but in the past at least, I think it was necessary to explicitly switch from SSH communication to WinRM protocol with this Vagrantfile setting:
config.vm.communicator = "winrm"
Or, is really your Windows WinRM service open/forwarded on your host's localhost:2202
?
Once ansible_connection
is set to winrm
, I don't think that Vagrant has to specify other Ansible winrm options as the defaults looks good to me according to Ansible Documentation:
ansible_winrm_scheme: Specify the connection scheme (
http
orhttps
) to use for the WinRM connection. Ansible useshttps
by default unless ansible_port is5985
Basic authentication is not enabled by default on a Windows host but can be enabled by running the following in PowerShell [...]
But of course, it may depends how is your Server configured (and maybe the version of Ansible in use).
Please give it a try and let me know about your new results (e.g. generated inventory, log output).
PS: On my side, I'll try to do a test by myself as well (out of curiousity)
@sol your experience feedbacks are more than welcome into #10766 💓.
The generated inventory lines for a winrm machine should more look like this (but on a wrapped single line):
ansible_connection=winrm
ansible_host=127.0.0.1
ansible_port=55985
ansible_user='vagrant'
ansible_password='vagrant'
ansible_winrm_server_cert_validation=ignore
although this kind of configuration is probably outdated with successive evolutions of WinRM. See #10444 discussion for more details, but recent working configuration looks for instance like this:
ansible_user: vagrant
ansible_password: vagrant
ansible_connection: psrp
ansible_port: 55986
ansible_psrp_transport: basic
ansible_psrp_cert_validation: ignore
Hope it helps...
I believe I can reproduce this issue, also with Vagrant 2.2.4 on Linux and a Windows guest. Unless I am misunderstanding something, which is totally possible. Anyway I hope this info might help, and thank you because the work-around provided helped me!
Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.box = "test-box"
config.vm.provision "ansible" do |ansible|
ansible.playbook = "site.yml"
# Uncomment the below for work-around
#ansible.host_vars = {
# "default" => { "ansible_winrm_scheme" => "http" }
#}
end
end
site.yml:
- hosts: all
tasks:
- win_ping:
Without the work-around, vagrant provision
fails with:
fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ssl: HTTPSConnectionPool(host='127.0.0.1', port=55985): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(1, u'[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:727)'),))", "unreachable": true}
Generated inventory:
# Generated by Vagrant
default ansible_connection=winrm ansible_host=127.0.0.1 ansible_port=55985 ansible_user='vagrant' ansible_password='vagrant'
Uncommenting the work-around in the Vagrantfile results in adding the variable ansible_winrm_scheme=http
to the generated inventory, and with that, vagrant provision
succeeds.
Hi, this issue has been open since 2019, is this going to be worked on? I am running Ubuntu 20.04 LTS with Vagrant 2.2.19, and this problem still remains an issue where one must use the nice work-around created above in order to leverage the Ansible Provisioner with WinRM.
The workaround does not work when you use vagrant to manage multiple machines. When i use one vm the workaround works as stated above, but when i try the same thing in a multimachine setup it gives me:
fatal: [win]: UNREACHABLE! => {"changed": false, "msg": "ssl: HTTPSConnectionPool(host='127.0.0.1', port=55985): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:997)')))", "unreachable": true}
Following Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.define "win" do |win|
win.vm.box = "gusztavvargadr/windows-10"
win.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
ansible.compatibility_mode = "2.0"
ansible.host_vars = {
"default" => { "ansible_winrm_scheme" => "http" }
}
end
end
config.vm.define "ubuntu" do |ubuntu|
ubuntu.vm.box = "ubuntu/focal64"
end
end
any ideas?
what is "default"? Does that mean the hosts?
Working solution
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provision/01-postinstall.yml"
ansible.extra_vars = {
ansible_winrm_scheme: 'http'
}
end