Class: KnifeBastion::ClientProxy

Inherits:
BasicObject
Defined in:
lib/knife-bastion/client_proxy.rb

Overview

Simple class, that delegates all the calls to the base client object. The latter is overwritten to first configure SOCKS proxy, and if connection fails - show warning about the bastion setup.

Constant Summary collapse

NETWORK_ERRORS =
[
  ::SocketError,
  ::Errno::ETIMEDOUT,
  ::Errno::ECONNRESET,
  ::Errno::ECONNREFUSED,
  ::Timeout::Error,
  ::OpenSSL::SSL::SSLError,
  defined?(::Berkshelf::ChefConnectionError) ? ::Berkshelf::ChefConnectionError : nil,
].compact.freeze

Instance Method Summary collapse

Constructor Details

#initialize(client, options = {}) ⇒ ClientProxy

Initializes an instance of the generic client proxy which sends all the

network traffic through the SOCKS proxy.

Parameters:

  • client (Object)

    the client object which communicates with the server over the network.

  • options (Hash) (defaults to: {})

    the configuration of the client proxy.

Options Hash (options):

  • :local_port (Integer) — default: 4443

    The local port of the SOCKS proxy.

  • :error_handler (Proc)

    network errors handler. By default it prints out a message which explains that the error may occur becase the bastion proxy has not been started.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/knife-bastion/client_proxy.rb', line 31

def initialize(client, options = {})
  @client = client

  @local_port = options[:local_port] || 4443

  server_type = ::HighLine.color("#{options[:server_type]} ", [:bold, :cyan]) if options[:server_type]
  @network_errors_handler = options[:error_handler] || -> (_) {
    ::Kernel.puts
    ::Kernel.puts '-' * 80
    ::Kernel.puts ::HighLine.color("WARNING:", [:bold, :red]) + " Failed to contact #{server_type}server!"
    ::Kernel.puts "You might need to start bastion connection with #{::HighLine.color("knife bastion start", [:bold, :magenta])} to access server."
    ::Kernel.puts '-' * 80
    ::Kernel.puts
    ::Kernel.raise
  }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

Wraps all original client calls into a with_socks_proxy method.



49
50
51
52
53
# File 'lib/knife-bastion/client_proxy.rb', line 49

def method_missing(method, *args, &block)
  with_socks_proxy do
    @client.send(method, *args, &block)
  end
end

Instance Method Details

#with_socks_proxyObject

Routes all network connections through the bastion proxy.



56
57
58
59
60
61
62
63
64
# File 'lib/knife-bastion/client_proxy.rb', line 56

def with_socks_proxy
  old_socks_server, old_socks_port = ::TCPSocket::socks_server, ::TCPSocket::socks_port
  ::TCPSocket::socks_server, ::TCPSocket::socks_port = '127.0.0.1', @local_port
  yield
rescue *NETWORK_ERRORS => e
  @network_errors_handler.call(e)
ensure
  ::TCPSocket::socks_server, ::TCPSocket::socks_port = old_socks_server, old_socks_port
end