`ANSIBLE_SSH_ARGS` `-o IdentityFile=` option fails to quote path to private key and breaks on spaces
Vagrant version
Vagrant 2.0.3
Host operating system
Ubuntu 16.04 LTS
Guest operating system
CentOS 7
Vagrantfile
Extract from my vagrant file.
config.vm.provision 'ansible' do |ansible|
ansible.playbook = 'common.yml'
ansible.verbose = true
ansible.inventory_path = 'inventories/dev/hosts.yml'
end
end
The Vagrantfile and the inventory file have been validated such that the static inventory matches the hosts defined in the vagrantfile
Debug output
Did not past full debug to gist. The relevant debug output is as follows (seen by invoking ansible.verbose = true
<myhostname>.vagrant.test: Running ansible-playbook...
PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o IdentityFile=/home/<myuser>/<some path with a space>/ansible/.vagrant/machines/<myhostname>.vagrant.test/libvirt/private_key -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --connection=ssh --timeout=30 --extra-vars=ansible_user\=\'vagrant\' --limit="<myhostname>.vagrant.test" --inventory-file=inventories/dev/hosts.yml -v common.yml
Using /home/<myuser>/<some path with a space>/ansible/ansible.cfg as config file
PLAY [Common] ******************************************************************
TASK [Gathering Facts] *********************************************************
fatal: [<myhostname>.vagrant.test]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname <part of directory name with a space>/ansible/.vagrant/machines/<myhostname>.vagrant.test/libvirt/private_key: Name or service not known\r\n", "unreachable": true}
Expected behavior
What should have happened?
SSH private key paths provided to ANSIBLE_SSH_ARGS are quoted to avoid issues with spaces
Actual behavior
What actually happened?
ANSIBLE_SSH_ARGS causes the play to break with {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname due to not quoting -o IdentityFile=<private key path with space>.
Steps to reproduce
- Run the ansible provisioner from an ansible project and Vagrant file that has a space in the parent path.
- Use
ansible.verbose = trueas a provisioner option to observe how-o IdentityFile=value was not safely quoted.
References
Related, but not identical
- https://github.com/hashicorp/vagrant/issues/9446
I have this issue too.
I can reproduce this bug on Vagrant 2.4.9:
$ vagrant provision
==> default: Running provisioner: ansible...
...stripped...
default: Running ansible-playbook...
PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o IdentityFile=/home/brlin/文件/Vagrant bug reproduction - ansible provisioner breaks when the `inventory_path` option's value contain spaces/.vagrant/machines/default/virtualbox/private_key -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --connection=ssh --timeout=30 --extra-vars=ansible_ssh_user\=\'vagrant\' --limit="default" --inventory-file=inventory.yml -v ping.yml
No config file found; using defaults
PLAY [Minimal play] ************************************************************
TASK [Gathering Facts] *********************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: No closing quotation
fatal: [default]: FAILED! => {"msg": "Unexpected failure during module execution: No closing quotation", "stdout": ""}
Another execution error example:
$ vagrant provision
==> default: This machine used to live in /home/brlin/Workarounds/safe-path-mountpoints/vagrant-issue-9597-reproduction but it's now at /home/brlin/文件/vagrant issue-9597-reproduction.
==> default: Depending on your current provider you may need to change the name of
==> default: the machine to run it as a different machine.
==> default: Running provisioner: ansible...
Vagrant gathered an unknown Ansible version:
and falls back on the compatibility mode '1.8'.
Alternatively, the compatibility mode can be specified in your Vagrantfile:
https://www.vagrantup.com/docs/provisioning/ansible_common.html#compatibility_mode
default: Running ansible-playbook...
PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o IdentityFile=/home/brlin/文件/vagrant issue-9597-reproduction/.vagrant/machines/default/virtualbox/private_key -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --connection=ssh --timeout=30 --extra-vars=ansible_ssh_user\=\'vagrant\' --limit="default" --inventory-file=inventory.yml -v ping.yml
No config file found; using defaults
PLAY [Minimal play] ************************************************************
TASK [Gathering Facts] *********************************************************
fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: OpenSSH_9.6p1 Ubuntu-3ubuntu13.14, OpenSSL 3.0.13 30 Jan 2024\r\ndebug1: Reading configuration data /home/brlin/.ssh/config\r\ndebug1: Reading configuration data /home/brlin/.ssh/hashbang.config\r\ndebug1: Reading configuration data /home/brlin/.ssh/tetherfi.config\r\ndebug1: Reading configuration data /home/brlin/.ssh/remarkable.config\r\ndebug1: Reading configuration data /home/brlin/.ssh/vagrant.config\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files\r\ndebug1: /etc/ssh/ssh_config line 21: Applying options for *\r\ndebug1: auto-mux: Trying existing master at '/home/brlin/.ansible/cp/58b16fd052'\r\ndebug1: Control socket \"/home/brlin/.ansible/cp/58b16fd052\" does not exist\r\nssh: Could not resolve hostname issue-9597-reproduction/.vagrant/machines/default/virtualbox/private_key: Name or service not known", "unreachable": true}
PLAY RECAP *********************************************************************
default : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.
Steps to reproduce
The following are the minimal steps to reproduce the issue:
-
Launch a text terminal.
-
Run the following command to clone this repository to a path containing spaces:
git clone https://github.com/brlin-tw/vagrant-issue-9597-reproduction.git "vagrant issue-9597-reproduction" -
Change the current working directory to the cloned repository:
cd "vagrant issue-9597-reproduction" -
Review the files in the repository if necessary.
-
Run the following command to start the Vagrant VM and provision it with Ansible:
vagrant upThe Ansible provisioner should fail with the following similar error message:
TASK [Ping the host] *********************************************************** fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: OpenSSH_9.6p1 Ubuntu-3ubuntu13.14, OpenSSL 3.0.13 30 Jan 2024\r\ndebug1: Reading configuration data /home/brlin/.ssh/config\r\ndebug1: Reading configuration data /home/brlin/.ssh/hashbang.config\r\ndebug1: Reading configuration data /home/brlin/.ssh/tetherfi.config\r\ndebug1: Reading configuration data /home/brlin/.ssh/remarkable.config\r\ndebug1: Reading configuration data /home/brlin/.ssh/vagrant.config\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files\r\ndebug1: /etc/ssh/ssh_config line 21: Applying options for *\r\ndebug1: auto-mux: Trying existing master at '/home/brlin/.ansible/cp/58b16fd052'\r\ndebug1: Control socket \"/home/brlin/.ansible/cp/58b16fd052\" does not exist\r\nssh: Could not resolve hostname issue-9597-reproduction/.vagrant/machines/default/virtualbox/private_key: Name or service not known", "unreachable": true}