From ffec0ff8d979dd01b67ffb765333f583acf2ca48 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 16 Aug 2017 16:09:28 -0700 Subject: [PATCH] (#8697) Introduce extra_args setting for ssh configs Prior to this commit, there was no way to add additional ssh arguments within a Vagrantfile for a given vagrant machine. This commit introduces a new option extra_args that allows users to pass in a single argument or an array of flags that will be added onto the ssh command. --- lib/vagrant/machine.rb | 2 ++ lib/vagrant/util/ssh.rb | 6 ++++ plugins/kernel_v2/config/ssh_connect.rb | 3 ++ test/unit/vagrant/machine_test.rb | 11 ++++++ test/unit/vagrant/util/ssh_test.rb | 36 +++++++++++++++++++ .../docs/vagrantfile/ssh_settings.html.md | 7 ++++ 6 files changed, 65 insertions(+) diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index e375d08ce..58c444a06 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -442,6 +442,7 @@ module Vagrant info[:username] ||= @config.ssh.default.username info[:compression] ||= @config.ssh.default.compression info[:dsa_authentication] ||= @config.ssh.default.dsa_authentication + info[:extra_args] ||= @config.ssh.default.extra_args # We set overrides if they are set. These take precedence over # provider-returned data. @@ -453,6 +454,7 @@ 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[:extra_args] = @config.ssh.extra_args if @config.ssh.extra_args # We also set some fields that are purely controlled by Varant info[:forward_agent] = @config.ssh.forward_agent diff --git a/lib/vagrant/util/ssh.rb b/lib/vagrant/util/ssh.rb index 8177cbc2a..31356b094 100644 --- a/lib/vagrant/util/ssh.rb +++ b/lib/vagrant/util/ssh.rb @@ -167,6 +167,12 @@ module Vagrant # # Without having extra_args be last, the user loses this ability command_options += ["-o", "ForwardAgent=yes"] if ssh_info[:forward_agent] + + # Note about :extra_args + # ssh_info[:extra_args] comes from a machines ssh config in a Vagrantfile, + # where as opts[:extra_args] comes from running the ssh command + command_options += Array(ssh_info[:extra_args]) if ssh_info[:extra_args] + command_options.concat(opts[:extra_args]) if opts[:extra_args] # Build up the host string for connecting diff --git a/plugins/kernel_v2/config/ssh_connect.rb b/plugins/kernel_v2/config/ssh_connect.rb index ba2f3175d..a33abab2e 100644 --- a/plugins/kernel_v2/config/ssh_connect.rb +++ b/plugins/kernel_v2/config/ssh_connect.rb @@ -11,6 +11,7 @@ module VagrantPlugins attr_accessor :paranoid attr_accessor :compression attr_accessor :dsa_authentication + attr_accessor :extra_args def initialize @host = UNSET_VALUE @@ -23,6 +24,7 @@ module VagrantPlugins @paranoid = UNSET_VALUE @compression = UNSET_VALUE @dsa_authentication = UNSET_VALUE + @extra_args = UNSET_VALUE end def finalize! @@ -36,6 +38,7 @@ module VagrantPlugins @paranoid = false if @paranoid == UNSET_VALUE @compression = true if @compression == UNSET_VALUE @dsa_authentication = true if @dsa_authentication == UNSET_VALUE + @extra_args = nil if @extra_args == UNSET_VALUE if @private_key_path && !@private_key_path.is_a?(Array) @private_key_path = [@private_key_path] diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index 6209fcdab..94255c6ab 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -793,6 +793,17 @@ describe Vagrant::Machine do it "paranoid should be default" do expect(instance.ssh_info[:paranoid]).to be(false) end + it "extra_args should be nil" do + expect(instance.ssh_info[:extra_args]).to be(nil) + end + it "extra_args should be set" do + instance.config.ssh.extra_args = ["-L", "127.1.2.7:8008:127.1.2.7:8008"] + expect(instance.ssh_info[:extra_args]).to eq(["-L", "127.1.2.7:8008:127.1.2.7:8008"]) + end + it "extra_args should be set as an array" do + instance.config.ssh.extra_args = "-6" + expect(instance.ssh_info[:extra_args]).to eq("-6") + end it "keys_only should be overridden" do instance.config.ssh.keys_only = false expect(instance.ssh_info[:keys_only]).to be(false) diff --git a/test/unit/vagrant/util/ssh_test.rb b/test/unit/vagrant/util/ssh_test.rb index 3ec0986f6..eb9da43d8 100644 --- a/test/unit/vagrant/util/ssh_test.rb +++ b/test/unit/vagrant/util/ssh_test.rb @@ -162,6 +162,42 @@ describe Vagrant::Util::SSH do end end + context "when extra_args is provided as an array" do + let(:ssh_info) {{ + host: "localhost", + port: 2222, + username: "vagrant", + private_key_path: [temporary_file], + extra_args: ["-L", "8008:localhost:80"] + }} + + it "enables agent forwarding options" do + allow(Vagrant::Util::SafeExec).to receive(:exec).and_return(nil) + + expect(described_class.exec(ssh_info)).to eq(nil) + expect(Vagrant::Util::SafeExec).to have_received(:exec) + .with("ssh", "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-o", "IdentityFile=#{ssh_info[:private_key_path][0]}", "-L", "8008:localhost:80") + end + end + + context "when extra_args is provided as a string" do + let(:ssh_info) {{ + host: "localhost", + port: 2222, + username: "vagrant", + private_key_path: [temporary_file], + extra_args: "-6" + }} + + it "enables agent forwarding options" do + allow(Vagrant::Util::SafeExec).to receive(:exec).and_return(nil) + + expect(described_class.exec(ssh_info)).to eq(nil) + expect(Vagrant::Util::SafeExec).to have_received(:exec) + .with("ssh", "vagrant@localhost", "-p", "2222", "-o", "LogLevel=FATAL", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-o", "IdentityFile=#{ssh_info[:private_key_path][0]}", "-6") + 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 d8ce7584c..929502e7b 100644 --- a/website/source/docs/vagrantfile/ssh_settings.html.md +++ b/website/source/docs/vagrantfile/ssh_settings.html.md @@ -157,3 +157,10 @@ default to `true` and `Compression=yes` will be enabled with ssh. `config.ssh.dsa_authentication` - 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` - 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.