From dbab46d5f8228f8dd56bbca2e63405e818c598f9 Mon Sep 17 00:00:00 2001 From: Saku Ytti Date: Mon, 29 Aug 2016 14:27:57 +0300 Subject: support terminal and ssh auth for same model Some boxes like prokurwa may authenticate via SSH (proper), or may have no auth on SSH and use terminal auth (improper) Even if SSH is configured for terminal auth, in this change we attempt to detect prompt, so that we won't expect terminal auth, even when requested, if it is not presented. --- lib/oxidized/input/ssh.rb | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index cd12167..c0b7cf9 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -42,7 +42,7 @@ module Oxidized unless @exec shell_open @ssh begin - @username ? shell_login : expect(@node.prompt) + login rescue Timeout::Error raise PromptUndetect, [ @output, 'not matching configured prompt', @node.prompt ].join(' ') end @@ -102,13 +102,18 @@ module Oxidized end end - # Cisco WCS has extremely dubious SSH implementation, SSH auth is always - # success, it always opens shell and then run auth in shell. I guess - # they'll never support exec() :) - def shell_login - expect username - cmd @node.auth[:username], password - cmd @node.auth[:password] + # some models have SSH auth or terminal auth based on version of code + # if SSH is configured for terminal auth, we'll still try to detect prompt + def login + if @username + match = expect username, @node.prompt + if match == username + cmd @node.auth[:username], password + cmd @node.auth[:password] + end + else + expect @node.prompt + end end def exec state=nil @@ -123,14 +128,18 @@ module Oxidized @output end - def expect regexp - Oxidized.logger.debug "lib/oxidized/input/ssh.rb: expecting #{regexp.inspect} at #{node.name}" + def expect *regexps + regexps = [regexps].flatten + Oxidized.logger.debug "lib/oxidized/input/ssh.rb: expecting #{regexps.inspect} at #{node.name}" Timeout::timeout(Oxidized.config.timeout) do @ssh.loop(0.1) do sleep 0.1 - not @output.match regexp + match = regexps.find { |regexp| @output.match regexp } + return match if match + true end end end + end end -- cgit v1.2.1 From 87e95ab4f947d33e0fc42bb8892cb0112f620b43 Mon Sep 17 00:00:00 2001 From: MajesticFalcon Date: Tue, 30 Aug 2016 17:49:14 -0500 Subject: Add UDP TFTP --- lib/oxidized/input/tftp | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/oxidized/input/tftp (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/tftp b/lib/oxidized/input/tftp new file mode 100644 index 0000000..bfb69f6 --- /dev/null +++ b/lib/oxidized/input/tftp @@ -0,0 +1,58 @@ +module Oxidized + require 'net/tftp' + require 'timeout' + require 'stringio' + require_relative 'cli' + + class TFTP < Input + RescueFail = { + :debug => [ + #Net::SSH::Disconnect, + ], + :warn => [ + #RuntimeError, + #Net::SSH::AuthenticationFailed, + ], + } + + include Input::CLI + + # TFTP utilizes UDP, there is not a connection. We simply specify an IP and send/receive data. + def connect node + @node = node + + @node.model.cfg['tftp'].each { |cb| instance_exec(&cb) } + @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-tftp", 'w') if Oxidized.config.input.debug? + @tftp = Net::TFTP.new @node.ip + end + + def cmd file + Oxidized.logger.info file.methods(true) + Oxidized.logger.debug "TFTP: #{file} @ #{@node.name}" + config = StringIO.new + @tftp.getbinary file, config + config.rewind + config.read + end + + + # meh not sure if this is the best way, but perhaps better than not implementing send + def send my_proc + my_proc.call + end + + def output + "" + end + + private + + def disconnect + # TFTP uses UDP, there is no connection to close + #rescue Errno::ECONNRESET, IOError + ensure + @log.close if Oxidized.config.input.debug? + end + + end +end -- cgit v1.2.1 From 35f20515be92d57245abd24b9b2969d5d70922ba Mon Sep 17 00:00:00 2001 From: MajesticFalcon Date: Tue, 30 Aug 2016 17:56:09 -0500 Subject: Update tftp --- lib/oxidized/input/tftp | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/tftp b/lib/oxidized/input/tftp index bfb69f6..cac8f2d 100644 --- a/lib/oxidized/input/tftp +++ b/lib/oxidized/input/tftp @@ -49,7 +49,6 @@ module Oxidized def disconnect # TFTP uses UDP, there is no connection to close - #rescue Errno::ECONNRESET, IOError ensure @log.close if Oxidized.config.input.debug? end -- cgit v1.2.1 From cc1184abc98fd270ee8fee4925f38de08c908bb8 Mon Sep 17 00:00:00 2001 From: MajesticFalcon Date: Tue, 30 Aug 2016 18:02:00 -0500 Subject: Update Filename and tftp load --- lib/oxidized/input/tftp | 57 ------------------------------------------ lib/oxidized/input/tftp.rb | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 57 deletions(-) delete mode 100644 lib/oxidized/input/tftp create mode 100644 lib/oxidized/input/tftp.rb (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/tftp b/lib/oxidized/input/tftp deleted file mode 100644 index cac8f2d..0000000 --- a/lib/oxidized/input/tftp +++ /dev/null @@ -1,57 +0,0 @@ -module Oxidized - require 'net/tftp' - require 'timeout' - require 'stringio' - require_relative 'cli' - - class TFTP < Input - RescueFail = { - :debug => [ - #Net::SSH::Disconnect, - ], - :warn => [ - #RuntimeError, - #Net::SSH::AuthenticationFailed, - ], - } - - include Input::CLI - - # TFTP utilizes UDP, there is not a connection. We simply specify an IP and send/receive data. - def connect node - @node = node - - @node.model.cfg['tftp'].each { |cb| instance_exec(&cb) } - @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-tftp", 'w') if Oxidized.config.input.debug? - @tftp = Net::TFTP.new @node.ip - end - - def cmd file - Oxidized.logger.info file.methods(true) - Oxidized.logger.debug "TFTP: #{file} @ #{@node.name}" - config = StringIO.new - @tftp.getbinary file, config - config.rewind - config.read - end - - - # meh not sure if this is the best way, but perhaps better than not implementing send - def send my_proc - my_proc.call - end - - def output - "" - end - - private - - def disconnect - # TFTP uses UDP, there is no connection to close - ensure - @log.close if Oxidized.config.input.debug? - end - - end -end diff --git a/lib/oxidized/input/tftp.rb b/lib/oxidized/input/tftp.rb new file mode 100644 index 0000000..2a6a088 --- /dev/null +++ b/lib/oxidized/input/tftp.rb @@ -0,0 +1,62 @@ +module Oxidized + require 'timeout' + require 'stringio' + require_relative 'cli' + + class TFTP < Input + RescueFail = { + :debug => [ + #Net::SSH::Disconnect, + ], + :warn => [ + #RuntimeError, + #Net::SSH::AuthenticationFailed, + ], + } + + include Input::CLI + + # TFTP utilizes UDP, there is not a connection. We simply specify an IP and send/receive data. + def connect node + begin + require 'net/tftp' + rescue LoadError + raise OxidizedError, 'net/tftp not found: sudo gem install net-tftp' + end + @node = node + + @node.model.cfg['tftp'].each { |cb| instance_exec(&cb) } + @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-tftp", 'w') if Oxidized.config.input.debug? + @tftp = Net::TFTP.new @node.ip + end + + def cmd file + Oxidized.logger.info file.methods(true) + Oxidized.logger.debug "TFTP: #{file} @ #{@node.name}" + config = StringIO.new + @tftp.getbinary file, config + config.rewind + config.read + end + + + # meh not sure if this is the best way, but perhaps better than not implementing send + def send my_proc + my_proc.call + end + + def output + "" + end + + private + + def disconnect + # TFTP uses UDP, there is no connection to close + #rescue Errno::ECONNRESET, IOError + ensure + @log.close if Oxidized.config.input.debug? + end + + end +end -- cgit v1.2.1 From f9bd7b3b3564d99fb34c82edfc6b779b76496758 Mon Sep 17 00:00:00 2001 From: MajesticFalcon Date: Tue, 30 Aug 2016 18:07:58 -0500 Subject: Remove unnecessary debugging --- lib/oxidized/input/tftp.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/tftp.rb b/lib/oxidized/input/tftp.rb index 2a6a088..c2f3a16 100644 --- a/lib/oxidized/input/tftp.rb +++ b/lib/oxidized/input/tftp.rb @@ -31,7 +31,6 @@ module Oxidized end def cmd file - Oxidized.logger.info file.methods(true) Oxidized.logger.debug "TFTP: #{file} @ #{@node.name}" config = StringIO.new @tftp.getbinary file, config -- cgit v1.2.1 From 5d99baa74881271af4e73a2072325b5959ed9371 Mon Sep 17 00:00:00 2001 From: MajesticFalcon Date: Tue, 30 Aug 2016 18:20:31 -0500 Subject: Update tftp.rb --- lib/oxidized/input/tftp.rb | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/tftp.rb b/lib/oxidized/input/tftp.rb index c2f3a16..18028c6 100644 --- a/lib/oxidized/input/tftp.rb +++ b/lib/oxidized/input/tftp.rb @@ -2,27 +2,19 @@ module Oxidized require 'timeout' require 'stringio' require_relative 'cli' - + + begin + require 'net/tftp' + rescue LoadError + raise OxidizedError, 'net/tftp not found: sudo gem install net-tftp' + end + class TFTP < Input - RescueFail = { - :debug => [ - #Net::SSH::Disconnect, - ], - :warn => [ - #RuntimeError, - #Net::SSH::AuthenticationFailed, - ], - } include Input::CLI # TFTP utilizes UDP, there is not a connection. We simply specify an IP and send/receive data. def connect node - begin - require 'net/tftp' - rescue LoadError - raise OxidizedError, 'net/tftp not found: sudo gem install net-tftp' - end @node = node @node.model.cfg['tftp'].each { |cb| instance_exec(&cb) } @@ -38,21 +30,10 @@ module Oxidized config.read end - - # meh not sure if this is the best way, but perhaps better than not implementing send - def send my_proc - my_proc.call - end - - def output - "" - end - private - + def disconnect # TFTP uses UDP, there is no connection to close - #rescue Errno::ECONNRESET, IOError ensure @log.close if Oxidized.config.input.debug? end -- cgit v1.2.1 From 8473dd0a6df171733ca6c02670ed1e1a5f894b00 Mon Sep 17 00:00:00 2001 From: MajesticFalcon Date: Tue, 30 Aug 2016 18:21:03 -0500 Subject: Update tftp.rb --- lib/oxidized/input/tftp.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/tftp.rb b/lib/oxidized/input/tftp.rb index 18028c6..78164d0 100644 --- a/lib/oxidized/input/tftp.rb +++ b/lib/oxidized/input/tftp.rb @@ -1,5 +1,4 @@ module Oxidized - require 'timeout' require 'stringio' require_relative 'cli' -- cgit v1.2.1 From 22755169b513ebde33de2704afd2f7a0b366723a Mon Sep 17 00:00:00 2001 From: Denver Abrey Date: Thu, 13 Oct 2016 22:00:33 +0200 Subject: Add key authentication to ssh input --- lib/oxidized/input/ssh.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index c0b7cf9..32f4e40 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -23,6 +23,7 @@ module Oxidized secure = Oxidized.config.input.ssh.secure @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-ssh", 'w') if Oxidized.config.input.debug? port = vars(:ssh_port) || 22 + keys = node.auth[:private_key].is_a?(Array) ? @node.auth[:private_key] : [@node.auth[:private_key]] if proxy_host = vars(:ssh_proxy) proxy = Net::SSH::Proxy::Command.new("ssh #{proxy_host} -W %h:%p") end @@ -32,7 +33,8 @@ module Oxidized :paranoid => secure, :auth_methods => %w(none publickey password keyboard-interactive), :number_of_password_prompts => 0, - :proxy => proxy + :proxy => proxy, + :keys => keys } ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex) ssh_opts[:encryption] = vars(:ssh_encryption).split(/,\s*/) if vars(:ssh_encryption) -- cgit v1.2.1 From 75534fa493013a5e563877ffc05eca6f4372999c Mon Sep 17 00:00:00 2001 From: Denver Abrey Date: Mon, 17 Oct 2016 20:42:10 +0200 Subject: Use variable vars(:ssh_keys) for private key authentication --- lib/oxidized/input/ssh.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index 32f4e40..15f1427 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -23,7 +23,6 @@ module Oxidized secure = Oxidized.config.input.ssh.secure @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-ssh", 'w') if Oxidized.config.input.debug? port = vars(:ssh_port) || 22 - keys = node.auth[:private_key].is_a?(Array) ? @node.auth[:private_key] : [@node.auth[:private_key]] if proxy_host = vars(:ssh_proxy) proxy = Net::SSH::Proxy::Command.new("ssh #{proxy_host} -W %h:%p") end @@ -34,9 +33,9 @@ module Oxidized :auth_methods => %w(none publickey password keyboard-interactive), :number_of_password_prompts => 0, :proxy => proxy, - :keys => keys } - ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex) + ssh_opts[:keys] = vars(:ssh_keys).is_a?(Array) ? vars(:ssh_keys) : [vars(:ssh_keys)] if vars(:ssh_keys) + ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex) ssh_opts[:encryption] = vars(:ssh_encryption).split(/,\s*/) if vars(:ssh_encryption) Oxidized.logger.debug "lib/oxidized/input/ssh.rb: Connecting to #{@node.name}" -- cgit v1.2.1 From 98ee2d2fadd56b9efadfc4f9ff667f71f6b22f6c Mon Sep 17 00:00:00 2001 From: Saku Ytti Date: Mon, 31 Oct 2016 17:54:47 +0200 Subject: Allow model to specify SSH PTY options --- lib/oxidized/input/ssh.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index 15f1427..30b481d 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -17,8 +17,9 @@ module Oxidized class NoShell < OxidizedError; end def connect node - @node = node - @output = '' + @node = node + @output = '' + @pty_options = { term: "vt100" } @node.model.cfg['ssh'].each { |cb| instance_exec(&cb) } secure = Oxidized.config.input.ssh.secure @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-ssh", 'w') if Oxidized.config.input.debug? @@ -74,6 +75,10 @@ module Oxidized private + def pty_options hash + @pty_options = @pty_options.merge hash + end + def disconnect disconnect_cli # if disconnect does not disconnect us, give up after timeout @@ -94,7 +99,7 @@ module Oxidized @output << data @output = @node.model.expects @output end - ch.request_pty (_opts={:term=>'vt100'}) do |_ch, success_pty| + ch.request_pty (@pty_options) do |_ch, success_pty| raise NoShell, "Can't get PTY" unless success_pty ch.send_channel_request 'shell' do |_ch, success_shell| raise NoShell, "Can't get shell" unless success_shell -- cgit v1.2.1 From a87fc34a84a893b86d5ccb401d3bd4b9e544bfc2 Mon Sep 17 00:00:00 2001 From: Saku Ytti Date: Mon, 31 Oct 2016 17:56:37 +0200 Subject: it shouldn't be a private method --- lib/oxidized/input/ssh.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/oxidized/input') diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb index 30b481d..9a5c508 100644 --- a/lib/oxidized/input/ssh.rb +++ b/lib/oxidized/input/ssh.rb @@ -73,12 +73,12 @@ module Oxidized @output end - private - def pty_options hash @pty_options = @pty_options.merge hash end + private + def disconnect disconnect_cli # if disconnect does not disconnect us, give up after timeout -- cgit v1.2.1