provisioners/ansible: add `IdentitiesOnly=yes`

This SSH option is always set, except when Vagrant is running from an
operating system fo the Solaris-family, as this parameter is not
supported by SunSSH. Logic taken from
bed1f8335f/lib/vagrant/util/ssh.rb (L116-L121)

Fix #5017
This commit is contained in:
Gilles Cornu 2015-01-12 08:58:29 +01:00
parent 49d1a92bf6
commit c3cae3d235
3 changed files with 58 additions and 5 deletions

View File

@ -5,6 +5,7 @@ BUG FIXES:
- core: push configurations are validated with global configs [GH-5130]
- guests/funtoo: fix incorrect path in configure networks [GH-4812]
- plugins/login: allow users to login with a token [GH-5145]
- provisioners/ansible: fix SSH settings to support more than 5 ssh keys [GH-5017]
## 1.7.2 (January 6, 2015)

View File

@ -1,3 +1,5 @@
require "vagrant/util/platform"
module VagrantPlugins
module Ansible
class Provisioner < Vagrant.plugin("2", :provisioner)
@ -209,6 +211,12 @@ module VagrantPlugins
# Don't access user's known_hosts file, except when host_key_checking is enabled.
ssh_options << "-o UserKnownHostsFile=/dev/null" unless config.host_key_checking
# Set IdentitiesOnly=yes to avoid authentication errors when the host has more than 5 ssh keys.
# Notes:
# - Solaris/OpenSolaris/Illumos uses SunSSH which doesn't support the IdentitiesOnly option.
# - this could be improved by sharing logic with lib/vagrant/util/ssh.rb
ssh_options << "-o IdentitiesOnly=yes" unless Vagrant::Util::Platform.solaris?
# Multiple Private Keys
@ssh_info[:private_key_path].drop(1).each do |key|
ssh_options << "-o IdentityFile=#{key}"

View File

@ -50,6 +50,7 @@ VF
let(:generated_inventory_file) { File.join(generated_inventory_dir, 'vagrant_ansible_inventory') }
before do
Vagrant::Util::Platform.stub(solaris?: false)
subject.instance_variable_get(:@logger).stub(:debug?).and_return(false)
machine.stub(ssh_info: ssh_info)
@ -103,10 +104,11 @@ VF
cmd_opts = args.last
if expected_host_key_checking
expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to be_nil unless config.raw_arguments
expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to_not include("-o UserKnownHostsFile=/dev/null")
else
expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o UserKnownHostsFile=/dev/null")
end
expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentitiesOnly=yes")
expect(cmd_opts[:env]['ANSIBLE_FORCE_COLOR']).to eql("true")
expect(cmd_opts[:env]['ANSIBLE_HOST_KEY_CHECKING']).to eql(expected_host_key_checking.to_s)
expect(cmd_opts[:env]['PYTHONUNBUFFERED']).to eql(1)
@ -270,7 +272,7 @@ VF
config.host_key_checking = true
end
it_should_set_arguments_and_environment_variables 6, 3, true
it_should_set_arguments_and_environment_variables 6, 4, true
end
describe "with boolean (flag) options disabled" do
@ -465,7 +467,7 @@ VF
it "shows the ansible-playbook command" 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=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml")
expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml")
}
end
end
@ -480,7 +482,7 @@ VF
it "shows the ansible-playbook command" 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=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml")
expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml")
}
end
end
@ -538,10 +540,52 @@ 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 IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --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' 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/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --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' playbook.yml")
}
end
end
#
# Special cases related to the Vagrant Host operating system in use
#
context "with a Solaris-like host" do
before do
Vagrant::Util::Platform.stub(solaris?: true)
end
it "does not set IdentitiesOnly=yes in 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_not include("-o IdentitiesOnly=yes")
# Note:
# The expectation below is a workaround to a possible misuse (or bug) in RSpec/Ruby stack.
# If 'args' variable is not required by in this block, the "Vagrant::Util::Subprocess).to receive"
# surprisingly expects to receive "no args".
# This problem can be "solved" by using args the "unnecessary" (but harmless) expectation below:
expect(true).to be_true
}
end
describe "and with host_key_checking option enabled" do
it "does not set ANSIBLE_SSH_ARGS environment variable" do
config.host_key_checking = true
expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args|
cmd_opts = args.last
expect(cmd_opts[:env]).to_not include('ANSIBLE_SSH_ARGS')
# Note:
# The expectation below is a workaround to a possible misuse (or bug) in RSpec/Ruby stack.
# If 'args' variable is not required by in this block, the "Vagrant::Util::Subprocess).to receive"
# surprisingly expects to receive "no args".
# This problem can be "solved" by using args the "unnecessary" (but harmless) expectation below:
expect(true).to be_true
}
end
end
end
end
end