Class | Net::SSH::Authentication::KeyManager |
In: |
lib/net/ssh/authentication/key_manager.rb
lib/net/ssh/authentication/key_manager.rb |
Parent: | Object |
This class encapsulates all operations done by clients on a user‘s private keys. In practice, the client should never need a reference to a private key; instead, they grab a list of "identities" (public keys) that are available from the KeyManager, and then use the KeyManager to do various private key operations using those identities.
The KeyManager also uses the Agent class to encapsulate the ssh-agent. Thus, from a client‘s perspective it is completely hidden whether an identity comes from the ssh-agent or from a file on disk.
key_files | [R] | The list of user key files that will be examined |
key_files | [R] | The list of user key files that will be examined |
known_identities | [R] | The map of loaded identities |
known_identities | [R] | The map of loaded identities |
options | [R] | The map of options that were passed to the key-manager |
options | [R] | The map of options that were passed to the key-manager |
Create a new KeyManager. By default, the manager will use the ssh-agent (if it is running).
# File lib/net/ssh/authentication/key_manager.rb, line 38 38: def initialize(logger, options={}) 39: self.logger = logger 40: @key_files = [] 41: @use_agent = true 42: @known_identities = {} 43: @agent = nil 44: @options = options 45: end
Create a new KeyManager. By default, the manager will use the ssh-agent (if it is running).
# File lib/net/ssh/authentication/key_manager.rb, line 38 38: def initialize(logger, options={}) 39: self.logger = logger 40: @key_files = [] 41: @use_agent = true 42: @known_identities = {} 43: @agent = nil 44: @options = options 45: end
Add the given key_file to the list of key files that will be used.
# File lib/net/ssh/authentication/key_manager.rb, line 58 58: def add(key_file) 59: key_files.push(File.expand_path(key_file)).uniq! 60: self 61: end
Add the given key_file to the list of key files that will be used.
# File lib/net/ssh/authentication/key_manager.rb, line 58 58: def add(key_file) 59: key_files.push(File.expand_path(key_file)).uniq! 60: self 61: end
Returns an Agent instance to use for communicating with an SSH agent process. Returns nil if use of an SSH agent has been disabled, or if the agent is otherwise not available.
# File lib/net/ssh/authentication/key_manager.rb, line 155 155: def agent 156: return unless use_agent? 157: @agent ||= Agent.connect(logger) 158: rescue AgentNotAvailable 159: @use_agent = false 160: nil 161: end
Returns an Agent instance to use for communicating with an SSH agent process. Returns nil if use of an SSH agent has been disabled, or if the agent is otherwise not available.
# File lib/net/ssh/authentication/key_manager.rb, line 155 155: def agent 156: return unless use_agent? 157: @agent ||= Agent.connect(logger) 158: rescue AgentNotAvailable 159: @use_agent = false 160: nil 161: end
Clear all knowledge of any loaded user keys. This also clears the list of default identity files that are to be loaded, thus making it appropriate to use if a client wishes to NOT use the default identity files.
# File lib/net/ssh/authentication/key_manager.rb, line 51 51: def clear! 52: key_files.clear 53: known_identities.clear 54: self 55: end
Clear all knowledge of any loaded user keys. This also clears the list of default identity files that are to be loaded, thus making it appropriate to use if a client wishes to NOT use the default identity files.
# File lib/net/ssh/authentication/key_manager.rb, line 51 51: def clear! 52: key_files.clear 53: known_identities.clear 54: self 55: end
Iterates over all available identities (public keys) known to this manager. As it finds one, it will then yield it to the caller. The origin of the identities may be from files on disk or from an ssh-agent. Note that identities from an ssh-agent are always listed first in the array, with other identities coming after.
# File lib/net/ssh/authentication/key_manager.rb, line 82 82: def each_identity 83: if agent 84: agent.identities.each do |key| 85: known_identities[key] = { :from => :agent } 86: yield key 87: end 88: end 89: 90: key_files.each do |file| 91: if File.readable?(file) 92: begin 93: private_key = KeyFactory.load_private_key(file) 94: key = private_key.send :public_key 95: known_identities[key] = { :from => :file, :file => file } 96: yield key 97: rescue Exception => e 98: error { "could not load public key file `#{file}.pub': #{e.class} (#{e.message})" } 99: end 100: end 101: end 102: 103: self 104: end
Iterates over all available identities (public keys) known to this manager. As it finds one, it will then yield it to the caller. The origin of the identities may be from files on disk or from an ssh-agent. Note that identities from an ssh-agent are always listed first in the array, with other identities coming after.
# File lib/net/ssh/authentication/key_manager.rb, line 82 82: def each_identity 83: if agent 84: agent.identities.each do |key| 85: known_identities[key] = { :from => :agent } 86: yield key 87: end 88: end 89: 90: key_files.each do |file| 91: if File.readable?(file) 92: begin 93: private_key = KeyFactory.load_private_key(file) 94: key = private_key.send :public_key 95: known_identities[key] = { :from => :file, :file => file } 96: yield key 97: rescue Exception => e 98: error { "could not load public key file `#{file}.pub': #{e.class} (#{e.message})" } 99: end 100: end 101: end 102: 103: self 104: end
This is used as a hint to the KeyManager indicating that the agent connection is no longer needed. Any other open resources may be closed at this time.
Calling this does NOT indicate that the KeyManager will no longer be used. Identities may still be requested and operations done on loaded identities, in which case, the agent will be automatically reconnected. This method simply allows the client connection to be closed when it will not be used in the immediate future.
# File lib/net/ssh/authentication/key_manager.rb, line 72 72: def finish 73: @agent.close if @agent 74: @agent = nil 75: end
This is used as a hint to the KeyManager indicating that the agent connection is no longer needed. Any other open resources may be closed at this time.
Calling this does NOT indicate that the KeyManager will no longer be used. Identities may still be requested and operations done on loaded identities, in which case, the agent will be automatically reconnected. This method simply allows the client connection to be closed when it will not be used in the immediate future.
# File lib/net/ssh/authentication/key_manager.rb, line 72 72: def finish 73: @agent.close if @agent 74: @agent = nil 75: end
Sign the given data, using the corresponding private key of the given identity. If the identity was originally obtained from an ssh-agent, then the ssh-agent will be used to sign the data, otherwise the private key for the identity will be loaded from disk (if it hasn‘t been loaded already) and will then be used to sign the data.
Regardless of the identity‘s origin or who does the signing, this will always return the signature in an SSH2-specified "signature blob" format.
# File lib/net/ssh/authentication/key_manager.rb, line 115 115: def sign(identity, data) 116: info = known_identities[identity] or raise KeyManagerError, "the given identity is unknown to the key manager" 117: 118: if info[:key].nil? && info[:from] == :file 119: begin 120: info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase]) 121: rescue Exception => e 122: raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})" 123: end 124: end 125: 126: if info[:key] 127: return Net::SSH::Buffer.from(:string, identity.ssh_type, 128: :string, info[:key].ssh_do_sign(data.to_s)).to_s 129: end 130: 131: if info[:from] == :agent 132: raise KeyManagerError, "the agent is no longer available" unless agent 133: return agent.sign(identity, data.to_s) 134: end 135: 136: raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})" 137: end
Sign the given data, using the corresponding private key of the given identity. If the identity was originally obtained from an ssh-agent, then the ssh-agent will be used to sign the data, otherwise the private key for the identity will be loaded from disk (if it hasn‘t been loaded already) and will then be used to sign the data.
Regardless of the identity‘s origin or who does the signing, this will always return the signature in an SSH2-specified "signature blob" format.
# File lib/net/ssh/authentication/key_manager.rb, line 115 115: def sign(identity, data) 116: info = known_identities[identity] or raise KeyManagerError, "the given identity is unknown to the key manager" 117: 118: if info[:key].nil? && info[:from] == :file 119: begin 120: info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase]) 121: rescue Exception => e 122: raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})" 123: end 124: end 125: 126: if info[:key] 127: return Net::SSH::Buffer.from(:string, identity.ssh_type, 128: :string, info[:key].ssh_do_sign(data.to_s)).to_s 129: end 130: 131: if info[:from] == :agent 132: raise KeyManagerError, "the agent is no longer available" unless agent 133: return agent.sign(identity, data.to_s) 134: end 135: 136: raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})" 137: end
Toggles whether the ssh-agent will be used or not. If true, an attempt will be made to use the ssh-agent. If false, any existing connection to an agent is closed and the agent will not be used.
# File lib/net/ssh/authentication/key_manager.rb, line 147 147: def use_agent=(use_agent) 148: finish if !use_agent 149: @use_agent = use_agent 150: end
Toggles whether the ssh-agent will be used or not. If true, an attempt will be made to use the ssh-agent. If false, any existing connection to an agent is closed and the agent will not be used.
# File lib/net/ssh/authentication/key_manager.rb, line 147 147: def use_agent=(use_agent) 148: finish if !use_agent 149: @use_agent = use_agent 150: end