diff --git a/CHANGELOG.md b/CHANGELOG.md index 24ea0614d..b7d91434d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ IMPROVEMENTS: `--no-color` mode globally. [GH-2261] - core: box URL and add date is tracked and shown if `-i` flag is specified for `vagrant box list` [GH-2327] + - core: Multiple SSH keys can be specified with `config.ssh.private_key_path` + [GH-907] - commands/init: Add `--output` option for specifing output path, or "-" for stdin. [GH-1364] - commands/provision: Add `--no-parallel` option to disable provider diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index 78780dd91..14c700197 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -299,8 +299,15 @@ module Vagrant end end + # Setup the keys + if !info[:private_key_path].is_a?(Array) + info[:private_key_path] = [info[:private_key_path]] + end + # Expand the private key path relative to the root path - info[:private_key_path] = File.expand_path(info[:private_key_path], @env.root_path) + info[:private_key_path].map! do |path| + File.expand_path(path, @env.root_path) + end # Return the final compiled SSH info data info diff --git a/lib/vagrant/util/ssh.rb b/lib/vagrant/util/ssh.rb index afbce4866..3f59cf854 100644 --- a/lib/vagrant/util/ssh.rb +++ b/lib/vagrant/util/ssh.rb @@ -70,7 +70,7 @@ module Vagrant :host => ssh_info[:host], :port => ssh_info[:port], :username => ssh_info[:username], - :key_path => ssh_info[:private_key_path] + :key_path => ssh_info[:private_key_path].join(", ") end raise Errors::SSHUnavailable @@ -85,7 +85,7 @@ module Vagrant :host => ssh_info[:host], :port => ssh_info[:port], :username => ssh_info[:username], - :key_path => ssh_info[:private_key_path] + :key_path => ssh_info[:private_key_path].join(", ") end end @@ -116,7 +116,11 @@ module Vagrant end # If we're not in plain mode, attach the private key path. - command_options += ["-i", options[:private_key_path].to_s] if !plain_mode + if !plain_mode + options[:private_key_path].each do |path| + command_options += ["-i", path.to_s] + end + end if ssh_info[:forward_x11] # Both are required so that no warnings are shown regarding X11 diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 6ae96cc39..2d35adb3c 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -167,7 +167,7 @@ module VagrantPlugins :auth_methods => ["none", "publickey", "hostbased", "password"], :config => false, :forward_agent => ssh_info[:forward_agent], - :keys => [ssh_info[:private_key_path]], + :keys => ssh_info[:private_key_path], :keys_only => true, :paranoid => false, :port => ssh_info[:port], @@ -175,7 +175,9 @@ module VagrantPlugins } # Check that the private key permissions are valid - Vagrant::Util::SSH.check_key_permissions(Pathname.new(ssh_info[:private_key_path])) + ssh_info[:private_key_path].each do |path| + Vagrant::Util::SSH.check_key_permissions(Pathname.new(path)) + end # Connect to SSH, giving it a few tries connection = nil diff --git a/plugins/kernel_v2/config/ssh_connect.rb b/plugins/kernel_v2/config/ssh_connect.rb index 36799d26a..06d9de10e 100644 --- a/plugins/kernel_v2/config/ssh_connect.rb +++ b/plugins/kernel_v2/config/ssh_connect.rb @@ -18,6 +18,10 @@ module VagrantPlugins @port = nil if @port == UNSET_VALUE @private_key_path = nil if @private_key_path == UNSET_VALUE @username = nil if @username == UNSET_VALUE + + if @private_key_path && !@private_key_path.is_a?(Array) + @private_key_path = [@private_key_path] + end end # NOTE: This is _not_ a valid config validation method, since it @@ -28,9 +32,15 @@ module VagrantPlugins def validate(machine) errors = _detected_errors - if @private_key_path && \ - !File.file?(File.expand_path(@private_key_path, machine.env.root_path)) - errors << I18n.t("vagrant.config.ssh.private_key_missing", :path => @private_key_path) + if @private_key_path + @private_key_path.each do |raw_path| + path = File.expand_path(raw_path, machine.env.root_path) + if !File.file?(path) + errors << I18n.t( + "vagrant.config.ssh.private_key_missing", + path: raw_path) + end + end end errors diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index 8234b7d3c..8eaa30810 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -331,14 +331,22 @@ describe Vagrant::Machine do it "should return the provider private key if given" do provider_ssh_info[:private_key_path] = "/foo" - instance.ssh_info[:private_key_path].should == "/foo" + instance.ssh_info[:private_key_path].should == ["/foo"] end it "should return the configured SSH key path if set" do provider_ssh_info[:private_key_path] = nil instance.config.ssh.private_key_path = "/bar" - instance.ssh_info[:private_key_path].should == "/bar" + instance.ssh_info[:private_key_path].should == ["/bar"] + end + + it "should return the array of SSH keys if set" do + provider_ssh_info[:private_key_path] = nil + instance.config.ssh.private_key_path = ["/foo", "/bar"] + + instance.ssh_info[:private_key_path].should == + ["/foo", "/bar"] end context "expanding path relative to the root path" do @@ -346,7 +354,7 @@ describe Vagrant::Machine do provider_ssh_info[:private_key_path] = "~/foo" instance.ssh_info[:private_key_path].should == - File.expand_path("~/foo", env.root_path) + [File.expand_path("~/foo", env.root_path)] end it "should with the config private key path" do @@ -354,7 +362,7 @@ describe Vagrant::Machine do instance.config.ssh.private_key_path = "~/bar" instance.ssh_info[:private_key_path].should == - File.expand_path("~/bar", env.root_path) + [File.expand_path("~/bar", env.root_path)] end end @@ -362,7 +370,8 @@ describe Vagrant::Machine do provider_ssh_info[:private_key_path] = nil instance.config.ssh.private_key_path = nil - instance.ssh_info[:private_key_path].should == instance.env.default_private_key_path.to_s + instance.ssh_info[:private_key_path].should == + [instance.env.default_private_key_path.to_s] end end end diff --git a/website/docs/source/v2/vagrantfile/ssh_settings.html.md b/website/docs/source/v2/vagrantfile/ssh_settings.html.md index ab9149d38..9737f7ce0 100644 --- a/website/docs/source/v2/vagrantfile/ssh_settings.html.md +++ b/website/docs/source/v2/vagrantfile/ssh_settings.html.md @@ -43,6 +43,10 @@ that ships with Vagrant, since that is what public boxes use. If you make your own custom box with a custom SSH key, this should point to that private key. +You can also specify multiple private keys by setting this to be an array. +This is useful, for example, if you use the default private key to bootstrap +the machine, but replace it with perhaps a more secure key later. +
`config.ssh.forward_agent` - If `true`, agent forwarding over SSH