module Net::SSH
def self._sanitize_options(options)
def self._sanitize_options(options) invalid_option_values = [nil, [nil]] unless (options.values & invalid_option_values).empty? nil_options = options.select { |_k, v| invalid_option_values.include?(v) }.map(&:first) Kernel.warn "#{caller_locations(2, 1)[0]}: Passing nil, or [nil] to Net::SSH.start is deprecated for keys: #{nil_options.join(', ')}" end end
def self._support_deprecated_option_paranoid(options)
def self._support_deprecated_option_paranoid(options) if options.key?(:paranoid) Kernel.warn( ":paranoid is deprecated, please use :verify_host_key. Supported " \ "values are exactly the same, only the name of the option has changed." ) if options.key?(:verify_host_key) Kernel.warn( "Both :paranoid and :verify_host_key were specified. " \ ":verify_host_key takes precedence, :paranoid will be ignored." ) else options[:verify_host_key] = options.delete(:paranoid) end end end
def self.assign_defaults(options)
def self.assign_defaults(options) if !options[:logger] options[:logger] = Logger.new(STDERR) options[:logger].level = Logger::FATAL end options[:password_prompt] ||= Prompt.default(options) %i[password passphrase].each do |key| options.delete(key) if options.key?(key) && options[key].nil? end end
def self.configuration_for(host, use_ssh_config)
to read.
be a file name (or array of file names) of SSH configuration file(s)
loaded (and an empty hash returned). Otherwise, +use_ssh_config+ may
/etc/ssh_config. If +use_ssh_config+ is nil or false, nothing will be
default), this will load configuration from both ~/.ssh/config and
from the SSH configuration file(s). If +use_ssh_config+ is true (the
Returns a hash of the configuration options for the given host, as read
def self.configuration_for(host, use_ssh_config) files = case use_ssh_config when true then Net::SSH::Config.expandable_default_files when false, nil then return {} else Array(use_ssh_config) end Net::SSH::Config.for(host, files) end
def self.start(host, user = nil, options = {}, &block)
If +user+ parameter is nil it defaults to USER from ssh_config, or
* :fingerprint_hash => 'MD5' or 'SHA256', defaults to 'SHA256'
returning false declines it and closes the connection.
the +:fingerprint+ and the +:session+. Returning true accepts the host key,
given to +verify+ is a hash consisting of the +:key+, the +:key_blob+,
You can also provide an own Object which responds to +verify+. The argument
* :always (secure) ::Net::SSH::Verifiers::Always
* :accept_new (insecure) ::Net::SSH::Verifiers::AcceptNew
* :accept_new_or_local_tunnel (insecure) ::Net::SSH::Verifiers::AcceptNewOrLocalTunnel
* :never (very insecure) ::Net::SSH::Verifiers::Never
In order of increasing strictness:
* :verify_host_key => specify how strict host-key verification should be.
example: ->{ UNIXSocket.open('/foo/bar')}
Net::SSH.start(host,user,agent_socket_factory: ->{ UNIXSocket.open('/foo/bar') })
* :agent_socket_factory => enables the user to pass a lambda/block that will serve as the socket factory
* :password_prompt => a custom prompt object with ask method. See Net::SSH::Prompt
password auth method
authentication method defaults to 3 set to 0 to disable prompt for
* :number_of_password_prompts => Number of prompts for the password
algorithms by net-ssh. Was the default behaviour until 2.10
* :append_all_supported_algorithms => set to +true+ to append all supported
supported and are translated to the corresponding Logger constant.
default. The symbols :debug, :info, :warn, :error, and :fatal are also
is very verbose, Logger::FATAL is all but silent). Logger::FATAL is the
* :verbose => how verbose to be (Logger verbosity constants, Logger::DEBUG
* :identity_agent => the path to the ssh-agent's UNIX socket
true
* :use_agent => Set false to disable the use of ssh-agent. Defaults to
Defaults to %w(~/.ssh/known_hosts ~/.ssh/known_hosts2).
Set to an array to specify multiple user known hosts files.
* :user_known_hosts_file => the location of the user known hosts file.
* :remote_user => used for substitution into the '%r' part of a ProxyCommand
configuration file.
parameter, and is primarily only useful when provided via an SSH
* :user => the user name to log in as; this overrides the +user+
* :timeout => how long to wait for the initial connection to be made
remote environment. Override the ones if specified in +send_env+.
* :set_env => a hash of environment variable names and values to set to the
remote environment. Names may be given as String or Regexp.
* :send_env => an array of local environment variable names to export to the
* :rekey_packet_limit => the max number of packets to process before rekeying
* :rekey_limit => the max number of bytes to process before rekeying
* :rekey_blocks_limit => the max number of blocks to process before rekeying
types.
option is only used for RSA public key authentication and ignored for other
'ssh-rsa-cert-v01@openssh.com', 'rsa-sha2-256', 'ssh-rsa'. Currently, this
this connection. Valid values are 'rsa-sha2-256-cert-v01@openssh.com',
* :pubkey_algorithms => the public key authentication algorithms to use for
* :proxy => a proxy instance (see Proxy) to use when connecting
properties (see Net::SSH::Connection::Session#properties)
* :properties => a hash of key/value pairs to add to the new connection's
* :port => the port to use when connecting to the remote host
* :password => the password to use to login
is +nil+, for no passphrase)
* :passphrase => the passphrase to use when loading a private key (default
* :paranoid => deprecated alias for :verify_host_key
asking for password.
should set it to true to prefer failing a password/etc auth methods vs.
authentication failure vs password prompt. Non-interactive applications
* :non_interactive => set to true if your app is non interactive and prefers
the window.
* :max_win_size => maximum size we tell the other side that is supported for
for better performance if your SSH server supports it (most do).
packet. Default is 0x8000 (32768 bytes). Increase to 0x10000 (65536 bytes)
* :max_pkt_size => maximum size we tell the other side that is supported per
* :logger => the logger instance to use when logging
identites.
option is intended for situations where ssh-agent offers many different
+key_data+ parameters, even if ssh-agent offers more identities. This
* :keys_only => set to +true+ to use only private keys from +keys+ and
a raw private key in PEM format.
* :key_data => an array of strings, with each element of the array being
being a key certificate to use with publickey authentication
* :keycert_data => an array of strings, which each element of the array
with publickey authentication
* :keycerts => an array of file names of key certificates to use
and hostbased authentication
* :keys => an array of file names of private keys to use for publickey
* :kex => the key exchange algorithm (or algorithms) to use
Defaults to 3
* :keepalive_maxcount => the maximun number of keepalive packet miss allowed.
Defaults to +300+ seconds.
* :keepalive_interval => the interval seconds for keepalive.
the keepalive_interval seconds. Defaults to +false+.
when there's no traffic between the SSH server and Net::SSH client for
* :keepalive => set to +true+ to send a keepalive packet to the SSH server
to modify /etc/hosts.
"alias", similarly to adding an entry in /etc/hosts but without needing
specified in an SSH configuration file. It lets you specify an
instead of the +host+ parameter, and is primarily only useful when
* :host_name => the real host name or IP to log into. This is used
host to a known_hosts dictionary file
* :host_key_alias => the host name to use when looking up or adding a
* :host_key => the host key algorithm (or algorithms) to use
* :hmac => the hmac algorithm (or algorithms) to use
hosts files. Defaults to %w(/etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2).
file. Set to an array if you want to specify multiple global known
* :global_known_hosts_file => the location of the global known hosts
It must implement #search_for and `add` in a similiar manner as KnownHosts.
* :known_hosts => a custom object holding known hosts records.
be forwarded
* :forward_agent => set to true if you want the SSH agent connection to
* :encryption => the encryption cipher (or ciphers) to use
files. Defaults to +true+.
a file-name (or array of file-names) to load those specific configuration
(~/.ssh/config, /etc/ssh_config), or to +false+ to not load them, or to
* :config => set to +true+ to load the default OpenSSH config files
* :compression_level => the compression level to use when sending data
whatever is supported.
* :compression => the compression algorithm to use, or +true+ to use
Defaults to +true+.
* :check_host_ip => Also ckeck IP address when connecting to remote host.
is set.)
establishing connection. (:bind_address is discarded if :proxy
* :bind_address => the IP address on the connecting machine to use in
* :auth_methods => an array of authentication methods to try
This method accepts the following options (all are optional):
end
ssh.loop
end
end
end
end
ch.send_data("password\n")
if data =~ /sudo password: /
print data
ch.on_data do |ch, data|
abort "could not execute sudo ls" unless success
ch.exec "sudo -p 'sudo password: ' ls" do |ch, success|
ssh.open_channel do |ch|
hostname = ssh.exec!("hostname")
ssh.exec! "cp /some/file /another/location"
Net::SSH.start("host", "user") do |ssh|
Net::SSH::Connection::Channel and Net::SSH::Service::Forward.)
will be an instance of Net::SSH::Connection::Session (q.v.). (See also
the connection will just be returned. The yielded (or returned) value
block, the connection will be closed when the block terminates, otherwise
The standard means of starting a new SSH connection. When used with a
def self.start(host, user = nil, options = {}, &block) invalid_options = options.keys - VALID_OPTIONS if invalid_options.any? raise ArgumentError, "invalid option(s): #{invalid_options.join(', ')}" end assign_defaults(options) _sanitize_options(options) options[:user] = user if user options = configuration_for(host, options.fetch(:config, true)).merge(options) host = options.fetch(:host_name, host) options[:check_host_ip] = true unless options.key?(:check_host_ip) if options[:non_interactive] options[:number_of_password_prompts] = 0 end _support_deprecated_option_paranoid(options) if options[:verbose] options[:logger].level = case options[:verbose] when Integer then options[:verbose] when :debug then Logger::DEBUG when :info then Logger::INFO when :warn then Logger::WARN when :error then Logger::ERROR when :fatal then Logger::FATAL else raise ArgumentError, "can't convert #{options[:verbose].inspect} to any of the Logger level constants" end end transport = Transport::Session.new(host, options) auth = Authentication::Session.new(transport, options) user = options.fetch(:user, user) || Etc.getpwuid.name if auth.authenticate("ssh-connection", user, options[:password]) connection = Connection::Session.new(transport, options) if block_given? begin yield connection ensure connection.close unless connection.closed? end else return connection end else transport.close raise AuthenticationFailed, "Authentication failed for user #{user}@#{host}" end end