summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan McGeary <ryan@mcgeary.org>2017-02-07 22:27:38 -0700
committerMiklos Fazekas <mfazekas@szemafor.com>2017-02-10 19:23:40 +0100
commit4ae3bb582b93787de0b7c91301318bf13b9c7012 (patch)
tree9b2933406c9af7354f5f5ba311a8861980a8ee9a
parentc471af1ee80bb72c7dee731d0fad884f80b8065a (diff)
downloadnet-ssh-4ae3bb582b93787de0b7c91301318bf13b9c7012.tar.gz
Add Proxy::Jump to simulate ProxyJump option in ssh_config
-rw-r--r--lib/net/ssh/proxy/jump.rb53
-rw-r--r--test/test_proxy_jump.rb51
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