diff options
author | Ryan McGeary <ryan@mcgeary.org> | 2017-02-07 22:27:38 -0700 |
---|---|---|
committer | Miklos Fazekas <mfazekas@szemafor.com> | 2017-02-10 19:23:40 +0100 |
commit | 4ae3bb582b93787de0b7c91301318bf13b9c7012 (patch) | |
tree | 9b2933406c9af7354f5f5ba311a8861980a8ee9a | |
parent | c471af1ee80bb72c7dee731d0fad884f80b8065a (diff) | |
download | net-ssh-4ae3bb582b93787de0b7c91301318bf13b9c7012.tar.gz |
Add Proxy::Jump to simulate ProxyJump option in ssh_config
-rw-r--r-- | lib/net/ssh/proxy/jump.rb | 53 | ||||
-rw-r--r-- | test/test_proxy_jump.rb | 51 |
2 files changed, 104 insertions, 0 deletions
diff --git a/lib/net/ssh/proxy/jump.rb b/lib/net/ssh/proxy/jump.rb new file mode 100644 index 0000000..01aefef --- /dev/null +++ b/lib/net/ssh/proxy/jump.rb @@ -0,0 +1,53 @@ +require 'uri' +require 'net/ssh/proxy/command' + +module Net; module SSH; module Proxy + + # An implementation of a jump proxy. To use it, instantiate it, + # then pass the instantiated object via the :proxy key to + # Net::SSH.start: + # + # require 'net/ssh/proxy/jump' + # + # proxy = Net::SSH::Proxy::Jump.new('user@proxy') + # Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| + # ... + # end + class Jump < Command + + # The jump proxies + attr_reader :jump_proxies + + # Create a new socket factory that tunnels via multiple jump proxes as + # [user@]host[:port]. + def initialize(jump_proxies) + @jump_proxies = jump_proxies + end + + # Return a new socket connected to the given host and port via the jump + # proxy that was requested when the socket factory was instantiated. + def open(host, port, connection_options = nil) + build_proxy_command_equivalent(connection_options) + super + end + + # We cannot build the ProxyCommand template until we know if the :config + # option was specified during `Net::SSH.start`. + def build_proxy_command_equivalent(connection_options = nil) + first_jump, extra_jumps = jump_proxies.split(",", 2) + config = connection_options && connection_options[:config] + uri = URI.parse("ssh://#{first_jump}") + + template = "ssh" + template << " -l #{uri.user}" if uri.user + template << " -p #{uri.port}" if uri.port + template << " -J #{extra_jumps}" if extra_jumps + template << " -F #{config}" if config != true && config + template << " -W %h:%p " + template << uri.host + + @command_line_template = template + end + end + +end; end; end diff --git a/test/test_proxy_jump.rb b/test/test_proxy_jump.rb new file mode 100644 index 0000000..3836303 --- /dev/null +++ b/test/test_proxy_jump.rb @@ -0,0 +1,51 @@ +require_relative 'common' +require 'net/ssh/proxy/jump' + +class TestProxyJump < NetSSHTest + def test_is_a_proxy_command + proxy = Net::SSH::Proxy::Jump.new("user@jumphost") + assert proxy.is_a?(Net::SSH::Proxy::Command) + end + + def test_host + proxy = Net::SSH::Proxy::Jump.new("jumphost") + proxy.build_proxy_command_equivalent + assert_equal "ssh -W %h:%p jumphost", proxy.command_line_template + end + + def test_user_host + proxy = Net::SSH::Proxy::Jump.new("sally@proxy") + proxy.build_proxy_command_equivalent + assert_equal "ssh -l sally -W %h:%p proxy", proxy.command_line_template + end + + def test_user_host_port + proxy = Net::SSH::Proxy::Jump.new("bob@jump:2222") + proxy.build_proxy_command_equivalent + assert_equal "ssh -l bob -p 2222 -W %h:%p jump", proxy.command_line_template + end + + def test_multiple_jump_proxies + proxy = Net::SSH::Proxy::Jump.new("user1@proxy1,user2@proxy2,user3@proxy3") + proxy.build_proxy_command_equivalent + assert_equal "ssh -l user1 -J user2@proxy2,user3@proxy3 -W %h:%p proxy1", proxy.command_line_template + end + + def test_config_override + proxy = Net::SSH::Proxy::Jump.new("proxy") + proxy.build_proxy_command_equivalent(config: "/home/user/.ssh/config2") + assert_equal "ssh -F /home/user/.ssh/config2 -W %h:%p proxy", proxy.command_line_template + end + + def test_config_false + proxy = Net::SSH::Proxy::Jump.new("proxy") + proxy.build_proxy_command_equivalent(config: false) + assert_equal "ssh -W %h:%p proxy", proxy.command_line_template + end + + def test_config_true + proxy = Net::SSH::Proxy::Jump.new("proxy") + proxy.build_proxy_command_equivalent(config: true) + assert_equal "ssh -W %h:%p proxy", proxy.command_line_template + end +end |