From 55a220f1c867512cb5725deb81d886c8dccc4441 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Tue, 22 Mar 2022 07:09:18 +0000 Subject: [PATCH] Pass ssh command for port forwarding using array (#1469) Switch to the command as an array format when passing the port forwarding ssh command to spawn to switch to execution of the ssh process directly instead of being executed by the default shell. Fixes: #1467 --- lib/vagrant-libvirt/action/forward_ports.rb | 23 +++++++++++---------- spec/unit/action/forward_ports_spec.rb | 12 +++++++++-- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/vagrant-libvirt/action/forward_ports.rb b/lib/vagrant-libvirt/action/forward_ports.rb index fd45952..ca46cc9 100644 --- a/lib/vagrant-libvirt/action/forward_ports.rb +++ b/lib/vagrant-libvirt/action/forward_ports.rb @@ -87,12 +87,13 @@ module VagrantPlugins gateway_ports) ssh_info = machine.ssh_info params = %W( + -n -L #{host_ip}:#{host_port}:#{guest_ip}:#{guest_port} -N #{ssh_info[:host]} - ).join(' ') - params += ' -g' if gateway_ports + ) + params += '-g' if gateway_ports options = (%W( User=#{ssh_info[:username]} @@ -105,32 +106,32 @@ module VagrantPlugins ForwardX11=#{ssh_info[:forward_x11] ? 'yes' : 'no'} IdentitiesOnly=#{ssh_info[:keys_only] ? 'yes' : 'no'} ) + ssh_info[:private_key_path].map do |pk| - "IdentityFile='\"#{pk}\"'" - end).map { |s| "-o #{s}" }.join(' ') + "IdentityFile=\"#{pk}\"" + end + ).map { |s| ['-o', s] }.flatten - options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.proxy_command + options += ['-o', "ProxyCommand=\"#{ssh_info[:proxy_command]}\""] if machine.provider_config.proxy_command + + ssh_cmd = ['ssh'] + options + params # TODO: instead of this, try and lock and get the stdin from spawn... - ssh_cmd = '' if host_port <= 1024 @@lock.synchronize do # TODO: add i18n env[:ui].info 'Requesting sudo for host port(s) <= 1024' r = system('sudo -v') if r - ssh_cmd += 'sudo ' # add sudo prefix + ssh_cmd.unshift('sudo') # add sudo prefix end end end - ssh_cmd += "ssh -n #{options} #{params}" - - @logger.debug "Forwarding port with `#{ssh_cmd}`" + @logger.debug "Forwarding port with `#{ssh_cmd.join(' ')}`" log_file = ssh_forward_log_file( env[:machine], host_ip, host_port, guest_ip, guest_port, ) @logger.info "Logging to #{log_file}" - spawn(ssh_cmd, [:out, :err] => [log_file, 'w'], :pgroup => true) + spawn(*ssh_cmd, [:out, :err] => [log_file, 'w'], :pgroup => true) end def ssh_forward_log_file(machine, host_ip, host_port, guest_ip, guest_port) diff --git a/spec/unit/action/forward_ports_spec.rb b/spec/unit/action/forward_ports_spec.rb index b87ea2e..5854a30 100644 --- a/spec/unit/action/forward_ports_spec.rb +++ b/spec/unit/action/forward_ports_spec.rb @@ -132,7 +132,11 @@ describe VagrantPlugins::ProviderLibvirt::Action::ForwardPorts do it 'should spawn ssh to setup forwarding' do expect(env).to receive(:[]).with(:forwarded_ports).and_return([port_options]) expect(ui).to receive(:info).with("#{port_options[:guest]} (guest) => #{port_options[:host]} (host) (adapter eth0)") - expect(subject).to receive(:spawn).with(/ssh -n -o User=vagrant -o Port=22.*-L \*:8080:192.168.1.121:80 -N localhost/, anything).and_return(9999) + expect(subject).to receive(:spawn) do |*args, **kwargs| + pargs = RUBY_VERSION < "2.7" ? args[0...-1] : args + expect(pargs).to start_with('ssh', '-o', 'User=vagrant', '-o', 'Port=22') + expect(pargs).to end_with('-n', '-L', '*:8080:192.168.1.121:80', '-N', 'localhost') + end.and_return(9999) expect(subject.forward_ports(env)).to eq([port_options]) @@ -148,7 +152,11 @@ describe VagrantPlugins::ProviderLibvirt::Action::ForwardPorts do expect(ui).to receive(:info).with("#{port_options[:guest]} (guest) => #{port_options[:host]} (host) (adapter eth0)") expect(ui).to receive(:info).with('Requesting sudo for host port(s) <= 1024') expect(subject).to receive(:system).with('sudo -v').and_return(true) - expect(subject).to receive(:spawn).with(/sudo ssh -n -o User=vagrant -o Port=22.*-L \*:80:192.168.1.121:80 -N localhost/, anything).and_return(10000) + expect(subject).to receive(:spawn) do |*args, **kwargs| + pargs = RUBY_VERSION < "2.7" ? args[0...-1] : args + expect(pargs).to start_with('sudo', 'ssh', '-o', 'User=vagrant', '-o', 'Port=22') + expect(pargs).to end_with('-n', '-L', '*:80:192.168.1.121:80', '-N', 'localhost') + end.and_return(10000) expect(subject.forward_ports(env)).to eq([port_options])