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
This commit is contained in:
Darragh Bailey
2022-03-22 07:09:18 +00:00
committed by GitHub
parent 39084ec86b
commit 55a220f1c8
2 changed files with 22 additions and 13 deletions

View File

@@ -87,12 +87,13 @@ module VagrantPlugins
gateway_ports) gateway_ports)
ssh_info = machine.ssh_info ssh_info = machine.ssh_info
params = %W( params = %W(
-n
-L -L
#{host_ip}:#{host_port}:#{guest_ip}:#{guest_port} #{host_ip}:#{host_port}:#{guest_ip}:#{guest_port}
-N -N
#{ssh_info[:host]} #{ssh_info[:host]}
).join(' ') )
params += ' -g' if gateway_ports params += '-g' if gateway_ports
options = (%W( options = (%W(
User=#{ssh_info[:username]} User=#{ssh_info[:username]}
@@ -105,32 +106,32 @@ module VagrantPlugins
ForwardX11=#{ssh_info[:forward_x11] ? 'yes' : 'no'} ForwardX11=#{ssh_info[:forward_x11] ? 'yes' : 'no'}
IdentitiesOnly=#{ssh_info[:keys_only] ? 'yes' : 'no'} IdentitiesOnly=#{ssh_info[:keys_only] ? 'yes' : 'no'}
) + ssh_info[:private_key_path].map do |pk| ) + ssh_info[:private_key_path].map do |pk|
"IdentityFile='\"#{pk}\"'" "IdentityFile=\"#{pk}\""
end).map { |s| "-o #{s}" }.join(' ') 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... # TODO: instead of this, try and lock and get the stdin from spawn...
ssh_cmd = ''
if host_port <= 1024 if host_port <= 1024
@@lock.synchronize do @@lock.synchronize do
# TODO: add i18n # TODO: add i18n
env[:ui].info 'Requesting sudo for host port(s) <= 1024' env[:ui].info 'Requesting sudo for host port(s) <= 1024'
r = system('sudo -v') r = system('sudo -v')
if r if r
ssh_cmd += 'sudo ' # add sudo prefix ssh_cmd.unshift('sudo') # add sudo prefix
end end
end end
end end
ssh_cmd += "ssh -n #{options} #{params}" @logger.debug "Forwarding port with `#{ssh_cmd.join(' ')}`"
@logger.debug "Forwarding port with `#{ssh_cmd}`"
log_file = ssh_forward_log_file( log_file = ssh_forward_log_file(
env[:machine], host_ip, host_port, guest_ip, guest_port, env[:machine], host_ip, host_port, guest_ip, guest_port,
) )
@logger.info "Logging to #{log_file}" @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 end
def ssh_forward_log_file(machine, host_ip, host_port, guest_ip, guest_port) def ssh_forward_log_file(machine, host_ip, host_port, guest_ip, guest_port)

View File

@@ -132,7 +132,11 @@ describe VagrantPlugins::ProviderLibvirt::Action::ForwardPorts do
it 'should spawn ssh to setup forwarding' do it 'should spawn ssh to setup forwarding' do
expect(env).to receive(:[]).with(:forwarded_ports).and_return([port_options]) 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(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]) 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("#{port_options[:guest]} (guest) => #{port_options[:host]} (host) (adapter eth0)")
expect(ui).to receive(:info).with('Requesting sudo for host port(s) <= 1024') 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(: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]) expect(subject.forward_ports(env)).to eq([port_options])