From cd93721f8f5b831694114b21178859fca35e03b8 Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Wed, 16 Dec 2015 09:54:53 +0100 Subject: [PATCH] provisioners/ansible: use quotes for the IdentityFile OpenSSH command line arguments Surprisingly (to me at least), a simple quote enclosure was not enough to fix the problem. Caveat: the stringified ansible-playbook command logged in verbose mode is wrongly formatted (no quotes are escaped). Fix #6671 --- CHANGELOG.md | 2 ++ plugins/provisioners/ansible/provisioner/host.rb | 4 +++- test/unit/plugins/provisioners/ansible/provisioner_test.rb | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49b5e6a1c..aa2ca48aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -129,6 +129,8 @@ BUG FIXES: [GH-6586, GH-6552] - provisioners/ansible: use quotes for the `ansible_ssh_private_key_file` value in the generated inventory [GH-6209] + - provisioners/ansible: use quotes for the IdentityFile OpenSSH command line + arguments [GH-6671] - provisioners/ansible: don't show the `ansible-playbook` command when verbose option is an empty string - provisioners/chef: fix `nodes_path` for Chef Zero [GH-6025, GH-6049] diff --git a/plugins/provisioners/ansible/provisioner/host.rb b/plugins/provisioners/ansible/provisioner/host.rb index dcce98fb8..ed212edf4 100644 --- a/plugins/provisioners/ansible/provisioner/host.rb +++ b/plugins/provisioners/ansible/provisioner/host.rb @@ -229,7 +229,9 @@ module VagrantPlugins # Multiple Private Keys unless !config.inventory_path && @ssh_info[:private_key_path].size == 1 @ssh_info[:private_key_path].each do |key| - ssh_options << "-o IdentityFile=#{key}" + # The outer single quotes are required to protect the inner + # double quotes to be stripped by the ssh/shell execution. + ssh_options << "-o IdentityFile='\"#{key}\"'" end end diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index c97cdb5ed..be46bfee1 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -604,8 +604,8 @@ VF it "passes additional Identity Files via ANSIBLE_SSH_ARGS" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| cmd_opts = args.last - expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentityFile=/an/other/identity") - expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentityFile=/yet/an/other/key") + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentityFile='\"/an/other/identity\"'") + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentityFile='\"/yet/an/other/key\"'") } end end @@ -786,7 +786,7 @@ VF it "shows the ansible-playbook command, with additional quotes when required" do expect(machine.env.ui).to receive(:detail).with { |full_command| - expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -o IdentityFile=/my/key1 -o IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --connection=ssh --timeout=30 --ask-sudo-pass --ask-vault-pass --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' --private-key=./myself.key playbook.yml") + expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -o IdentityFile='\"/my/key1\"' -o IdentityFile='\"/my/key2\"' -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --connection=ssh --timeout=30 --ask-sudo-pass --ask-vault-pass --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' --private-key=./myself.key playbook.yml") } end end