From 87437317dc3bb474858814d33a9ce94c38113518 Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Thu, 27 Sep 2018 11:16:50 +0100 Subject: [PATCH 1/7] Add support for passing ssh config file in via config --- plugins/communicators/ssh/communicator.rb | 2 +- plugins/kernel_v2/config/ssh.rb | 3 +++ test/unit/plugins/kernel_v2/config/ssh_test.rb | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index e9b0cce8f..7f0b171dc 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -376,7 +376,7 @@ module VagrantPlugins # Build the options we'll use to initiate the connection via Net::SSH common_connect_opts = { auth_methods: auth_methods, - config: false, + config: ssh_info[:config], forward_agent: ssh_info[:forward_agent], send_env: ssh_info[:forward_env], keys_only: ssh_info[:keys_only], diff --git a/plugins/kernel_v2/config/ssh.rb b/plugins/kernel_v2/config/ssh.rb index 1dc3d51c9..07b362ed6 100644 --- a/plugins/kernel_v2/config/ssh.rb +++ b/plugins/kernel_v2/config/ssh.rb @@ -5,6 +5,7 @@ require_relative "ssh_connect" module VagrantPlugins module Kernel_V2 class SSHConfig < SSHConnectConfig + attr_accessor :config attr_accessor :forward_agent attr_accessor :forward_x11 attr_accessor :forward_env @@ -22,6 +23,7 @@ module VagrantPlugins def initialize super + @config = UNSET_VALUE @forward_agent = UNSET_VALUE @forward_x11 = UNSET_VALUE @forward_env = UNSET_VALUE @@ -46,6 +48,7 @@ module VagrantPlugins def finalize! super + @config = false if @config == UNSET_VALUE @forward_agent = false if @forward_agent == UNSET_VALUE @forward_x11 = false if @forward_x11 == UNSET_VALUE @forward_env = false if @forward_env == UNSET_VALUE diff --git a/test/unit/plugins/kernel_v2/config/ssh_test.rb b/test/unit/plugins/kernel_v2/config/ssh_test.rb index 15e23a7a0..ecb7a0831 100644 --- a/test/unit/plugins/kernel_v2/config/ssh_test.rb +++ b/test/unit/plugins/kernel_v2/config/ssh_test.rb @@ -8,6 +8,8 @@ describe VagrantPlugins::Kernel_V2::SSHConfig do describe "#default" do it "defaults to vagrant username" do subject.finalize! + expect(subject.default.config).to eq(false) + expect(subject.default.port).to eq(22) expect(subject.default.username).to eq("vagrant") end end From 50a569747cd5f8c57cd8be23284eec49cec19e26 Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Thu, 27 Sep 2018 12:23:13 +0100 Subject: [PATCH 2/7] Use 'be_falsey' matcher --- test/unit/plugins/kernel_v2/config/ssh_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/plugins/kernel_v2/config/ssh_test.rb b/test/unit/plugins/kernel_v2/config/ssh_test.rb index ecb7a0831..43e6f72b2 100644 --- a/test/unit/plugins/kernel_v2/config/ssh_test.rb +++ b/test/unit/plugins/kernel_v2/config/ssh_test.rb @@ -8,7 +8,7 @@ describe VagrantPlugins::Kernel_V2::SSHConfig do describe "#default" do it "defaults to vagrant username" do subject.finalize! - expect(subject.default.config).to eq(false) + expect(subject.default.config).to be_falsey expect(subject.default.port).to eq(22) expect(subject.default.username).to eq("vagrant") end From 87e38a0beda6a227e027188f02b54380e0417bcb Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Thu, 27 Sep 2018 12:44:18 +0100 Subject: [PATCH 3/7] Remove 'config' from ssh.defaults, and instead setup in '.connect' --- plugins/communicators/ssh/communicator.rb | 6 ++++- plugins/kernel_v2/config/ssh.rb | 3 --- .../communicators/ssh/communicator_test.rb | 22 +++++++++++++++++++ .../unit/plugins/kernel_v2/config/ssh_test.rb | 1 - 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 7f0b171dc..4e7ab4d51 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -376,7 +376,7 @@ module VagrantPlugins # Build the options we'll use to initiate the connection via Net::SSH common_connect_opts = { auth_methods: auth_methods, - config: ssh_info[:config], + config: false, forward_agent: ssh_info[:forward_agent], send_env: ssh_info[:forward_env], keys_only: ssh_info[:keys_only], @@ -414,6 +414,10 @@ module VagrantPlugins connect_opts[:proxy] = Net::SSH::Proxy::Command.new(ssh_info[:proxy_command]) end + if ssh_info[:config] + connect_opts[:config] = ssh_info[:config] + end + @logger.info("Attempting to connect to SSH...") @logger.info(" - Host: #{ssh_info[:host]}") @logger.info(" - Port: #{ssh_info[:port]}") diff --git a/plugins/kernel_v2/config/ssh.rb b/plugins/kernel_v2/config/ssh.rb index 07b362ed6..1dc3d51c9 100644 --- a/plugins/kernel_v2/config/ssh.rb +++ b/plugins/kernel_v2/config/ssh.rb @@ -5,7 +5,6 @@ require_relative "ssh_connect" module VagrantPlugins module Kernel_V2 class SSHConfig < SSHConnectConfig - attr_accessor :config attr_accessor :forward_agent attr_accessor :forward_x11 attr_accessor :forward_env @@ -23,7 +22,6 @@ module VagrantPlugins def initialize super - @config = UNSET_VALUE @forward_agent = UNSET_VALUE @forward_x11 = UNSET_VALUE @forward_env = UNSET_VALUE @@ -48,7 +46,6 @@ module VagrantPlugins def finalize! super - @config = false if @config == UNSET_VALUE @forward_agent = false if @forward_agent == UNSET_VALUE @forward_x11 = false if @forward_x11 == UNSET_VALUE @forward_env = false if @forward_env == UNSET_VALUE diff --git a/test/unit/plugins/communicators/ssh/communicator_test.rb b/test/unit/plugins/communicators/ssh/communicator_test.rb index 3b2cb9a32..3c54807c8 100644 --- a/test/unit/plugins/communicators/ssh/communicator_test.rb +++ b/test/unit/plugins/communicators/ssh/communicator_test.rb @@ -748,6 +748,28 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do communicator.send(:connect) end end + + context "with config configured" do + + before do + expect(machine).to receive(:ssh_info).and_return( + host: '127.0.0.1', + port: 2222, + config: './ssh_config', + keys_only: true, + verify_host_key: false + ) + end + + it "has password defined" do + expect(Net::SSH).to receive(:start).with( + anything, anything, hash_including( + config: './ssh_config' + ) + ).and_return(true) + communicator.send(:connect) + end + end end describe ".generate_environment_export" do diff --git a/test/unit/plugins/kernel_v2/config/ssh_test.rb b/test/unit/plugins/kernel_v2/config/ssh_test.rb index 43e6f72b2..d654da450 100644 --- a/test/unit/plugins/kernel_v2/config/ssh_test.rb +++ b/test/unit/plugins/kernel_v2/config/ssh_test.rb @@ -8,7 +8,6 @@ describe VagrantPlugins::Kernel_V2::SSHConfig do describe "#default" do it "defaults to vagrant username" do subject.finalize! - expect(subject.default.config).to be_falsey expect(subject.default.port).to eq(22) expect(subject.default.username).to eq("vagrant") end From 122ef7307c9efca26df73eb7731a707a824c43e8 Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Thu, 27 Sep 2018 15:22:51 +0100 Subject: [PATCH 4/7] Flesh out `:config` support. Also noticed whilst testing that if the `ProxyCommand` uses `%r`, then it fails with `unable to find remote user`, so added support for `config.ssh.remote_user` aswell --- lib/vagrant/machine.rb | 4 ++++ plugins/commands/ssh_config/command.rb | 2 ++ plugins/communicators/ssh/communicator.rb | 4 ++++ plugins/kernel_v2/config/ssh_connect.rb | 8 ++++++++ 4 files changed, 18 insertions(+) diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index 450e21fc1..c4fc253d1 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -452,9 +452,11 @@ module Vagrant info[:keys_only] ||= @config.ssh.default.keys_only info[:verify_host_key] ||= @config.ssh.default.verify_host_key info[:username] ||= @config.ssh.default.username + info[:remote_user] ||= @config.ssh.default.remote_user info[:compression] ||= @config.ssh.default.compression info[:dsa_authentication] ||= @config.ssh.default.dsa_authentication info[:extra_args] ||= @config.ssh.default.extra_args + info[:config] ||= @config.ssh.default.config # We set overrides if they are set. These take precedence over # provider-returned data. @@ -466,7 +468,9 @@ module Vagrant info[:dsa_authentication] = @config.ssh.dsa_authentication info[:username] = @config.ssh.username if @config.ssh.username info[:password] = @config.ssh.password if @config.ssh.password + info[:remote_user] = @config.ssh.remote_user if @config.ssh.remote_user info[:extra_args] = @config.ssh.extra_args if @config.ssh.extra_args + info[:config] = @config.ssh.config if @config.ssh.config # We also set some fields that are purely controlled by Vagrant info[:forward_agent] = @config.ssh.forward_agent diff --git a/plugins/commands/ssh_config/command.rb b/plugins/commands/ssh_config/command.rb index 492352f36..c21a9aec7 100644 --- a/plugins/commands/ssh_config/command.rb +++ b/plugins/commands/ssh_config/command.rb @@ -55,6 +55,8 @@ module VagrantPlugins proxy_command: ssh_info[:proxy_command], ssh_command: ssh_info[:ssh_command], forward_env: ssh_info[:forward_env], + config: ssh_info[:config], + remote_user: ssh_info[:remote_user], } # Render the template and output directly to STDOUT diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 4e7ab4d51..c92e39980 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -418,6 +418,10 @@ module VagrantPlugins connect_opts[:config] = ssh_info[:config] end + if ssh_info[:remote_user] + connect_opts[:remote_user] = ssh_info[:remote_user] + end + @logger.info("Attempting to connect to SSH...") @logger.info(" - Host: #{ssh_info[:host]}") @logger.info(" - Port: #{ssh_info[:port]}") diff --git a/plugins/kernel_v2/config/ssh_connect.rb b/plugins/kernel_v2/config/ssh_connect.rb index c4c6fec0e..9e8666d38 100644 --- a/plugins/kernel_v2/config/ssh_connect.rb +++ b/plugins/kernel_v2/config/ssh_connect.rb @@ -3,6 +3,7 @@ module VagrantPlugins class SSHConnectConfig < Vagrant.plugin("2", :config) attr_accessor :host attr_accessor :port + attr_accessor :config attr_accessor :private_key_path attr_accessor :username attr_accessor :password @@ -13,10 +14,12 @@ module VagrantPlugins attr_accessor :compression attr_accessor :dsa_authentication attr_accessor :extra_args + attr_accessor :remote_user def initialize @host = UNSET_VALUE @port = UNSET_VALUE + @config = UNSET_VALUE @private_key_path = UNSET_VALUE @username = UNSET_VALUE @password = UNSET_VALUE @@ -27,6 +30,7 @@ module VagrantPlugins @compression = UNSET_VALUE @dsa_authentication = UNSET_VALUE @extra_args = UNSET_VALUE + @remote_user = UNSET_VALUE end def finalize! @@ -42,6 +46,7 @@ module VagrantPlugins @compression = true if @compression == UNSET_VALUE @dsa_authentication = true if @dsa_authentication == UNSET_VALUE @extra_args = nil if @extra_args == UNSET_VALUE + @remote_user = nil if @remote_user == UNSET_VALUE if @private_key_path && !@private_key_path.is_a?(Array) @private_key_path = [@private_key_path] @@ -51,6 +56,9 @@ module VagrantPlugins @verify_host_key = @paranoid end + # Default to not loading system ssh_config file + @config = false if @config == UNSET_VALUE + # Values for verify_host_key changed in 5.0.0 of net-ssh. If old value # detected, update with new value case @verify_host_key From 9d72feb36c7c55f22027d9d04e92891f2868a69b Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Thu, 27 Sep 2018 16:15:03 +0100 Subject: [PATCH 5/7] Add support for SSH config file to to 'vagrant ssh' command --- lib/vagrant/util/ssh.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/vagrant/util/ssh.rb b/lib/vagrant/util/ssh.rb index 43d1dcfbf..e2b0ffaba 100644 --- a/lib/vagrant/util/ssh.rb +++ b/lib/vagrant/util/ssh.rb @@ -178,6 +178,10 @@ module Vagrant "-o", "ForwardX11Trusted=yes"] end + if ssh_info[:config] + command_options += ["-F", ssh_info[:config]] + end + if ssh_info[:proxy_command] command_options += ["-o", "ProxyCommand=#{ssh_info[:proxy_command]}"] end From 0500f2b9b35d300895d8a45990e3908e0c8910d3 Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Thu, 27 Sep 2018 16:16:03 +0100 Subject: [PATCH 6/7] Add support for SSH config file to Rsync helper --- plugins/synced_folders/rsync/helper.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/synced_folders/rsync/helper.rb b/plugins/synced_folders/rsync/helper.rb index c190cf3c1..5604b83cf 100644 --- a/plugins/synced_folders/rsync/helper.rb +++ b/plugins/synced_folders/rsync/helper.rb @@ -77,6 +77,11 @@ module VagrantPlugins proxy_command = "-o ProxyCommand='#{ssh_info[:proxy_command]}' " end + ssh_config_file = "" + if ssh_info[:config] + ssh_config_file = "-F #{ssh_info[:config]}" + end + # Create the path for the control sockets. We used to do this # in the machine data dir but this can result in paths that are # too long for unix domain sockets. @@ -91,6 +96,7 @@ module VagrantPlugins "ssh", "-p", "#{ssh_info[:port]}", "-o", "LogLevel=#{log_level}", proxy_command, + ssh_config_file, control_options, ] From 90a5854684f5e496f08c1ce99eaddc6fe6560315 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 11 Dec 2018 07:51:44 -0800 Subject: [PATCH 7/7] Fill out ssh options config and remote_user Include config option within ssh_config command output template. Default remote_user value to set username value. Include existence check on provided config value to ensure file is available. Update tests to include coverage on all changes. Add new options to the docs. --- plugins/commands/ssh_config/command.rb | 1 - plugins/kernel_v2/config/ssh_connect.rb | 22 ++- templates/commands/ssh_config/config.erb | 3 + templates/locales/en.yml | 1 + .../commands/ssh_config/command_test.rb | 13 ++ .../communicators/ssh/communicator_test.rb | 24 ++- .../kernel_v2/config/ssh_connect_test.rb | 74 ++++++++++ .../synced_folders/rsync/helper_test.rb | 10 ++ test/unit/vagrant/machine_test.rb | 10 ++ test/unit/vagrant/util/ssh_test.rb | 20 +++ .../docs/vagrantfile/ssh_settings.html.md | 138 +++++++++--------- 11 files changed, 244 insertions(+), 72 deletions(-) diff --git a/plugins/commands/ssh_config/command.rb b/plugins/commands/ssh_config/command.rb index c21a9aec7..8b0d2830a 100644 --- a/plugins/commands/ssh_config/command.rb +++ b/plugins/commands/ssh_config/command.rb @@ -56,7 +56,6 @@ module VagrantPlugins ssh_command: ssh_info[:ssh_command], forward_env: ssh_info[:forward_env], config: ssh_info[:config], - remote_user: ssh_info[:remote_user], } # Render the template and output directly to STDOUT diff --git a/plugins/kernel_v2/config/ssh_connect.rb b/plugins/kernel_v2/config/ssh_connect.rb index 9e8666d38..897046bad 100644 --- a/plugins/kernel_v2/config/ssh_connect.rb +++ b/plugins/kernel_v2/config/ssh_connect.rb @@ -46,19 +46,24 @@ module VagrantPlugins @compression = true if @compression == UNSET_VALUE @dsa_authentication = true if @dsa_authentication == UNSET_VALUE @extra_args = nil if @extra_args == UNSET_VALUE - @remote_user = nil if @remote_user == UNSET_VALUE + @config = nil if @config == UNSET_VALUE if @private_key_path && !@private_key_path.is_a?(Array) @private_key_path = [@private_key_path] end + if @remote_user == UNSET_VALUE + if @username + @remote_user = @username + else + @remote_user = nil + end + end + if @paranoid @verify_host_key = @paranoid end - # Default to not loading system ssh_config file - @config = false if @config == UNSET_VALUE - # Values for verify_host_key changed in 5.0.0 of net-ssh. If old value # detected, update with new value case @verify_host_key @@ -92,6 +97,15 @@ module VagrantPlugins end end + if @config + config_path = File.expand_path(@config, machine.env.root_path) + if !File.file?(config_path) + errors << I18n.t( + "vagrant.config.ssh.ssh_config_missing", + path: @config) + end + end + if @paranoid machine.env.ui.warn(I18n.t("vagrant.config.ssh.paranoid_deprecated")) end diff --git a/templates/commands/ssh_config/config.erb b/templates/commands/ssh_config/config.erb index 8aa244cf0..b0cdbeedc 100644 --- a/templates/commands/ssh_config/config.erb +++ b/templates/commands/ssh_config/config.erb @@ -1,4 +1,7 @@ Host <%= host_key %> +<% if config -%> + Include <%= config %> +<% end -%> HostName <%= ssh_host %> User <%= ssh_user %> Port <%= ssh_port %> diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 3890182b6..5af7bdb11 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -1810,6 +1810,7 @@ en: paranoid_deprecated: |- The key `paranoid` is deprecated. Please use `verify_host_key`. Supported values are exactly the same, only the name of the option has changed. + ssh_config_missing: "`config` file must exist: %{path}" triggers: bad_command_warning: |- The command '%{cmd}' was not found for this trigger. diff --git a/test/unit/plugins/commands/ssh_config/command_test.rb b/test/unit/plugins/commands/ssh_config/command_test.rb index d88a39b66..84f593e54 100644 --- a/test/unit/plugins/commands/ssh_config/command_test.rb +++ b/test/unit/plugins/commands/ssh_config/command_test.rb @@ -165,5 +165,18 @@ Host #{machine.name} expect(output).to include('StrictHostKeyChecking ') expect(output).to include('UserKnownHostsFile ') end + + it "includes custom ssh_config path when provided" do + allow(machine).to receive(:ssh_info) { ssh_info.merge(config: "/custom/ssh/config") } + + output = "" + allow(subject).to receive(:safe_puts) do |data| + output += data if data + end + + subject.execute + + expect(output).to include("Include /custom/ssh/config") + end end end diff --git a/test/unit/plugins/communicators/ssh/communicator_test.rb b/test/unit/plugins/communicators/ssh/communicator_test.rb index 3c54807c8..6a979ecc3 100644 --- a/test/unit/plugins/communicators/ssh/communicator_test.rb +++ b/test/unit/plugins/communicators/ssh/communicator_test.rb @@ -750,7 +750,6 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do end context "with config configured" do - before do expect(machine).to receive(:ssh_info).and_return( host: '127.0.0.1', @@ -761,7 +760,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do ) end - it "has password defined" do + it "has config defined" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( config: './ssh_config' @@ -770,6 +769,27 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do communicator.send(:connect) end end + + context "with remote_user configured" do + let(:remote_user) { double("remote_user") } + + before do + expect(machine).to receive(:ssh_info).and_return( + host: '127.0.0.1', + port: 2222, + remote_user: remote_user + ) + end + + it "has remote_user defined" do + expect(Net::SSH).to receive(:start).with( + anything, anything, hash_including( + remote_user: remote_user + ) + ).and_return(true) + communicator.send(:connect) + end + end end describe ".generate_environment_export" do diff --git a/test/unit/plugins/kernel_v2/config/ssh_connect_test.rb b/test/unit/plugins/kernel_v2/config/ssh_connect_test.rb index 0c2772b66..e11386f31 100644 --- a/test/unit/plugins/kernel_v2/config/ssh_connect_test.rb +++ b/test/unit/plugins/kernel_v2/config/ssh_connect_test.rb @@ -3,6 +3,17 @@ require File.expand_path("../../../../base", __FILE__) require Vagrant.source_root.join("plugins/kernel_v2/config/ssh_connect") describe VagrantPlugins::Kernel_V2::SSHConnectConfig do + include_context "unit" + + let(:iso_env) do + # We have to create a Vagrantfile so there is a root path + env = isolated_environment + env.vagrantfile("") + env.create_vagrant_env + end + + let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) } + subject { described_class.new } describe "#verify_host_key" do @@ -29,4 +40,67 @@ describe VagrantPlugins::Kernel_V2::SSHConnectConfig do expect(subject.verify_host_key).to eq(:always) end end + + describe "#config" do + let(:config_file) { "/path/to/config" } + + before do + # NOTE: The machine instance must be initialized before + # any mocks on File are registered. Otherwise it + # will cause a failure attempting to create the + # instance + machine + allow(File).to receive(:file?). + with(/#{Regexp.escape(config_file)}/). + and_return(true) + end + + it "defaults to nil" do + subject.finalize! + expect(subject.config).to be_nil + end + + it "should return the set path" do + subject.config = config_file + subject.finalize! + expect(subject.config).to eq(config_file) + end + + it "should validate when path exists" do + subject.config = config_file + subject.finalize! + machine + expect(File).to receive(:file?). + with(/#{Regexp.escape(config_file)}/). + and_return(true) + expect(subject.validate(machine)).to be_empty + end + + it "should not validate when path does not exist" do + subject.config = config_file + subject.finalize! + expect(File).to receive(:file?). + with(/#{Regexp.escape(config_file)}/). + and_return(false) + expect(subject.validate(machine)).not_to be_empty + end + end + + describe "#remote_user" do + let(:username) { double("username") } + let(:remote_user) { double("remote_user") } + + it "should default to username value" do + subject.username = username + subject.finalize! + expect(subject.remote_user).to eq(subject.username) + end + + it "should be set to provided value" do + subject.username = username + subject.remote_user = remote_user + subject.finalize! + expect(subject.remote_user).to eq(remote_user) + end + end end diff --git a/test/unit/plugins/synced_folders/rsync/helper_test.rb b/test/unit/plugins/synced_folders/rsync/helper_test.rb index 3e6c1274a..61f83eed0 100644 --- a/test/unit/plugins/synced_folders/rsync/helper_test.rb +++ b/test/unit/plugins/synced_folders/rsync/helper_test.rb @@ -319,5 +319,15 @@ describe VagrantPlugins::SyncedFolderRSync::RsyncHelper do subject.rsync_single(machine, ssh_info, opts) end + + it "includes custom ssh config when set" do + ssh_info[:config] = "/path/to/ssh/config" + expect(Vagrant::Util::Subprocess).to receive(:execute) do |*args| + ssh_config_args = "-F /path/to/ssh/config" + expect(args.any?{|a| a.include?(ssh_config_args)}).to be_truthy + result + end + subject.rsync_single(machine, ssh_info, opts) + end end end diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index 02646e353..e956636b6 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -847,6 +847,16 @@ describe Vagrant::Machine do expect(instance.ssh_info[:private_key_path]).to eql([path]) end + it "should return the remote_user when set" do + instance.config.ssh.remote_user = "remote-user" + expect(instance.ssh_info[:remote_user]).to eq("remote-user") + end + + it "should return the config when set" do + instance.config.ssh.config = "/path/to/ssh_config" + expect(instance.ssh_info[:config]).to eq("/path/to/ssh_config") + end + context "with no data dir" do let(:base) { true } let(:data_dir) { nil } diff --git a/test/unit/vagrant/util/ssh_test.rb b/test/unit/vagrant/util/ssh_test.rb index a8617c6bc..9d84f0225 100644 --- a/test/unit/vagrant/util/ssh_test.rb +++ b/test/unit/vagrant/util/ssh_test.rb @@ -236,6 +236,26 @@ describe Vagrant::Util::SSH do end end + context "when config is provided" do + let(:ssh_info) {{ + host: "localhost", + port: 2222, + username: "vagrant", + config: "/path/to/config" + }} + + it "enables ssh config loading" do + allow(Vagrant::Util::SafeExec).to receive(:exec).and_return(nil) + expect(Vagrant::Util::SafeExec).to receive(:exec) do |exe_path, *args| + expect(exe_path).to eq(ssh_path) + config_options = ["-F", "/path/to/config"] + expect(args & config_options).to eq(config_options) + end + + expect(described_class.exec(ssh_info)).to eq(nil) + end + end + context "with subprocess enabled" do let(:ssh_info) {{ host: "localhost", diff --git a/website/source/docs/vagrantfile/ssh_settings.html.md b/website/source/docs/vagrantfile/ssh_settings.html.md index 12227d7bd..1e457f3b4 100644 --- a/website/source/docs/vagrantfile/ssh_settings.html.md +++ b/website/source/docs/vagrantfile/ssh_settings.html.md @@ -18,54 +18,38 @@ defaults are typically fine, but you can fine tune whatever you would like. ## Available Settings -* `config.ssh.username` (string) - This sets the username that Vagrant will SSH -as by default. Providers are free to override this if they detect a more -appropriate user. By default this is "vagrant", since that is what most -public boxes are made as. +* `config.ssh.compression` (boolean) - If `false`, this setting will not include the +compression setting when ssh'ing into a machine. If this is not set, it will +default to `true` and `Compression=yes` will be enabled with ssh. -* `config.ssh.password` (string) - This sets a password that Vagrant will use to -authenticate the SSH user. Note that Vagrant recommends you use key-based -authentication rather than a password (see `private_key_path`) below. If -you use a password, Vagrant will automatically insert a keypair if -`insert_key` is true. +* `config.ssh.config` (string) - Path to a custom ssh_config file to use for configuring +the SSH connections. -* `config.ssh.host` (string) - The hostname or IP to SSH into. By default this is -empty, because the provider usually figures this out for you. +* `config.ssh.dsa_authentication` (boolean) - If `false`, this setting will not include +`DSAAuthentication` when ssh'ing into a machine. If this is not set, it will +default to `true` and `DSAAuthentication=yes` will be used with ssh. -* `config.ssh.port` (integer) - The port to SSH into. By default this is port 22. +* `config.ssh.export_command_template` (string) - The template used to generate +exported environment variables in the active session. This can be useful +when using a Bourne incompatible shell like C shell. The template supports +two variables which are replaced with the desired environment variable key and +environment variable value: `%ENV_KEY%` and `%ENV_VALUE%`. The default template +is: -* `config.ssh.guest_port` (integer) - The port on the guest that SSH is running on. This -is used by some providers to detect forwarded ports for SSH. For example, if -this is set to 22 (the default), and Vagrant detects a forwarded port to -port 22 on the guest from port 4567 on the host, Vagrant will attempt -to use port 4567 to talk to the guest if there is no other option. + ```ruby + config.ssh.export_command_template = 'export %ENV_KEY%="%ENV_VALUE%"' + ``` -* `config.ssh.private_key_path` (string, array of strings) - The path to the private -key to use to SSH into the guest machine. By default this is the insecure private key -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.keys_only` (boolean) - Only use Vagrant-provided SSH private keys (do not use -any keys stored in ssh-agent). The default value is `true`. - -* `config.ssh.verify_host_key` (string, symbol) - Perform strict host-key verification. The -default value is `:never`. - -* `config.ssh.paranoid` (boolean) - Perform strict host-key verification. The default value is -`false`. - - __Deprecation:__ The `config.ssh.paranoid` option is deprecated and will be removed - in a future release. Please use the `config.ssh.verify_host_key` option instead. +* `config.ssh.extra_args` (array of strings) - This settings value is passed directly +into the ssh executable. This allows you to pass any arbitrary commands to do things such +as reverse tunneling down into the ssh program. These options can either be +single flags set as strings such as `"-6"` for IPV6 or an array of arguments +such as `["-L", "8008:localhost:80"]` for enabling a tunnel from host port 8008 +to port 80 on guest. * `config.ssh.forward_agent` (boolean) - If `true`, agent forwarding over SSH connections is enabled. Defaults to false. -* `config.ssh.forward_x11` (boolean) - If `true`, X11 forwarding over SSH connections -is enabled. Defaults to false. - * `config.ssh.forward_env` (array of strings) - An array of host environment variables to forward to the guest. If you are familiar with OpenSSH, this corresponds to the `SendEnv` parameter. @@ -74,6 +58,18 @@ parameter. config.ssh.forward_env = ["CUSTOM_VAR"] ``` +* `config.ssh.forward_x11` (boolean) - If `true`, X11 forwarding over SSH connections +is enabled. Defaults to false. + +* `config.ssh.guest_port` (integer) - The port on the guest that SSH is running on. This +is used by some providers to detect forwarded ports for SSH. For example, if +this is set to 22 (the default), and Vagrant detects a forwarded port to +port 22 on the guest from port 4567 on the host, Vagrant will attempt +to use port 4567 to talk to the guest if there is no other option. + +* `config.ssh.host` (string) - The hostname or IP to SSH into. By default this is +empty, because the provider usually figures this out for you. + * `config.ssh.insert_key` (boolean) - If `true`, Vagrant will automatically insert a keypair to use for SSH, replacing Vagrant's default insecure key inside the machine if detected. By default, this is true. @@ -83,6 +79,34 @@ if detected. By default, this is true. If you do not have to care about security in your project and want to keep using the default insecure key, set this to `false`. +* `config.ssh.keep_alive` (boolean) - If `true`, this setting SSH will send keep-alive packets +every 5 seconds by default to keep connections alive. + +* `config.ssh.keys_only` (boolean) - Only use Vagrant-provided SSH private keys (do not use +any keys stored in ssh-agent). The default value is `true`. + +* `config.ssh.paranoid` (boolean) - Perform strict host-key verification. The default value is +`false`. + + __Deprecation:__ The `config.ssh.paranoid` option is deprecated and will be removed + in a future release. Please use the `config.ssh.verify_host_key` option instead. + +* `config.ssh.password` (string) - This sets a password that Vagrant will use to +authenticate the SSH user. Note that Vagrant recommends you use key-based +authentication rather than a password (see `private_key_path`) below. If +you use a password, Vagrant will automatically insert a keypair if +`insert_key` is true. + +* `config.ssh.port` (integer) - The port to SSH into. By default this is port 22. + +* `config.ssh.private_key_path` (string, array of strings) - The path to the private +key to use to SSH into the guest machine. By default this is the insecure private key +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.proxy_command` (string) - A command-line command to execute that receives the data to send to SSH on stdin. This can be used to proxy the SSH connection. `%h` in the command is replaced with the host and `%p` is replaced with @@ -99,40 +123,24 @@ the port. streamed to the UI. Instead, the output will be delivered in full to the UI once the command has completed. -* `config.ssh.keep_alive` (boolean) - If `true`, this setting SSH will send keep-alive packets -every 5 seconds by default to keep connections alive. +* `config.ssh.remote_user` (string) - The "remote user" value used to replace the `%r` +character(s) used within a configured `ProxyCommand`. This value is only used by the +net-ssh library (ignored by the `ssh` executable) and should not be used in general. +This defaults to the value of `config.ssh.username`. * `config.ssh.shell` (string) - The shell to use when executing SSH commands from Vagrant. By default this is `bash -l`. Note that this has no effect on the shell you get when you run `vagrant ssh`. This configuration option only affects the shell to use when executing commands internally in Vagrant. -* `config.ssh.export_command_template` (string) - The template used to generate -exported environment variables in the active session. This can be useful -when using a Bourne incompatible shell like C shell. The template supports -two variables which are replaced with the desired environment variable key and -environment variable value: `%ENV_KEY%` and `%ENV_VALUE%`. The default template -is: - - ```ruby - config.ssh.export_command_template = 'export %ENV_KEY%="%ENV_VALUE%"' - ``` - * `config.ssh.sudo_command` (string) - The command to use when executing a command with `sudo`. This defaults to `sudo -E -H %c`. The `%c` will be replaced by the command that is being executed. -* `config.ssh.compression` (boolean) - If `false`, this setting will not include the -compression setting when ssh'ing into a machine. If this is not set, it will -default to `true` and `Compression=yes` will be enabled with ssh. +* `config.ssh.username` (string) - This sets the username that Vagrant will SSH +as by default. Providers are free to override this if they detect a more +appropriate user. By default this is "vagrant", since that is what most +public boxes are made as. -* `config.ssh.dsa_authentication` (boolean) - If `false`, this setting will not include -`DSAAuthentication` when ssh'ing into a machine. If this is not set, it will -default to `true` and `DSAAuthentication=yes` will be used with ssh. - -* `config.ssh.extra_args` (array of strings) - This settings value is passed directly -into the ssh executable. This allows you to pass any arbitrary commands to do things such -as reverse tunneling down into the ssh program. These options can either be -single flags set as strings such as `"-6"` for IPV6 or an array of arguments -such as `["-L", "8008:localhost:80"]` for enabling a tunnel from host port 8008 -to port 80 on guest. +* `config.ssh.verify_host_key` (string, symbol) - Perform strict host-key verification. The +default value is `:never`.